36

In my application I am trying to move images using animation. When I try to animate the image is cutting even though I use clipChildren false in every xml block

    <RelativeLayout
        android:id="@+id/baselayout"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/imageView1"
        android:clipChildren="false"
        android:clipToPadding="false" >
Fattie
  • 27,874
  • 70
  • 431
  • 719
Vamshi
  • 1,495
  • 1
  • 15
  • 31
  • For anyone googling here pls note that roflharrison has solved the problem BUT there is an error in the code example given by roflharrison. Correct code: https://stackoverflow.com/a/53654808/294884 – Fattie Apr 14 '21 at 12:19

6 Answers6

38

One of the parents of your RelativeLayout might be clipping children (sometimes compatibility libraries add a mystery ViewGroup such as NoSaveStateFrameLayout for example). I've used something like this in the past with success to disable clip on all parents of a view:

public void disableClipOnParents(View v) {
    if (v.getParent() == null) {
        return;
    }

    if (v instanceof ViewGroup) {
        ((ViewGroup) v).setClipChildren(false);
    }

    if (v.getParent() instanceof View) {
        disableClipOnParents((View) v.getParent());
    }
}
Community
  • 1
  • 1
roflharrison
  • 2,300
  • 23
  • 26
  • 1
    It worked for me, thanks for the answer! Apparently some views are added when you include a layout and that was causing the problem for me. – shalafi Aug 06 '14 at 12:23
  • 2
    UPDATE: i was using support library 21.0.3. updating to 22.0.0 fixed this problem for me! – Sam Apr 02 '15 at 13:48
  • It worked for me. But getting one issue. Condition is : Suppose there is RelativeLayout_1 parent of ListView_1. ListView_1 is parent of RelativeLayout_2. RelativeLayout_2 parent of ImageView_1. I need to animate the child "ImageView_1" and move it outside the parent, than I used your methods. It worked fine, but while scrolling the list, ListView_1 also comes over RelativeLayout_1. Is it possible to apply clipping only for one child ? – Shanki Bansal May 20 '15 at 17:17
  • for future readers: programmatically setting might not work for animating views that are leaving dialog fragment on android `4.x` devices. But setting `clipChildren` and `clipToPadding` for all `ViewGroup`s via XML + invalidate `fragment root view` on `onAnimationUpdate` event make the trick. For some reasons, that i really don't understans, programmatically setting clip settings + invalidating root view on 4x devices `does not work`. On 5x devices it works without XML and manually invalidating. – ashakirov Jan 19 '16 at 10:50
  • Worked for me !! Just wondering if this is an obvious thing to know? (Since I didn't knew this for coming here :-/ ) – Yash May 12 '17 at 08:44
  • 2
    It's not obvious that the system is wrapping your views into helper ViewGroup's. If you want to see it in action open the Layout Inspector for a case where you are experiencing `clipChildren="false"` not working and you'll probably find a mystery ViewGroup in your hierarchy. – roflharrison May 22 '17 at 06:54
  • @roflharrison thanks so much for the solution BUT your code has two minor errors which will stop it working in some cases. KehuiLi answer shows the problem and fix. – Fattie Apr 14 '21 at 12:13
22

I know its late, but this is the simplest complete answer:

just put on every layout :

    android:clipChildren="false"
    android:clipToPadding="false"

Note @roflharrison mentioned: this won't work in the cases where the operating system wraps/injects your view in ViewGroup's that's aren't in your layout

mhdjazmati
  • 4,152
  • 1
  • 26
  • 37
11

The final reason is "RelativeLayout". So to solve it, don't use RelativeLayout as your Larger-than-parent control's parent. FrameLayout instead, like:

<!-- it's ok as grand parent -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false">

    <!-- parent must not be a RelativeLayout -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="38dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="9dp">

        <!-- Your Larger-than-parent View -->
        <View
            android:layout_width="56dp"
            android:layout_height="138dp"
            android:layout_gravity="center"
            android:background="@android:color/black" />

    </FrameLayout>

</RelativeLayout>
Xavier.S
  • 319
  • 2
  • 7
5

The idea of @roflharrison is quite good, however, the codes has some problem: Here we disable clipChildren recursively, but when we reached the root view, it's v.getParents() would be null, the method returns immediately, and its ClipChildren attribute won't be disabled.

What's more, for the following line:

if (v.getParent() instanceof View)

?? Shouldn't the parent of the view be a ViewGroup? And shouldn't we disable ViewGroup's clip attributes, not View's? So I change the code to the following, and it worked quite well:

public void disableClipOnParents(View v) {
    if (v == null) {
        return;
    }
    if (v instanceof ViewGroup) {
        ((ViewGroup) v).setClipChildren(false);
    }
    disableClipOnParents((View) v.getParent());
}
Kehui Li
  • 301
  • 2
  • 3
  • THE CORRECT ANSWER THANKS !! – Fattie Apr 14 '21 at 12:15
  • 1
    Note that you may well also wish to set `setClipToPadding(false)` . – Fattie Apr 14 '21 at 12:27
  • This also won't work on all devices. You should check `v.getParent() instanceof View` before casting it to `View`. You may end up with `ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View` or something similar. There are multiple cases when this can happen ([see search results](https://stackoverflow.com/search?q=android.view.ViewRootImpl+cannot+be+cast+to+android.view.View)). – Michal Vician Dec 17 '21 at 20:11
1

Hi~ if your layout includes "paddingXXX" tags, you can remove them and try again. it's work for me~

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:gravity="center_vertical"
    android:padding="8dp"
    android:orientation="horizontal">

code above will clip childView and next will not:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:gravity="center_vertical"
    android:orientation="horizontal">
Draken
  • 3,134
  • 13
  • 34
  • 54
Yun.Lu
  • 61
  • 5
0

In my case clipChildren=false didn't work, because I had also set clipToOutline = true on the parent in my code. This attribute caused children to be clipped in the parent's outline which in my case was a contour of the parent's background. Seems like clipToOutline has higher priority than clipChildren=false.

If clipChildren=false does not work for you, please make sure you don't have clipToOutline=true set in the code.

Milszym
  • 306
  • 1
  • 3
  • 8