Android 子布局绘制超出父布局期望,对子布局进行裁切

这篇文章的题目不知道该咋起,就暂且这样吧。

这篇博文解决的问题:

这里的布局情况是一个LinearLayout,里头放了两TextView,关键在于,LinearLayout的背景是一个带圆角的,而TextView没有圆角效果是一个直角,所以在头和尾的这两TextView的直角会形成超出父布局期望的范围这种现象。

实际期望的效果:

期望的效果应该是子布局根据父布局背景的圆角大小进行调整,把TextView直角突出的部分给裁剪掉。

要实现这个效果其实很简单,只需要自定义父布局,让父布局根据自己的圆角大小,调整画布,让子View的绘制不要超出画布范围即可。

贴出代码:

public class AutoFixFrameLayout extends LinearLayout {

    private int mRadius = 0;

    public AutoFixFrameLayout(Context context) {
        super(context);
    }

    public AutoFixFrameLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoFixFrameLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //or in here
    }


    public void setRadius(int radius) {
        mRadius = radius;
        invalidate();
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        //关键代码在这里
        Path path = new Path();
        RectF rectF = new RectF();
        rectF.set(0, 0, getWidth(), getHeight());
        path.addRoundRect(rectF, dp2px(getContext(), mRadius), dp2px(getContext(), mRadius), Path.Direction.CW);
        canvas.clipPath(path);
        //要在调用super.dispatchDraw之前设置裁切范围噢
        super.dispatchDraw(canvas);
    }

    private int dp2px(Context context, int dp) {
        return (int) (context.getResources().getDisplayMetrics().density * dp + 0.5f);
    }
}

这个父布局的关键在于,dispatchDraw,在这个方法内,设置了canvas的裁切范围,注意 圆角大小要自己根据实际情况设置,为Path添加了一个圆角RectF,并且设置canvas裁切范围,如此就能实现上图所示的效果了。

再来说说为啥在dispatchDraw设置裁切范围就能对子View生效。

ViewGroup.java

protected void dispatchDraw(Canvas canvas) {
    //...省略若干无关代码
    drawChild(canvas, transientChild, drawingTime);
    ....
}

//child.draw 即调用到子View的draw方法中
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
}
View.java
public void draw(Canvas canvas) {
    //省略若干无关代码...
    onDraw(canvas);
    ....
     
}

结论:子View拿到的canvas实际上是在ViewGroup的dispatchDraw当中传过来的,那么在dispatchDraw方法内设置canvas的裁切,限定了画布范围,子View的绘制自然就被拿捏了。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值