版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/I_do_can/article/details/78085530
IOS界面那么好看,不服气呀,android应该也是支持模糊阴影的, Paint.setShadowLayer官方文档
上一篇可以实现阴影,但是没有模糊效果,本文加上模糊效果
本文只是一个测试代码,属于抛砖引玉的,读者可以通过修改完善源码实现更好的效果
Paint.setShadowLayer是支持设置阴影的,不过有几个坑
- 需要关闭硬件加速,否则没有效果
- 阴影的颜色是需要带透明度的,否则没有效果
思路
- 比如你有一个 200dp*100dp的矩形空间需要显示边界阴影,先通过计算布局大小,给这个区域设置padding, 这个padding的目的是给阴影留下位置,阴影区域的大小是原空间的大小,给出的代码是一个ViewGroup,可以直接使用
- 效果还是可以的 (测试代码,只是右侧阴影和底部多一点阴影)
- 使用方法, 里面可以放任意的布局,是一个FrameLayout
<XXX.XXX.XXX.ShadowLayout2
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="200dp"
android:layout_height="100dp"
android:background="#6c6b6b"
android:gravity="center"
android:text="测试阴影"/>
</XXX.XXX.XXX.ShadowLayout2>
附上全部代码
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import com.benqu.wuta.R;
/**
* 控件阴影效果,只是最外层空间加阴影,不处理内部子控件
* 使用 Paint.setShadowLayer(),这是一个Layout,
* 思路: 比如你有一个 200dp*100dp的矩形空间需要显示边界阴影,先通过计算onLayout,给这个区域设置padding
* 这个padding的目的是给阴影留下位置,阴影区域的大小是原空间的大小
* 这里默认处理的是设置右边和下边的模糊阴影
* 当然,通过修改onDraw 里的代码,可以实现圆形边界阴影,圆角矩形边界阴影,Bitmap的边界阴影等等。。。
* Created by slack
* on 17/9/25 下午1:28
*/
public class ShadowLayout2 extends FrameLayout {
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF mRectF = new RectF();
/**
* 阴影的颜色, 需要带透明
*/
private int mShadowColor = Color.argb(128, 249, 94, 94);
/**
* 阴影的大小范围 radius越大越模糊,越小越清晰
*/
private float mShadowRadius = 10;
/**
* 阴影的宽度,比如底部的阴影,那就是底部阴影的高度
*/
private float mShadowWidth = 15;
/**
* 阴影 x 轴的偏移量, 计算padding时需要计算在内
*/
private float mShadowDx = 0;
/**
* 阴影 y 轴的偏移量,计算padding时需要计算在内,比如想底部的阴影多一些,这个设置值就可以了
*/
private float mShadowDy = 10;
public ShadowLayout2(Context context) {
this(context, null);
}
public ShadowLayout2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ShadowLayout2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
/**
* 为 ShadowLayout 设置 Padding 以为显示阴影留出空间
*/
private void resetShadowPadding() {
float rectLeft = 0;
float rectTop = 0;
float rectRight = 0;
float rectBottom = 0;
int paddingLeft = 0;
int paddingTop = 0;
int paddingRight = 0;
int paddingBottom = 0;
// todo 测试代码,待完善,暂时是右侧和底部的阴影
rectRight = this.getWidth() - mShadowWidth - mShadowDx;
paddingRight = (int) mShadowWidth + (int) mShadowDx;
rectBottom = this.getHeight() - mShadowWidth - mShadowDy;
paddingBottom = (int) mShadowWidth + (int) mShadowDy;
mRectF.left = rectLeft;
mRectF.top = rectTop;
mRectF.right = rectRight;
mRectF.bottom = rectBottom;
this.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
/**
* 决定View在ViewGroup中的位置 , 此处left ,top...是相对于父视图
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
resetShadowPadding();
}
/**
* 决定View的大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 如何绘制这个View, 真正绘制阴影的方法
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mRectF, mPaint);
}
/**
* 读取设置的阴影的属性
*
* @param attrs 从其中获取设置的值
*/
private void init(AttributeSet attrs) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // 关闭硬件加速,setShadowLayer 才会有效
this.setWillNotDraw(false); // 调用此方法后,才会执行 onDraw(Canvas) 方法
// todo 从AttributeSet获取设置的值
mPaint.setAntiAlias(true);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setShadowLayer(mShadowRadius, mShadowDx, mShadowDy, mShadowColor);
}
}