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

完整代碼可參見此處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章