自定义布局舍入其内容的角落 [英] Custom Layout that rounds the corners of its content

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

问题描述

我想创建一个通用的ViewGroup,然后可以在XML布局中重用圆的东西都放进去的角落。

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

下面是Java code:

 包圆;引入静态android.graphics.Path.Direction.CCW;
公共类RoundedView扩展的FrameLayout {
    私人浮动半径;
    私人路径path =新路径();
    私人RectF RECT =新RectF();    公共RoundedView(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
        this.radius = attrs.getAttributeFloatValue(NULL,corner_radius,0F);
    }    @覆盖
    保护无效的onDraw(帆布油画){
        INT savedState = canvas.save();
        浮W =的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(这是包括方形的ImageView与Facebook的个人主页画面中的FrameLayout):

这样就实现了一轮边界你做这样的事情:

  @覆盖
保护无效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(保存);
}

您可以实际创建任何复杂的路径:)

记住,你可以与你请相交在你喜欢的方式多次剪辑的OP操作调用clipPath多次。

请注意:我创造了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天全站免登陆