我有一个带有clipsChildren=false
属性的ConstraintLayout,因为某些子项需要在其边界之外绘制。但是,应该修剪其中一个孩子(视图A)(如果重要的话,我使用的是LinearGradient)。我无法将子视图移动到其他父视图,因为它受限于需要在边界外绘制的同级视图(视图B)。
如何强制只剪切视图A而又不剪切视图B?
我曾尝试在View A的onDraw期间使父项上的clipsChildren异常,但未成功。我也尝试过在画布上手动设置clipRect,但是即使没有更改,clipRect也被设置为View A的大小。
最佳答案
您将必须对应该剪切的视图进行剪切。为ConstraintLayout设置android:clipChildren="false"
。
编写一个自定义视图,以扩展您要裁剪的视图的类型。将draw()
方法更改为类似于以下内容的内容,以裁剪掉父视图之外的视图的任何部分。
在下图中,大红色正方形的四个角被剪切的文本视图占据。您可以在下图中看到全文视图的轮廓。顶部中间的紫色正方形是未修剪的子级。
这是使用的自定义视图:
class ClippedChild @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextView(context, attrs, defStyleAttr) {
override fun draw(canvas: Canvas) {
val parent = parent as ViewGroup
val clippingRect = Rect()
getDrawingRect(clippingRect)
if (left < 0) {
clippingRect.left = -left
}
if (top < 0) {
clippingRect.top = -top
}
if (right > parent.width) {
clippingRect.right = width - (right - parent.width)
}
if (bottom > parent.height) {
clippingRect.bottom = height - (bottom - parent.height)
}
canvas.save()
canvas.clipRect(clippingRect)
super.draw(canvas)
canvas.restore()
}
}
...以及布局的XML:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/innerLayout"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="#F44336"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<View
android:id="@+id/ViewA"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#9C27B0"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.example.myapplication.ClippedChild
android:id="@+id/ViewB1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#9C27B0"
android:text="top\n/start"
android:gravity="bottom|end"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="parent" />
<com.example.myapplication.ClippedChild
android:id="@+id/ViewB2"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="top\n/end"
android:gravity="bottom|start"
android:background="#2196F3"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<com.example.myapplication.ClippedChild
android:id="@+id/ViewB3"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#8BC34A"
android:text="bottom\n/end"
android:gravity="top|start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
<com.example.myapplication.ClippedChild
android:id="@+id/ViewB4"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FFEB3B"
android:text="bottom\n/start"
android:gravity="top|end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
<com.example.myapplication.ClippedChild
android:id="@+id/ViewB5"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FFEB3B"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>