android单边阴影、多边阴影和圆角阴影

您所在的位置:网站首页 边框设置圆角和直角 android单边阴影、多边阴影和圆角阴影

android单边阴影、多边阴影和圆角阴影

2023-08-09 02:00| 来源: 网络整理| 查看: 265

       现在好多设计都喜欢用阴影,各种颜色、各种图形的阴影做起来费时费力,而官方的cardview不支持设置阴影颜色,阴影位置也是更拟物化的z轴阴影,不能符合设计的要求,因此专门写了一个工具。

       GitHub地址:https://github.com/maxiaoyi/FpShadowLayout

      用法:implementation 'com.mxy.fpshadowlayout:fpshadowlayout:0.0.1'

       效果如图:

       核心实现是用LinearGradient,自定义viewGroup,设置阴影长度对应的padding,画出阴影。

       首先,来看一下LinearGradient的用法:

int[] colors = {Color.parseColor("#ff0000"), Color.parseColor("#00ffffff")}; float[] floats = new float[]{0f, 1.0f}; LinearGradient gradient = new LinearGradient(0,0,100,0,colors, floats, Shader.TileMode.CLAMP); paint.setShader(gradient); RectF rectF = new RectF(0, 0, 100, 50); canvas.drawRect(rectF, paint);

colors是一组颜色数组,代表颜色从哪一种过渡到另外一种,可是两个或者三个颜色。floats是位置权重的数组,代表每一种颜色所占位置的权重,同样可以是两个或者三个,数量要和colors对应。

lineargradient的构造方法中,重点说一下前面四个参数,这四个参数实际上是定义了渐变的方向,x如果从0到n,y是从0到0的话,表示渐变在x轴上从左往右平铺。代码

new LinearGradient(0,0,100,0,colors, floats, Shader.TileMode.CLAMP);

具体效果:

接下来变一下,x从n到0,y不变:

可以看到颜色反转了,变成从右往左平铺。接下来x保持都是0,y从0到n:

此时颜色变成了y轴上从上往下平铺,同理,y如果从n到0的话,颜色也会出现反转,从下往上平铺。所以,改变x和y我们就可以实现渐变从不同方向开始。

在上面代码中RectF rectF = new RectF(0, 0, 100, 50),画了一个矩形区域,new LinearGradient(0,0,100,0,colors, floats, Shader.TileMode.CLAMP),这句代码表示颜色渐变的区域,此时我们把渐变x=100,变成x=50,为了区分明显,我加了一个矩形边框

LinearGradient gradient = new LinearGradient(0,0,50,0,colors, floats, Shader.TileMode.CLAMP); paint.setShader(gradient); RectF rectF = new RectF(0, 0, 100, 50); canvas.drawRect(rectF, paint); Paint paint1 = new Paint(); paint1.setColor(Color.GREEN); paint1.setStyle(Paint.Style.STROKE); paint1.setStrokeWidth(2); canvas.drawRect(rectF,paint1);

为了区别明显,我把colors中第二个颜色白色改成黑色,int[] colors = {Color.parseColor("#ff0000"), Color.parseColor("#00000000")};

效果对比如下(左边是x=100,右边是x=50)

可以看出渐变的区域之外,view还是保持原来的样子不变,至此我们可以看出view所在区域和渐变区域的关系。接下来就可以进入正题,怎么去画出view的阴影。

首先,关闭硬件加速,setLayerType(View.LAYER_TYPE_SOFTWARE, null)设置view的阴影所在边的padding:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { float effect = mShadowRadius; int paddingLeft = 0; int paddingTop = 0; int paddingRight = 0; int paddingBottom = 0; if ((mShadowSide & LEFT) == LEFT) { paddingLeft = (int) effect; } if ((mShadowSide & TOP) == TOP) { paddingTop = (int) effect; } if ((mShadowSide & RIGHT) == RIGHT) { paddingRight = (int) effect; } if ((mShadowSide & BOTTOM) == BOTTOM) { paddingBottom = (int) effect; } this.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); super.onMeasure(widthMeasureSpec, heightMeasureSpec); }

获取属性值:

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.Fp_ShadowLayout); if (typedArray != null) { mShadowColor = typedArray.getColor(R.styleable.Fp_ShadowLayout_fp_shadowColor, getContext().getResources().getColor(android.R.color.black)); mShadowRadius = typedArray.getDimension(R.styleable.Fp_ShadowLayout_fp_shadowRadius, dip2px(0)); mRoundCornerRadius = typedArray.getDimension(R.styleable.Fp_ShadowLayout_fp_shadowRoundRadius, dip2px(0)); mShadowSide = typedArray.getInt(R.styleable.Fp_ShadowLayout_fp_shadowSide, ALL); mShadowShape = typedArray.getInt(R.styleable.Fp_ShadowLayout_fp_shadowShape, SHAPE_RECTANGLE); mCornerPosition = typedArray.getInt(R.styleable.Fp_ShadowLayout_fp_round_corner, CORNER_ALL); typedArray.recycle(); }

