1. 程式人生 > >Android clipChildren與clipToPadding使用以及簡單ViewPager自定義切換效果

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

完整程式碼可參見此處