Android 视图剪辑
Posted
技术标签:
【中文标题】Android 视图剪辑【英文标题】:Android View Clipping 【发布时间】:2011-07-31 06:14:49 【问题描述】:有没有办法在 android (Honeycomb) 中定义 ViewGroup 的剪辑区域?例如,我有一个带有圆角图像背景的 ListView。当我滚动浏览列表时,孩子们会伸出背景的角落——我希望他们夹在圆角内。
左图是它当前正在做的,右图是我想要的。
我在看ClipDrawable,不过好像只能用于进度条?
另外,我正在尝试在小部件中执行此操作。所以我不能使用自定义视图并覆盖 onDraw 进行遮罩。
谢谢!
【问题讨论】:
您找到解决方案了吗?我也试图在一个小部件中实现这一点。 【参考方案1】:尝试将 ViewGroup 子类化并覆盖 OnDraw 方法,如下所示,替换为 RADIUS_IN_PIXELS 的值:
@Override
protected void onDraw(Canvas canvas)
Path clipPath = new Path();
clipPath.addRoundRect(new RectF(canvas.getClipBounds()), RADIUS_IN_PIXELS, RADIUS_IN_PIXELS, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
...并创建一个像这样的自定义可绘制对象,称为“圆角”,替换为 YOUR_BACKGROUND_COLOR 和 RADIUS_IN_DP,确保将 DP 中矩形的圆角与您之前在 PX 中的剪切半径相匹配:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="RADIUS_IN_DP" />
<solid android:color="YOUR_BACKGROUND_COLOR"/>
</shape>
然后您可以在布局中使用该子类,添加行
android:background="@drawable/rounded"
android:clipChildren="true"
所有子元素都将剪辑到您在 OnDraw() 覆盖中指定的边界,并且将根据您的“圆形”可绘制对象添加背景。
【讨论】:
永远不要在onDraw
中实例化对象,这会导致延迟。
最初的问题是要求一些可以与 RemoteViews 一起使用的东西。【参考方案2】:
确保layout
具有圆角背景。
科特林
layout.outlineProvider = ViewOutlineProvider.BACKGROUND
layout.clipToOutline = true
Java
layout.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
layout.setClipToOutline(true);
【讨论】:
注意:需要 API 级别 21【参考方案3】:使用overridden onDraw(Canvas canvas)
创建自定义布局
致电canvas.clipRect(0, 0, mCanvasWidth, mCanvasHeight);
这将剪切所有超出布局边界的视图。
别忘了在构造函数中调用setWillNotDraw(false)
,这样你的onDraw就会执行
【讨论】:
【参考方案4】:这个怎么样:How to render an Android view to a bitmap,然后剪辑那个位图。
或者,另一个想法,使用FrameLayout
,将您的剪辑蒙版堆叠在您的视图组之上。剪辑蒙版将具有透明的中间、不透明的边框。
在这两种情况下,我想处理用户输入会很棘手......
【讨论】:
第一个选项不起作用,因为它在一个小部件中,因此它只能使用与 RemoteViews 兼容的视图。 第二个选项,因为它是一个主屏幕小部件,所以剪辑蒙版不可行。【参考方案5】:Path p = new Path()
// define your clipping path...
canvas.clipPath(p);
【讨论】:
【参考方案6】:如果您查看WhatsUp,您可以看到在联系人图片中有一个被圆角边框环绕的图像。 为此,我将 ImageView 放在具有圆形边框的 FrameLayout(FrameLayout 因为我在图片前面使用 ProgressBar 来通知加载[实际上不可见])中。图片是方形的,但要对其进行细化,您需要使用画布。
再看看这个link,它将解决您的问题;)
【讨论】:
【参考方案7】:也许你可以使用 Canvas.clipRegion 方法来剪辑到视图的差异。
【讨论】:
【参考方案8】:要添加@Marco 的答案,您还可以提供自定义View.outlineProvider
。我在使用 Google 较新的 MaterialCardView
时遇到了类似的问题。出于某种原因,该视图不会用圆角剪裁其子视图。子视图只会绘制在圆角的顶部。
科特林:
val cornerRadius = 16.dp()
materialCardView.apply
clipToOutline = true
outlineProvider = object : ViewOutlineProvider()
override fun getOutline(view: View?, outline: Outline?)
view?.apply
outline?.setRoundRect(0, 0, width, (height + cornerRadius).toInt(), cornerRadius)
【讨论】:
【参考方案9】:试试 android:clipToPadding。它会解决你的问题。
【讨论】:
以上是关于Android 视图剪辑的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Xamarin Android 中剪辑滚动视图的边界
Android实现一个progressBar,上面有两个剪辑textview