Drop shadow for custom imageView
To achieve this you should use CardView. So it will be something like:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#687199"
>
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="40dp"
app:cardElevation="16dp"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/test"
/>
</androidx.cardview.widget.CardView>
</FrameLayout>
You just need to play around with app:cardElevation
and app:cardCornerRadius
to get the shadow you need.
Also, keep in mind that the Android shadow system draws darker and longer shadows when objects are closer to the bottom of the screen.
How to add shadow around circular imageview
Here, I share my best practice to show a shadow effect to a circular image/resource with some details.
The above example image's icon is 56dp x 56dp and is cropped with a zoomed view so it may not look attractive but the results will show good on an actual device under the naked eye.
The above example is delivered by using:
- Some amount of elevation, to let shadow.
- Provide margin to the view almost double of elevation to fit the shadow.
- Ensure the parent view provides the space almost double of elevation to fit the shadow.
- Create and use an OutlineProvider to create the shadow.
Now here we begin with the code.
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/margin_14dp"> // Point no. 3
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img"
android:layout_width="@dimen/margin_56dp"
android:layout_height="@dimen/margin_56dp"
android:layout_margin="@dimen/margin_14dp" // Point no. 2
android:elevation="@dimen/margin_8dp" // Point no. 1
android:src="@drawable/ic_bell" />
</FrameLayout>
Let's proceed to point no. 4, here is the OutlineProvider class for a Circular Outline.
import android.graphics.Outline;
import android.view.View;
import android.view.ViewOutlineProvider;
public class CircularOutlineProvider extends ViewOutlineProvider {
@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), (view.getWidth() / 2F));
}
}
We left to use the OutlineProvider in our Java/Kotlin class to do the magic at runtime.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
findViewById(R.id.img).setOutlineProvider(new CircularOutlineProvider());
End of Magic Session!
For more experience and enhance details, please read the official article.
Custom ImageView with drop shadow
Okay, I don't foresee any more answers on this one, so what I ended up going with for now is just a solution for rectangular images. I've used the following NinePatch:
along with the appropriate padding in XML:
<ImageView
android:id="@+id/image_test"
android:background="@drawable/drop_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6px"
android:paddingTop="4px"
android:paddingRight="8px"
android:paddingBottom="9px"
android:src="@drawable/pic1"
/>
to get a fairly good result:
Not ideal, but it'll do.
How to set shadow effect on ImageView
Sadly there is no straight-forward way to get this working for android. But there are some options that you can try.
Option #1There are several unsupported drawing operations for hardware accelerated layers, that includes SetShadowLayer
for non-text views.
So, in order to get the SetShadowLayer
render for a non-text view, you need to set the LayerType
rendering as SOFTWARE
as explained in this solution.
SetLayerType(LayerType.Software, null);
But the major drawback of course is that it can be a performance issue.
Option #2Second option is to use an radial gradient to emulate the shadow. I had implemented it as a renderer (but you should be able to implement it as an effect too). The result of course is not as great as a blurred shadow effect. You will also have to set the right Padding
to let some space for the shadow to render, and be visible under the image.
protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
{
try
{
var nativeCtrl = Control;
var formsElement = Element;
if (nativeCtrl == null || formsElement == null)
{
base.DispatchDraw(canvas);
return;
}
//convert from logical to native metrics if need be
var shadowDistanceX = 10f;
var shadowDistanceY = 10f;
var shadowRadius = 5f;
var shadowOpacity = .5f;
var shadowColor = Color.Black;
var cornerRadius = 0.2f;
var bounds = formsElement.Bounds;
var left = shadowDistanceX;
var top = shadowDistanceY;
var right = Width + shadowDistanceX;
var bottom = Height + shadowDistanceY;
var rect = new Android.Graphics.RectF(left, top, right, bottom);
canvas.Save();
using (var paint = new Android.Graphics.Paint { AntiAlias = true })
{
paint.SetStyle(Android.Graphics.Paint.Style.Fill);
var nativeShadowColor = shadowColor.MultiplyAlpha(shadowOpacity * 0.75f).ToAndroid();
paint.Color = nativeShadowColor;
var gradient = new Android.Graphics.RadialGradient(
0.5f, 0.5f,
shadowRadius,
shadowColor.ToAndroid(),
nativeShadowColor,
Android.Graphics.Shader.TileMode.Clamp
);
paint.SetShader(gradient);
//convert from logical to native metrics if need be
var nativeRadius = cornerRadius;
canvas.DrawRoundRect(rect, nativeRadius, nativeRadius, paint);
var clipPath = new Android.Graphics.Path();
clipPath.AddRoundRect(new Android.Graphics.RectF(0f, 0f, Width, Height), nativeRadius, nativeRadius, Android.Graphics.Path.Direction.Cw);
canvas.ClipPath(clipPath);
}
canvas.Restore();
}
catch (Exception ex)
{
//log exception
}
base.DispatchDraw(canvas);
}
Option #3Another option would be to use SkiaSharp for Forms - i.e. create a container (or layered) view that renders the shadow around the child view (image). You can either have SkiaSharp render the image too, or embed a XF based image control inside the layout.
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args)
{
var imgInfo = args.Info;
var surface = args.Surface;
var canvas = surface.Canvas;
var drawBounds = imgInfo.Rect;
var path = new SKPath();
var cornerRadius = 5f;
if (cornerRadius > 0)
{
path.AddRoundedRect(drawBounds, cornerRadius, cornerRadius);
}
else
{
path.AddRect(drawBounds);
}
using (var paint = new SKPaint()
{
ImageFilter = SKImageFilter.CreateDropShadow(
offsetX,
offsetY,
blurX,
blurY,
color,
SKDropShadowImageFilterShadowMode.DrawShadowOnly),
})
{
canvas.DrawPath(path, paint);
}
}
How can we set shadow effect for View in Android?
You can create your own "shadow view"
<View
android:id="@+id/shadow_view"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="bottom"
android:background="@drawable/shadow_gradient" />
and add the shadow drawable to it:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="@android:color/transparent"
android:startColor="#8f000000" />
</shape>
The height is up to you, to experiment and see what works best for you as is the angle and start colour of the drawable. You just need to align this view layout to any view layout you want to have a shadow and you are good.
Related Topics
How to Set Datetimepicker to Month and Year Only Format
How to Loop Through Each and Every Row, Put Value in Gridview Column Cells
How to Round Up the Time to the Nearest X Minutes
C# Json Serialization of Dictionary into {Key:Value, ...} Instead of {Key:Key, Value:Value, ...}
String to Decimal With 2 Decimal Places Always
Entity Framework Migrations Renaming Tables and Columns
Angular Post Request Received in Net Core API as Null
System.Collections.Generic.List Does Not Contain a Definition for 'Select'
C# How to Check If a Url Exists/Is Valid
Linq Multiple Group by in a List<T> Then Convert to List<T>
Deserialize Json in C# - How to Handle Null Return Values
How to Ignore First Two Columns of CSV File
How to Generate Getters and Setters in Visual Studio