ViewPager是一個允許頁面左右滑動的佈局管理器,不同的頁面可以有不同數據。我們可以通過實現ViewPager.PageTransformer接口來自定義滑動切換效果。
我們需重寫transformPage方法,這個方法有2個參數。第一個參數是指需要設置滑動效果的頁面,包括即將滑出頁面,即將滑入頁面,已經滑出的頁面,我們可以通過第二個參數判斷第一個參數是指哪個頁面。第二個參數不是頁面的下標,它是一個浮點數,在用戶滑動的過程中,它是動態變化的,通過判斷它的值可得出第一個參數的具體指向。
如果ViewPager沒有設置PageMargin屬性,當前頁面的position爲0,前一個爲-1,後一個爲1。在滑動的過程中,position不斷變化。以左滑爲例,當ViewPager向左滑動時,當前頁面的position從0逐漸變爲-1,即將滑入的頁面position從1逐漸變爲0,滑入的後一個頁面position變爲1。當設置了PageMargin屬性時,當前頁面依舊爲0,前後頁面得加上或減去一個偏移量。(前減後加)。偏移量爲 pageMargin / pageWidth 。我們可以在滑動的過程中通過setAlpha()等方法,改變page的屬性達到動態效果。
下面是一個小例子,如圖。
由圖我們可以看到,當頁面沒有處於當前頁面時,頁面變得透明,高度變少,當頁面滑至當前頁面時,恢復正常。另外我們可以看到屏幕不僅顯示當前頁面,而且顯示前後頁面的部分視圖。我們可以通過設置ViewPager父佈局以及ViewPager本身屬性clipChildren爲false實現。這個屬性表示是否裁切子View的顯示範圍,設置爲false就可以實現上述效果。
public class MyPageTransformer implements ViewPager.PageTransformer {
//透明度和高度最小值
private static final float MIN_SCALE = 0.70f;
private static final float MIN_ALPHA = 0;
@Override
public void transformPage(@NonNull View page, float position) {
int width = page.getWidth();
int offset = 20 / width; // 20爲PageMargin屬性值
if(position < -1 - offset){
page.setAlpha(MIN_ALPHA);
page.setScaleY(MIN_SCALE);
}else if(position <= 1 + offset){//在[-1-offset,1+offset]範圍
if(position == 0){ //當前頁面
page.setAlpha(1.0f);
page.setScaleY(1.0f);
}else{
if(position < 0){ //在[-1-offset,0]範圍
//平滑變化
float f = MIN_ALPHA + (1 - MIN_ALPHA) * (1 + position + offset);
page.setAlpha(f);
float s = MIN_SCALE +(1 - MIN_SCALE) * (1+position + offset);
page.setScaleY(s);
}else{ //在[0,1+offset]範圍
//平滑變化
float f = MIN_ALPHA + (1 - MIN_ALPHA) * (1 - position + offset);
page.setAlpha(f);
float s = MIN_SCALE +(1 - MIN_SCALE) * (1 - position + offset);
page.setScaleY(s);
}
}
}
}
}
我們根據不斷變化的參數position來設置頁面屬性,達到平滑過渡的效果。
佈局文件:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:background="@color/colorPrimary"
tools:context=".Main3Activity">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager_2"
android:layout_width="match_parent"
android:layout_height="220dp"
android:layout_marginLeft="60dp"
android:layout_marginRight="60dp"
android:clipChildren="false"
/>
</RelativeLayout>
設置margin留出空間來顯示其他頁面。
activity代碼:
public class Main3Activity extends AppCompatActivity {
private ViewPager viewPager;
private List<Integer> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
init();
MyPageTransformer n = new MyPageTransformer();
cardViewAdapter adapter = new cardViewAdapter(this, list);
viewPager.setAdapter(adapter);
viewPager.setPageMargin(20);
viewPager.setOffscreenPageLimit(3);//設置緩存頁面數量
viewPager.setPageTransformer(false,n);
}
private void init(){
viewPager = findViewById(R.id.view_pager_2);
list = new ArrayList<>();
for(int i = 0; i < 7; i++){
list.add(R.drawable.a);
}
}
}
viewPager適配器:
public class cardViewAdapter extends PagerAdapter {
private List<Integer> list;
private LayoutInflater inflater;
private Context mContext;
private ImageView iv;
cardViewAdapter(Context context, List<Integer> list){
this.list = list;
mContext = context;
inflater = LayoutInflater.from(mContext);
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View view = inflater.inflate(R.layout.cardview, container, false);
iv = view.findViewById(R.id.image_card);
iv.setImageResource(list.get(position));
container.addView(view);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
}
其他效果同理,修改MyPageTransformer代碼即可。