Android clipChildren与clipToPadding使用以及简单ViewPager自定义切换效果

首先看看我们要实现的效果:
这里写图片描述
主要希望实现两个效果:
1. 滚动的文本框在TITLE“下方“穿过,但初始时,文本框是有TITLE的高度的”paddingTop”的;
2. 下方第三个图标的高度超出其所在的父控件高度。
先上布局文件:

<?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:background="#f6f6f6"
              android:clipChildren="false"
              android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            android:paddingTop="50dp">

            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n很长很长的文本\n"
                android:textSize="50sp"/>
        </ScrollView>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#a00058f1"
            android:gravity="center"
            android:text="TITLE"
            android:textColor="#ffffffff"
            android:textSize="20sp"/>
    </FrameLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_gravity="bottom"
        android:background="#fff"
        android:elevation="12dp"
        android:orientation="horizontal">

        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher"/>

        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher"/>

        <ImageView
            android:id="@+id/iv"
            android:layout_width="0dp"
            android:layout_height="180dp"
            android:layout_gravity="bottom"
            android:layout_weight="1"
            android:scaleType="fitXY"
            android:src="@mipmap/ic_launcher"/>

        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher"/>

        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@mipmap/ic_launcher"/>
    </LinearLayout>

</LinearLayout>

首先先引入两个属性:
1. android:clipChildren – 是否限制子视图在其范围内,简单理解,就是其子view是否可以在超出自身原本的范围绘制“突出”的部分,默认值为true。需要注意的是,突出的部分是没有响应事件的,如下图:
这里写图片描述
第三个图标虽然超出了LinearLayout的高度范围,但是点击超出的部分,是不会响应imageview的点击事件的。此属性一般需要在根节点设置。
2. android:clipToPadding – 这个就能比较简单理解了,是否允许子view在padding的范围中绘制,默认值为true。一般设置此属性为false,以实现如上图所示的,ListView、RecycleView、ScrollView的“初始padding”的效果。


clipToPadding和clipChildren 还可以配合Viewpager,实现各种酷炫的切换效果,如下面的例子:
这里写图片描述
布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:id="@+id/fl"
    android:clickable="true"
    android:clipChildren="false"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_gravity="center"
        android:layout_marginLeft="60dp"
        android:layout_marginRight="60dp"
        android:background="#f6f6f6"
        android:clipToPadding="false"
        android:orientation="vertical"
        android:overScrollMode="never"
        android:paddingBottom="20dp"
        android:paddingTop="20dp"/>
</FrameLayout>

中间灰色的部分是ViewPager,要实现此效果,需要ViewPager的父容器设置clipChildren为false以及自身设置clipToPadding为false,同时设置左右margin,以显示前后两页,同时需在代码中设置:

        vp.setPageMargin(30);  // 设置页间的距离
        vp.setOffscreenPageLimit(3); // 因为要同时显示三页,因此此处需要将默认的缓存页面从1变为3
        vp.setPageTransformer(false, new PageAnimation()); // 自定义切换效果
        vp.setAdapter(new Adapter());

其中,setPageTransformer是用来给ViewPager设置切换效果的,主要是重写

 /**
         * page - Apply the transformation to this page
         * position - Position of page relative to the current front-and-center position of the pager. 0 is front and center. 1 is one full page position to the right, and -1 is one page position to the left.
         */
 public void transformPage(View page, float position)

方法,page就是ViewPager中的单个页面,position指的是这个page在ViewPager中的当前位置。静止时,
当前选中的(一般是中央的)position是0,左边的是-1,右边的是1,以此类推。在手指向左滑动过程中,当前选中的page的position从0变为-1,这期间的position都会回调到这个方法,我们就可以利用这个做一系列的动画了,以下是上例的切换效果:

/**
     * 切换动画
     */
    class PageAnimation implements ViewPager.PageTransformer {
        final float SCALE_MAX = 0.75f;
        final float ALPHA_MAX = 0.5f;
        final float MAX_Z = 12;

        @Override
        public void transformPage(View page, float position) {
            float scale = (position < 0)
                    ? ((1 - SCALE_MAX) * position + 1)
                    : ((SCALE_MAX - 1) * position + 1);
            float alpha = (position < 0)
                    ? ((1 - ALPHA_MAX) * position + 1)
                    : ((ALPHA_MAX - 1) * position + 1);
            //为了滑动过程中,page间距不变,这里做了处理
            if (position < 0) {
                ViewCompat.setPivotX(page, page.getWidth());
                ViewCompat.setPivotY(page, page.getHeight() / 2);
            } else {
                ViewCompat.setPivotX(page, 0);
                ViewCompat.setPivotY(page, page.getHeight() / 2);
            }
            ViewCompat.setScaleX(page, scale);
            ViewCompat.setScaleY(page, scale);
            ViewCompat.setAlpha(page, Math.abs(alpha));

            // 阴影
            ViewCompat.setElevation(page, MAX_Z * Math.abs(alpha));
        }
    }

完整代码可参见此处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值