Android官网培训课:用ViewPager做屏幕幻灯片

本文介绍如何使用ViewPager实现屏幕间的幻灯片过渡效果,并提供了创建自定义动画的具体方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

是指从从一个完整屏幕到另一个屏幕的转移过渡,经常用在app安装向导或者幻灯片展示上。本节课讲解如何用ViewPage实现屏幕幻灯片,支持库ViewPager能够自动实现屏幕幻灯片效果。

创建View


创建一个用于fragment的layout布局文件。如下示例布局文件包含一个text view来显示某些文字。

<com.example.android.animationsdemo.ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    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" />

</com.example.android.animationsdemo.ScrollView>

创建Fragment片段


创建一个Fragment类,在onCreateView()方法中返回你刚刚创建的layout布局。任何时候你想显示一个新的页面给用户时,你就可以在父activity中创建这个Fragment的实例:

public class ScreenSlidePageFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.fragment_screen_slide_page, container, false);

        return rootView;
    }
}

添加一个ViewPager


ViewPagers 有内置的滑动手势功能,通过滑动在多个page之间转移,屏幕幻灯片动画的显示是其默认方式,所以你不需要以PagerAdapter创建任何.ViewPager,不需要以PagerAdapter作为新的pager的提供者,也不需要PagerAdapter使用先前创造的fragment类。have built-in swipe gestures to transition through pages, and they display screen slide animations by default, so you don't need to create any. ViewPagers use PagerAdapters as a supply for new pages to display, so the PagerAdapter will use the fragment class that you created earlier.

首先,创造一个包含ViewPager的layout布局。

<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,该activity做以下几件事情:

  • 将ViewPager设置为activity的显示内容
  • 创建一个继承 FragmentStatePagerAdapter 抽象类的类并实现getItem()方法,这个方法提供 ScreenSlidePageFragment 的实例作为新的page页。Pager Adapter作为ViewPager的适配器,需要实现getCount()方法,这个方法返回适配器中的页面数(本例子中为5)。
  • PagerAdapter 绑定到 ViewPager.
  • 处理设备的回退键事件响应,当回退键按下时,在fragment片段的虚拟堆栈中做回退操作。如果用户已经在第一页了,那么继续在activity的回退栈中做回退。
public class ScreenSlidePagerActivity extends FragmentActivity {
    /**
     * 页面的个数(向导的步数)
     */
    private static final int NUM_PAGES = 5;

    /**
     * Pager组件,可以水平滑动来访问上一个向导步骤或者下一个。
     */
    private ViewPager mPager;

    /**
     * Pager Adapter适配器,给view pager组件提供页面。
     */
    private PagerAdapter mPagerAdapter;

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

        // 实例化一个ViewPager和PagerAdapter.
        mPager = (ViewPager) findViewById(R.id.pager);
        mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
        mPager.setAdapter(mPagerAdapter);
    }

    @Override
    public void onBackPressed() {
        if (mPager.getCurrentItem() == 0) {
            // 如果当前用户正在看向导的第一步,那么让系统来处理这个后退键好了,系统会调用这个activity的finish()然后对回退栈做弹出操作。
            super.onBackPressed();
        } else {
            // 否则的话,选择回退到上一步
            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
        }
    }

    /**
     * 简单的Pager Adapter,按顺序显示五个ScreenSlidePageFragment。
     */
    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;
        }
    }
}

通过PageTransformer自定义动画


如果不想按默认的屏幕幻灯片动画,那么需要实现ViewPager.PagerTransformer接口,然后把实现提供给viewPager。这个接口只有一个方法,就是transformPage()。在每次屏幕转移的那一时点,这个方法会被调用一次,一是为了每个当前处于visible状态的page页面(一般情况下只有一个是visible的),二是为了刚刚离开屏幕的相邻页面。例如,如果页面三是visible的,而用户向页面四做滑动董卓,transformPage()方法会为页面二、三、四调用。

在transformPage()的实现中,你可以通过确定那个页面需要被转移来创建传统的幻灯片动画。屏幕上幻灯片的位置(由transformPage()方法的参数position提供)可以让你确定要转移那张页面。

position参数指出了相对于屏幕中心,给定页面的相对位置。这是一个动态的参数,会随着用户滑动页面而改变。当一个页面填满屏幕时,他的位置是0。当一个页面刚刚被滑出到屏幕的右侧时,他的位置是1.当用户把页面1和页面2滑动到屏幕中间时,页面1和页面2各占屏幕一部分,这时页面1的position为-0.5,页面2的position为0.5。基于页面在屏幕的相对位置,你可以通过设置页面的属性来创建个性化的屏幕幻灯片效果,可以通过像 setAlpha()setTranslationX(), 或是 setScaleY()的方法来改变页面的属性。

当你实现了一个PageTransformer时,调用setPageTransformer()来实现个性化的幻灯片效果。如下所以,如果你有一个名为ZoomOutPageTransformer的PageTransformer,你可以这样来设置个性化的幻灯片:

ViewPager pager = (ViewPager) findViewById(R.id.pager);
...
pager.setPageTransformer(true, new ZoomOutPageTransformer());

下面是缩放型page transformer和深度型page transformer。

缩放型Zoom-out page transformer

当在相邻页面间滑动时,该pageTransformer会收缩和渐隐页面。当页面回到屏幕中心,它会放大页面尺寸然后渐现页面。

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

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

        if (position < -1) { // [-Infinity,-1)
            // 这个页面正在向左远离屏幕
            view.setAlpha(0);

        } else if (position <= 1) { // [-1,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);
            }

            // 按比例缩小页面(比例在 MIN_SCALE 和 1之间)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // 相对于其尺寸进行渐隐
            view.setAlpha(MIN_ALPHA +
                    (scaleFactor - MIN_SCALE) /
                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));

        } else { // (1,+Infinity]
            // 该页面正在向右远离屏幕
            view.setAlpha(0);
        }
    }
}

深度型Depth page transformer

这个page transformer使用默认的屏幕幻灯片动画效果,同时用一个“加深”动画来作用于滑动到右边的页面。这个“加深”动画还慢慢渐隐页面,线性的缩小图片。

注意:D在使用“加深”动画的同时,默认的动画效果还仍然在,所以你必须用一个负的x轴偏移来抵消屏幕滑动。

view.setTranslationX(-1 * view.getWidth() * position);
The following example shows how to counteract the default screen slide animation in a working page transformer:


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

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

        if (position < -1) { // [-Infinity,-1)
            // 页面正在向左离开屏幕
            view.setAlpha(0);

        } else if (position <= 0) { // [-1,0]
            // 使用正常的滑动效果,
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);

        } else if (position <= 1) { // (0,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 { // (1,+Infinity]
            // 页面向右离开屏幕
            view.setAlpha(0);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值