首页 > 解决方案 > 在 clipsChildren=false 父级的单个子级上启用剪辑

问题描述

我有一个带clipsChildren=false属性的 ConstraintLayout,因为有些孩子需要在他们的范围之外绘制。然而,其中一个孩子(视图 A)应该被剪裁(如果这很重要,我正在使用 LinearGradient)。我无法将子视图移动到不同的父视图,因为它受限于需要在边界之外绘制的同级视图(视图 B)。

如何强制只剪裁视图 A,而不剪裁视图 B?

在视图 A 的 onDraw 期间,我尝试在父级上禁用 clipsChildren,但没有成功。我也尝试在画布上手动设置 clipRect,但即使没有更改,clipRect 也被设置为视图 A 的大小。

标签: androidcanvasandroid-constraintlayout

解决方案


您将不得不对应该被剪裁的视图进行自己的剪裁。对于ConstraintLayoutandroid: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>

推荐阅读