前言

Android 中当子 View 的宽度/高度超过父 View 时,超出部分系统不会显示。

但有时 UI 设计人员对于自己的设计理念有着执着的追求。使用 clipChildren 属性可以满足需求,同时减少我们的代码量。


Andoid - clipChildren

clipChildren 的默认值为 true,即子 View 的宽度/高度超过父 View 时,超出部分系统不会显示。

当 clipChildren 值为 false 时,如果子 View 的宽度/高度超过父 View 时,超出部分系统不会显示。

然而事情并没有那么简单,在使用过程发现该属性不会生效。


小结

笔者做了七个实验,但肯定有哥们没耐心看完,总结下 clipChildren 生效的前提条件:

  1. clipChildren 声明在爷爷属性下即可。我当初写代码写急眼了,写了个递归,所有 ViewGroup 的 View 属性都设置了 clipChildren。没必要,只需要设置爷爷属性即可。
  2. 要保证爷爷有足够的空间显示超出的部分。
  3. 如果超出部分在爷爷的最右侧,可以给爷爷设置 paddingRight,同时给爷爷设置 clipToPadding=“false” 即可。可见最后一个示例。

另外 clipChildren 会导致超出部分无法响应点击事件,可以通过此篇文章试下,我就不测试了。


实验

写了一个简单的 Demo,记录各种无效的、有效的写法,防止后人踩坑。

图片 img_brand :


Android clipchild android clipchildren不生效_布局文件


clipChildren 设置在父 View 属性下

设置不会无效:一个 Activity,其布局文件设置如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:background="@color/red"
        android:clipChildren="false">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />
    </RelativeLayout>
</LinearLayout>

示例图如下:


Android clipchild android clipchildren不生效_xml_02


clipChildren 设置在爷爷属性下且爷爷比父 View 更宽

设置会生效:一个 Activity,其布局文件设置如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:background="@color/red"
        android:clipChildren="false">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />
    </RelativeLayout>
</LinearLayout>

示例图如下:


Android clipchild android clipchildren不生效_Android clipchild_03


clipChildren 设置在爷爷属性下且爷爷和父亲一样宽

设置不会生效:一个 Activity,其布局文件设置如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"  // 或者设置为 120 dp
    android:layout_height="wrap_content" // 或者设置为 120 dp
    android:gravity="center"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:background="@color/red"
        android:clipChildren="false">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />
    </RelativeLayout>
</LinearLayout>

示例图如下:


Android clipchild android clipchildren不生效_xml_02


clipChildren 设置在爷爷属性下且爷爷比父 View 更宽,但是只宽一点点

设置会生效,但是只显示了部分:一个 Activity,其布局文件设置如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="130dp" // 因为我设置了 gravity="center",要想完全显示,需要设置为 140 dp。
    android:layout_height="130dp"
    android:gravity="center"
    android:background="@color/blue"
    android:orientation="vertical">
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:background="@color/red"
        android:clipChildren="false">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />
    </RelativeLayout>
</LinearLayout>

示例图如下:


Android clipchild android clipchildren不生效_Android clipchild_05

因为我设置了 gravity=“center”,要想完全显示,需要设置其爷爷宽度为 140 dp。


clipChildren 设置在爷爷属性下且爷爷比父 View 更宽且 View 在最右侧

设置不会生效,因为爷爷的右侧没有显示的空间了。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="160dp"
    android:layout_height="160dp"
    android:background="@color/blue"
    android:clipChildren="false">

    <RelativeLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentRight="true"
        android:background="@color/red">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />

    </RelativeLayout>


</RelativeLayout>

示例图如下:

Android clipchild android clipchildren不生效_布局文件_06


clipChildren 设置在爷爷属性下且 爷爷比父 View 更宽且 View 在最右侧且爷爷右侧设置足够空间的 padding

设置不会生效:有的哥们说,既然最右侧没有空间显示,那么给爷爷设置一个 padding,那不就显示了吗?

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="160dp"
    android:layout_height="160dp"
    android:background="@color/blue"
    android:clipChildren="false"
    android:paddingRight="10dp">


    <RelativeLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentRight="true"
        android:background="@color/red">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />

    </RelativeLayout>


</RelativeLayout>

示例图如下:

Android clipchild android clipchildren不生效_xml_07


clipChildren 设置在爷爷属性下且爷爷比父 View 更宽且 View 在最右侧且爷爷右侧设置足够空间的 padding 且爷爷设置了 clipToPadding

设置会生效:上个例子的思路是对的,要想生效,还需要额外给爷爷设置一个属性 clipToPadding=“false”。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="160dp"
    android:layout_height="160dp"
    android:background="@color/blue"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:paddingRight="10dp">


    <RelativeLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentRight="true"
        android:background="@color/red">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="-10dp"
            android:src="@drawable/img_brand" />

    </RelativeLayout>
</RelativeLayout>

示例图如下:

Android clipchild android clipchildren不生效_布局文件_08