Android的clipToPadding与clipChildren

1,630 阅读2分钟

背景

clipToPadding与clipChildren是有用的两个设置属性,常在RecyclerView、ViewPager等场景中使用,下面图文介绍两个参数具体的意义。

clipToPadding

在viewGroup中使用,默认值为true,即viewGroup的padding部分是看不到子view的内容的。先上动图,红色是子view,蓝色是view的父容器,activity的白底是爷爷容器。

SVID_20220126_232427_1.gif

点击按钮,开始动画,子view的宽高同时都变大300,使其大小尺寸超过父容器,但是由于父容器设置了paddingEnd,导致子view不能延展到父容器的padding部分。下面的java代码(主要是点击按钮开始动效改变子view的宽高)以及xml布局。

protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_test);
   final View childView = findViewById(R.id.view_child);
   Button animatorBtn = findViewById(R.id.btn_change_size);
   animatorBtn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
         // 点击按钮,开始动画,子view的宽高都变大300,使其大小超过父容器
         int width = childView.getLayoutParams().width;
         ValueAnimator animator = ValueAnimator.ofFloat(width, width + 300);
         animator.setDuration(2000);
         animator.removeAllUpdateListeners();
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
               ViewGroup.LayoutParams layoutParams = childView.getLayoutParams();
               Float animatedValue = (Float) animation.getAnimatedValue();
               layoutParams.width = animatedValue.intValue();
               layoutParams.height = animatedValue.intValue();
               childView.setLayoutParams(layoutParams);
            }
         });
         animator.start();
      }
   });
}
<?xml version="1.0" encoding="utf-8"?>
<!-- 爷爷容器 -->
<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"
    tools:context=".TestActivity">
    
    <!-- 父容器ViewGroup -->
    <LinearLayout
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:background="@android:color/holo_blue_light"
        android:paddingEnd="20dp">
        
        <!-- 子view -->
        <View
            android:id="@+id/view_child"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_marginStart="10dp"
            android:layout_marginTop="10dp"
            android:background="@android:color/holo_red_light" />
    </LinearLayout>

    <!-- 点击按钮开始动效 -->
    <Button
        android:id="@+id/btn_change_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="change size" />
</RelativeLayout>

如下是在父容器LinearLayout中增加了属性android:clipToPadding="false" 的效果,可以看到子view已经可以延伸到父容器的padding区域了: SVID_20220126_234021_1.gif

clipChildren

在上一个动图中,子view最终右边和底边都与父容器平齐,实际上子view的尺寸大小是超过父容器的,如果想让子view展示超出父容器之外,就需要用到clipChildren,该属性默认值也是为true,注意该属性值不是设置在父容器上,而是要设置在爷爷容器上,即上面xml中的RelativeLayout,通过设置 android:clipChildren="false" 就有了如下的效果,子view超出了父容器的限制,成功展示在父容器之外: SVID_20220126_230009_1.gif

需要注意,如果子view的父容器设置了padding,但没有设置android:clipToPadding="false",这时即使爷爷容器设置了android:clipChildren="false",子view的效果也不会超出父容器,效果跟第一个动图一样(可以想象一个view都不能展示在父容器的padding区域自然更不可能直接展示到父容器之外的爷爷容器去)。