功能需求:
1、有多個佈局,要求滑動展示,中間大,兩邊小,兩邊小的佈局,大部分在屏幕外,屏幕裏面,漏出來一點,讓用戶知道可以滑動;
2、這多個佈局,內容有差異,甚至,可能有較大差異;
3、在邊緣處,也可以滑動。
類似畫廊效果,其實網上有對應的,但是,細節地方,有些博客寫的不全,我剛開始寫,對着一兩個博客寫,總是出現奇怪的問題,或者沒有效果。對比了不同的博客,纔出來效果。爲此,我寫個博客,乾脆把所有需要注意的細節,都寫出來。一步到位。
本項目中,用到的 Viewpager 的 PageTransformer ,是借鑑自另外一個項目。那個項目中,有多種動畫樣式。有興趣的,可以去看看。
後面的細節說明,請一定、一定、一定要讀完
功能分析:
1、可以滑動,且每個佈局之間,可能(現在或未來)有較大差異。使用 viewpager+Fragment
2、滑動附帶變大、變小功能,使用 viewpager 的 setPageTransformer
爲了適應不同的情況。viewpager+Fragment,可以直接出現在Activity中,也可以嵌套出現在 Fragment 中,所以,兩種情況,我在項目都寫了。
效果圖(左右黑邊,表示手機屏幕邊緣):
1、默認情況
2、滑動了一點
3、滑動停止
細節說明:
1、要實現中間正常展示,左右兩邊漏一點,需要有2點要注意
1、1:viewpager的寬度,不能爲 match_parent
1、2:viewpager和其直接父控件,都需要添加屬性
android:clipChildren="false"
如:
<LinearLayout
android:id="@+id/viewPagerLl_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:gravity="center"
android:orientation="horizontal">
<androidx.viewpager.widget.ViewPager
android:id="@+id/myViewPager_1"
android:layout_width="250dp"
android:layout_height="400dp"
android:clipChildren="false"
android:overScrollMode="never" />
</LinearLayout>
2、給viewpager添加滑動監聽,並且 onPageScrolled 中做個處理。
myViewPager_1?.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
//有的博客中說要加這句話,但是實際測試發現,沒有這個,也沒異常。安全起見,還是保留
viewPagerLl_1?.invalidate()
}
override fun onPageSelected(position: Int) {
Toast.makeText(this@ViewPagerInActivity, "$position", Toast.LENGTH_SHORT).show()
}
})
到此,基本功能具備了。會發現,滑動當前完全展示的佈局以外的地方,是無效的。無法滑動。這就需要再進行額外的處理。
最後,優化滑動處理
爲了好區分,我就給每個滑動佈局(viewpager中的Fragment)加個背景,用於觀察邊界。
這裏,每個大的色塊,如:綠色。表示Fragment的大小。其實,也是viewpager的大小。(viewpager指定了大小,Fragment的根佈局是 match_parent)
如果做了上面 說明 中的那兩步,只能觸摸中間完整展示大小的色塊,才能滑動。現在需要的是,滑動中間色塊的兩邊(如 第二張圖的左右 綠、黃色塊,也能滑動)
1、給viewpager添加一個父佈局(父控件),寬度建議充滿屏幕(最終要根據實際需求來)
2、處理父控件的觸摸事件,觸摸父控件的時候(其實就是觸摸viewpager以外的地方),把觸摸事件交給viewpager
viewPagerLl_1?.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
return myViewPager_1.dispatchTouchEvent(event);
}
})