其中有阴影的颜色,阴影的长度,圆角的大小,阴影所在的边,圆角所在的边,是矩形还是圆角矩形。接下来就要在ondraw里面画出阴影,如果是矩形的话部分代码如下:

if ((mShadowSide & LEFT) == LEFT && (mShadowSide & TOP) != TOP && (mShadowSide & RIGHT) != RIGHT && (mShadowSide & BOTTOM) != BOTTOM) { //画左边阴影 drawRectLinearGradient(canvas, mShadowRadius, 0, 0, 0, colors, floats, Shader.TileMode.CLAMP, new RectF(0, 0, mShadowRadius, mViewHeight)); } else if ((mShadowSide & LEFT) != LEFT && (mShadowSide & TOP) == TOP && (mShadowSide & RIGHT) != RIGHT && (mShadowSide & BOTTOM) != BOTTOM) { //画上边阴影 drawRectLinearGradient(canvas, 0, mShadowRadius, 0, 0, colors, floats, Shader.TileMode.CLAMP, new RectF(0, 0, mViewWidth, mShadowRadius)); } else if ((mShadowSide & LEFT) != LEFT && (mShadowSide & TOP) != TOP && (mShadowSide & RIGHT) == RIGHT && (mShadowSide & BOTTOM) != BOTTOM) { //画右边阴影 drawRectLinearGradient(canvas, mViewWidth - mShadowRadius, 0, mViewWidth, 0, colors, floats, Shader.TileMode.CLAMP, new RectF(mViewWidth - mShadowRadius, 0, mViewWidth, mViewHeight)); } else if ((mShadowSide & LEFT) != LEFT && (mShadowSide & TOP) != TOP && (mShadowSide & RIGHT) != RIGHT && (mShadowSide & BOTTOM) == BOTTOM) { //画下边阴影 drawRectLinearGradient(canvas, 0, mViewHeight - mShadowRadius, 0, mViewHeight, colors, floats, Shader.TileMode.CLAMP, new RectF(0, mViewHeight - mShadowRadius, mViewWidth, mViewHeight)); }

上面代码只是只有一条边有阴影时的情况,还可能有两条、三条和四条边有阴影,所以需要做出各种判断组合,比如:上下,上左,左右下等等组合,其中关键一点是画出两条边相交时角落处的阴影怎么去画:

从上图可以看出,角落处是一个从180度开始,扫过90度的四分之一弧度的半圆,此时就要用到RadialGradient了:

RadialGradient linearGradient = new RadialGradient(centerX, centerY, radius, colors, positions, tile); mPaint.setShader(linearGradient); canvas.drawArc(rectF, startAngle, sweepAngle, true, mPaint);

可以看出RadialGradient和LinearGradient差不多,最主要的是圆心和半径,其他的参数和LinearGradient一样。圆心就是角落顶点的坐标,半径就是阴影的半径,然后用canvas的drawArc画出这段圆弧。

接下来看一下如果是圆角矩形的话怎么去画:

从上图可以看出,画圆角处的阴影时我们的半径为:阴影长度+圆角的半径,但此时画这个圆弧时,阴影的渐变是从圆心向外扩散,也就是说从圆心到矩形圆角的这段(上图左上角圆心到黑色圆弧区域)区域会被遮挡。解决办法就是这部分区域用无色去填充,原来的colors有两个颜色,现在变成三个,对应的positions也要改成三个值:

private float[] creatTwoPositionFloat() { float[] floats = new float[]{0f, 1f}; return floats; } private float[] creatThreePositionFloat() { float[] floats = new float[]{mRoundCornerRadius / (mShadowRadius + mRoundCornerRadius), mRoundCornerRadius / (mShadowRadius + mRoundCornerRadius), 1f}; return floats; } private int[] creatTwoPositionColor() { int[] colors = new int[]{mShadowColor, 0x00ffffff}; return colors; } private int[] creatThreePositionColor() { int[] colors = new int[]{0x00ffffff, mShadowColor, 0x00ffffff}; return colors; }

同时要关注左下角,这里的圆弧和左上角的又不一样,这里需要一个以下图点A(圆角半径+阴影半径,viewHeight-圆角半径)为圆心,圆角半径+阴影半径为半径画一个圆,同时这个圆的区域限定如下图左下角的绿色矩形(长度=2*(圆角半径+阴影半径),高度=2*圆角半径)所示:

将上图中的左边阴影换到下边,即上下边有阴影,再来看左下角,下图中紫色的区域就是半圆角的区域:

综上所看,以左下角为例,一个圆角有四种画法:圆角朝上(阴影在左边),圆角朝下(阴影在下边),90度的圆角(圆角所连的两条边都有阴影),顶角为直角的圆角(两条边的夹角没有圆角)

至此,四个角的画法和单边、多边和多角组合到一起,差不多200多种组合,才能完工。。。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3