一、用layer-list实现,效果不是很好,边缘比较生硬:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <gradient android:centerX="0.5" android:centerY="0.5" android:endColor="@android:color/white" android:gradientRadius="55dp" android:startColor="@color/colorPrimary" android:type="radial"/> <corners android:radius="100dp"/> </shape> </item> <item android:bottom="5dp" android:right="5dp" android:left="5dp"> <shape> <!--<gradient--> <!--android:centerX="0.5"--> <!--android:centerY="0.5"--> <!--android:endColor="@android:color/white"--> <!--android:gradientRadius="100dp"--> <!--android:startColor="@android:color/holo_red_light"--> <!--android:type="radial"/>--> <solid android:color="@color/colorPrimary"/> <corners android:radius="100dp"/> </shape> </item> </layer-list>
二、采用自定义组件实现-重写onDraw方法:
@Override protected void onMeasure(int withMeasureSpec, int heightMeasureSpec) { super.onMeasure(withMeasureSpec, heightMeasureSpec); this.with = this.getMeasuredWidth(); this.height = this.getMeasuredHeight(); // this.shadowLeft = this.getPaddingLeft(); this.shadowTop = this.getPaddingTop(); this.shadowRight = this.getPaddingRight(); this.shadowBottom = this.getPaddingBottom(); // if (shadowBottom > shadowTop) { this.shadowDy = shadowTop / 3; } else { this.shadowDy = shadowTop / 3; } if (shadowLeft > shadowRight) { this.shadowDx = shadowRight / 3; } else { this.shadowDx = shadowLeft / 3; } } @Override protected void onDraw(Canvas canvas) { paint.setColor(backgroundColor); paint.setShadowLayer(shadowBottom, shadowDx, shadowDy, shadowColor); setLayerType(LAYER_TYPE_SOFTWARE, null); switch (drawType) { case CIRCLE: if (with > height) { canvas.drawCircle(with / 2, height / 2, with / 2 - (shadowTop + shadowBottom) * 2 / 3, paint); } else { canvas.drawCircle(with / 2, height / 2, height / 2 - (shadowTop + shadowBottom) * 2 / 3, paint); } break; case RECT: canvas.drawRect(shadowLeft, shadowBottom, with - shadowLeft, height - shadowBottom, paint); break; default: break; } super.onDraw(canvas);//放在最后执行,不能让添加的绘制的内容覆盖了原有的内容 }
ps:代码中的计算方法用于定义阴影范围,可以自己重写。主要是通过Paint类的
public void setShadowLayer(float radius, float dx, float dy, int shadowColor) { nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor); }
方法实现阴影,阴影颜色可以自己定义,不支持硬件加速,效果比第一种好。
三、Android 5.0以上 Material Design在组件中定义属性:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shadow_one" android:elevation="50dp" app:layout_constraintBottom_toTopOf="parent" app:layout_constraintLeft_toRightOf="parent" app:layout_constraintRight_toLeftOf="parent" app:layout_constraintTop_toBottomOf="parent"> <ImageView android:layout_width="120dp" android:layout_height="200dp" android:src="@mipmap/image"/> </LinearLayout>
ps:一般组件直接定义elevation属性即可有阴影效果,但是比如ImageView显示图片,不能直接设置该属性取得阴影效果,直接在外面再加个父布局,再在父布局上设置该属性即可。此种方法效果最好,但是阴影的颜色无法自定义,并且只支持Android 5.0以上。