自定义布局这轮其内容的角落 [英] Custom Layout which rounds the corners of its content

查看:95
本文介绍了自定义布局这轮其内容的角落的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个通用的ViewGroup,然后可以在XML布局中重复使用圆的东西都投入它的角落。

由于某种原因, canvas.clipPath()似乎并没有产生效果。我究竟做错了什么?

下面是Java code:

 包绕行;

引入静态android.graphics.Path.Direction.CCW;
公共类RoundedView扩展的FrameLayout {
    私人浮动半径;
    私人路径路径=新路径();
    私人RectF RECT =新RectF();

    公共RoundedView(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
        this.radius = attrs.getAttributeFloatValue(NULL,corner_radius,0F);
    }

    @覆盖
    保护无效的OnDraw(帆布油画){
        INT savedState = canvas.save();
        浮瓦特=的getWidth();
        浮动H =的getHeight();
        path.reset();
        rect.set(0,0,W,H);
        path.addRoundRect(矩形,半径,半径,CCW);
        path.close();
        布尔调试= canvas.clipPath(路径);
        super.onDraw(画布);
        canvas.restoreToCount(savedState);
    }
}
 

在使用XML:

 < XML版本=1.0编码=UTF-8&GT?;
< rounded.RoundedView的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    corner_radius =40.0>
    < RelativeLayout的
        机器人:ID =@ + ID / RelativeLayout1
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent>
        ...
    < / RelativeLayout的>
< /rounded.RoundedView>
 

解决方案

正确的方法来创建剪辑的孩子的ViewGroup是做在dispatchDraw(Canvas)的方法。

这是你如何能夹了的ViewGroup的任何儿童圆一个例子:

 私人路径path =新路径();

@覆盖
保护无效onSizeChanged(INT W,INT小时,INT oldw,诠释oldh){
    super.onSizeChanged(W,H,oldw,oldh);

    //计算路径
    浮半宽度= W / 2F;
    浮halfHeight = H / 2F;
    浮动的centerX =半角;
    浮centerY = halfHeight;
    path.reset();
    path.addCircle(的centerX,centerY,Math.min(半角,halfHeight),Path.Direction.CW);
    path.close();

}

@覆盖
保护无效dispatchDraw(帆布油画){
    INT保存= canvas.save();
    canvas.clipPath(circlePath);
    super.dispatchDraw(画布);
    canvas.restoreToCount(保存);
}
 

在dispatchDraw方法是一个叫夹儿童。无需setWillNotDraw(假),如果你的布局只是限制它的孩子。

此图像与code获得上述情况,我只是扩展Facebook的ProfilePictureView(这是一个的FrameLayout包括方形的ImageView与Facebook的个人资料图片):

圈子剪辑

因此​​,要实现一个圆形边框,你做这样的事情:

  @覆盖
保护无效onSizeChanged(INT W,INT小时,INT oldw,诠释oldh){
    super.onSizeChanged(W,H,oldw,oldh);

    //计算路径
    path.reset();
    rect.set(0,0,W,H);
    path.addRoundRect(矩形,半径,半径,Path.Direction.CW);
    path.close();

}

@覆盖
保护无效dispatchDraw(帆布油画){
    INT保存= canvas.save();
    canvas.clipPath(路径);
    super.dispatchDraw(画布);
    canvas.restoreToCount(保存);
}
 

轮边裁剪

实际上,你可以创建任何复杂的路径:)

请记住,您可以拨打clipPath多次使用了OP操作,您请相交多个剪辑在你喜欢的方式。

请注意:我创造了onSizeChanged的路径,因为在OnDraw中这样做是不好的性能

注2:剪取一个路径是无抗锯齿完成的:/所以如果你想你需要做一些其他的方式边界光滑。我不知道有什么办法使剪辑使用抗锯齿现在的。

好运气

I would like to create a generic ViewGroup which can then be reused in XML layouts to round the corners of anything that is put into it.

For some reason canvas.clipPath() doesn't seem to have an effect. What am I doing wrong?

Here is the Java code:

package rounded;

import static android.graphics.Path.Direction.CCW;
public class RoundedView extends FrameLayout {
    private float radius;
    private Path path = new Path();
    private RectF rect = new RectF();

    public RoundedView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.radius = attrs.getAttributeFloatValue(null, "corner_radius", 0f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int savedState = canvas.save();
        float w = getWidth();
        float h = getHeight();
        path.reset();
        rect.set(0, 0, w, h);
        path.addRoundRect(rect, radius, radius, CCW);
        path.close();
        boolean debug = canvas.clipPath(path);
        super.onDraw(canvas);
        canvas.restoreToCount(savedState);
    }
}

Usage in XML:

<?xml version="1.0" encoding="utf-8"?>
<rounded.RoundedView   xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    corner_radius="40.0" >
    <RelativeLayout 
        android:id="@+id/RelativeLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        ...
    </RelativeLayout>
</rounded.RoundedView>

解决方案

The right way to create a ViewGroup that clip its children is to do it in the dispatchDraw(Canvas) method.

This is an example on how you can clip any children of a ViewGroup with a circle:

private Path path = new Path();

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    // compute the path
    float halfWidth = w / 2f;
    float halfHeight = h / 2f;
    float centerX = halfWidth;
    float centerY = halfHeight;
    path.reset();
    path.addCircle(centerX, centerY, Math.min(halfWidth, halfHeight), Path.Direction.CW);
    path.close();

}

@Override
protected void dispatchDraw(Canvas canvas) {
    int save = canvas.save();
    canvas.clipPath(circlePath);
    super.dispatchDraw(canvas);
    canvas.restoreToCount(save);
}

the dispatchDraw method is the one called to clip children. No need to setWillNotDraw(false) if your layout just clip its children.

This image is obtained with the code above, I just extended Facebook ProfilePictureView (which is a FrameLayout including a square ImageView with the facebook profile picture):

So to achieve a round border you do something like this:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    // compute the path
    path.reset();
    rect.set(0, 0, w, h);
    path.addRoundRect(rect, radius, radius, Path.Direction.CW);
    path.close();

}

@Override
protected void dispatchDraw(Canvas canvas) {
    int save = canvas.save();
    canvas.clipPath(path);
    super.dispatchDraw(canvas);
    canvas.restoreToCount(save);
}

You can actually create any complex path :)

Remember you can call clipPath multiple times with the "Op" operation you please to intersect multiple clipping in the way you like.

NOTE: I created the Path in the onSizeChanged because doing so in the onDraw is bad for performance.

NOTE2: clipping a Path is done without anti-aliasing :/ so if you want smooth borders you'll need to do it in some other way. I'm not aware of any way of making clipping use anti-aliasing right now.

Good luck

这篇关于自定义布局这轮其内容的角落的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