gpt4 book ai didi

android - 圆角内容的自定义布局

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:15:07 27 4
gpt4 key购买 nike

我想创建一个通用的 ViewGroup,然后可以在 XML 布局中重复使用它来圆角放置其中的任何内容。

出于某种原因,canvas.clipPath() 似乎没有效果。我做错了什么?

Java代码如下:

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);
}
}

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>

最佳答案

创建剪辑其子项的 ViewGroup 的正确方法是在 dispatchDraw(Canvas) 方法中执行此操作。

这是一个关于如何用圆圈剪辑 ViewGroup 的任何子级的示例:

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);
}

dispatchDraw 方法是调用来剪辑子项的方法。如果您的布局只是剪辑其子项,则无需 setWillNotDraw(false)

这张图片是用上面的代码得到的,我只是用facebook扩展了Facebook ProfilePictureView(这是一个FrameLayout,包括一个正方形ImageView个人资料图片):

circle clipping

因此,要实现圆形边框,您可以这样做:

@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);
}

round border clipping

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

请记住,您可以使用“Op”操作多次调用 clipPath,以便以您喜欢的方式与多个剪辑相交。

注意:我在 onSizeChanged 中创建了路径,因为在 onDraw 中这样做不利于性能。

注意 2:在不使用抗锯齿的情况下剪切路径 :/因此,如果您想要平滑的边界,则需要以其他方式进行。我现在不知道有什么方法可以让剪辑使用抗锯齿。

更新(大纲)

自 Android Lollipop (API 21) 起,高度和阴影可以应用于 View 。一个叫做Outline的新概念已介绍。这是一条路径,告诉框架要用于 compute the shadow 的 View 的形状。和其他东西(例如涟漪效应)。

View 的默认 Outline 是 View 大小的矩形,但可以很容易地制成椭圆形/圆形或圆角矩形。要定义自定义 Outline,您必须使用方法 setOutlineProvider()在 View 上,如果它是自定义 View ,您可能希望在构造函数中将其设置为自定义 ViewOutlineProvider 定义为自定义 View 的内部类。您可以使用您选择的 Path 定义您自己的 Outline 提供程序,只要它是 convex path。 (数学概念是指没有凹槽和孔洞的封闭路径,例如星形和齿轮形都不是凸形)。

您还可以使用方法 setClipToOutline(true)使大纲也剪辑(我认为这也适用于抗锯齿,有人可以在评论中确认/反驳吗?),但这仅支持非路径大纲。

祝你好运

关于android - 圆角内容的自定义布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33747775/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com