自定义布局舍入其内容的角落 [英] Custom Layout that rounds the corners of its content
问题描述
我想创建一个通用的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:机器人=http://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屋!