Android開發:ViewPager實現屏幕滑動,及定義切換動畫(實例)

在兩個完整的界面之間進行切換是非常常見的效果,Android提供的ViewPager使我們實現起來非常的便捷,在這裏,我將講解如何用ViewPager實現切換,以及如何自定義切換的動畫效果。

一、實現屏幕切換

其實非常簡單,實際上我們只需要四個文件即可實現效果,首先創建一個Fragment所使用的佈局文件layout/fragment_screen_slide_page,佈局文件中包含一個顯示文本的TextView:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/contentView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        style="?android:textAppearanceMedium"
        android:padding="16dp"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/lorem_ipsum"/>
</ScrollView>

 

然後創建一個 Fragment子類,它從onCreateView() 方法中返回之前創建的佈局。無論何時如果我們需要爲用戶展示一個新的頁面,可以在它的父Activity中創建該Fragment的實例:

ScreenSlidePageFragment.java
package com.example.power.mytest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Power on 2018/10/22.
 */

public class ScreenSlidePageFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup)inflater.inflate(
                R.layout.fragment_screen_slide_page, container, false
        );
        return rootView;
    }
}

ViewPager有內建的滑動手勢進行頁面的轉換,而且默認有滑動效果。我們需要使用PagerAdapter爲ViewPager補充新的頁面,這就需要使用到新建的Fragment。

activity_screen_slide.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

接着,我們創建一個新的Activity,其中,繼承自FragmentStatePagerAdapter抽象類的類,然後實現getItem()方法來把ScreenSlidePageFragment實例作爲新頁面補充進來。PagerAdapter還需要實現getCount()方法,它返回 Adapter將要創建頁面的總數(例如5個)。並且處理Back按鈕,按下變爲在虛擬的Fragment棧中回退。如果用戶已經在第一個頁面了,則在Activity的回退棧(back stack)中回退。

ScreenSlidePagerActivity.java
package com.example.power.mytest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;

/**
 * Created by Power on 2018/10/22.
 */

public class ScreenSlidePagerActivity extends FragmentActivity {
    private static final int NUM_PAGES = 5;
    private ViewPager mPager;
    private PagerAdapter mPagerAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_slide);

        mPager = (ViewPager)findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        mPager.setAdapter(mPagerAdapter);
        mPager.setPageTransformer(true, new DepthPageTransformer());
    }

    @Override
    public void onBackPressed() {
        if(mPager.getCurrentItem() == 0){
            super.onBackPressed();
        }else{
            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
        }
    }

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter{
        public ScreenSlidePagerAdapter(FragmentManager fm){
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return new ScreenSlidePageFragment();
        }

        @Override
        public int getCount() {
            return NUM_PAGES;
        }
    }
}

二、自定義切換動畫

按照上面的步驟運行後,效果就可以看見了,但是如果我們想自定義切換的效果,要怎麼做呢?其實很簡單,我們只需要實現ViewPager.PageTransformer接口,然後把它補充到ViewPager中就行了。ViewPager.PageTransformer接口只暴露一個接口transformPage()。每次界面切換,這個方法都會爲每個可見頁面(通常只有一個頁面可見)和剛消失的相鄰頁面調用一次。例如,第三頁可見而且用戶向第四頁拖動,transformPage()在操作的各個階段爲第二,三,四頁分別調用。

 

transformPage()的實現中,基於當前屏幕顯示的頁面的positionposition 由transformPage方法的參數給出)決定哪些頁面需要被動畫轉換,這樣我們就能創建自己的動畫。

但是,在此之前,我們需要先理解ViewPager中的position。position參數表示特定頁面相對於屏幕中的頁面的位置。它的值在用戶滑動頁面過程中動態變化。當某一頁面填充屏幕,它的值爲0。當頁面剛向屏幕右側方向被拖走,它的值爲1。如果用戶在頁面1和頁面2間滑動到一半,那麼頁面1的position爲-0.5並且頁面2的position爲 0.5。根據屏幕上頁面的position,我們可以通過setAlpha(),setTranslationXsetScaleX()這些方法設定頁面屬性來自定義滑動動畫。

在實現ViewPager.PageTransformer後,只需要在ScreenSlidePagerActivity.java中添加一行即可(注,XXX代表你的接口名)

mPager.setPageTransformer(true, new XXX());

接下來舉例兩個實現的接口,可以實現之後看一下效果,理解之後就可以自行定義自己的動畫效果了。

ZoomOutPageTransformer
package com.example.power.mytest;

import android.support.v4.view.ViewPager;
import android.view.View;

/**
 * Created by Power on 2018/10/22.
 */

public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;

    public void transformPage(View view, float position){
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if(position < -1){
            view.setAlpha(0);
        }else if(position <= 1){
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if(position < 0){
                view.setTranslationX(horzMargin - vertMargin / 2);
            }else{
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) /
                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));
        }else{
            view.setAlpha(0);
        }
    }
}
DepthPageTransformer
package com.example.power.mytest;

import android.support.v4.view.ViewPager;
import android.view.View;

/**
 * Created by Power on 2018/10/22.
 */

public class DepthPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.75f;

    public void transformPage(View view, float position){
        int pageWidth = view.getWidth();

        if(position < -1){
            view.setAlpha(0);
        }else if(position <= 0){
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);
        }else if(position <= 1){
            view.setAlpha(1 - position);
            view.setTranslationX(pageWidth * -position);
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        }else{
            view.setAlpha(0);
        }
    }
}

 

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