Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable clip on single child of clipsChildren=false parent

I have a ConstraintLayout with clipsChildren=false property, since some of the children need to draw outside of their bounds. One of the children (View A) however should be clipped (I'm using a LinearGradient, if that matters). I cannot move the child view to a different parent, as it is constrained to a sibling view (View B) that needs to draw outside the bounds.

How can I force just View A to be clipped, without also clipping View B?

I have attempted disablind clipsChildren on parent during onDraw in View A, but to no success. I've also tried manually setting clipRect on canvas, but even without changes the clipRect is being set to the size of View A.

like image 594
user1126068 Avatar asked Dec 14 '25 05:12

user1126068


1 Answers

You will have to do your own clipping on the view that should be clipped. For the ConstraintLayout set android:clipChildren="false".

Write a custom view that extends the type of view that you want to clip. Change the draw() method to something like the following to clip any part of the view that falls outside of the parent.

In the image below, the four corners of the large red square are occupied with text views that are clipped. You can see the outline of the full text views in the following image. The top center purple square is child that is not clipped.

enter image description here

Here is the custom view that is used:

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

...and the XML for the layout:

 <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>
like image 99
Cheticamp Avatar answered Dec 16 '25 22:12

Cheticamp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!