【Android Developers Training】 70. 使用ViewPager实现屏幕滑动
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。
原文链接:http://developer.android.com/training/animation/screen-slide.html
屏幕滑动是从一个完整的屏幕转换到另一个屏幕的动画,对于配置向导或者幻灯片的应用场景是很常见的。这节课将会展示如何使用support library.ViewPager提供的ViewPager来自动实现滑动的动画。下面是一个屏幕滑动的动画例子:
如果你希望略过这部分内容直接看代码样例,可以直接下载样例代码,然后选择淡入淡出动画的例子。下面的文件是实现代码:
src/ScreenSlidePageFragment.javasrc/ScreenSlideActivity.javalayout/activity_screen_slide.xmllayout/fragment_screen_slide_page.xml
一). 创建视图
创建一个布局文件,你马上就会使用到它作为一个fragment的内容布局。下面的代码是一个例子,包含了一个文本框显示一些文本:
<!-- fragment_screen_slide_page.xml -->
<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" />
</ScrollView>
同时记得给这个fragment定义一个字符串。
二). 创建一个Fragment
创建一个Fragment类,在onCreateView()中返回你刚才创建的布局。当你需要向用户显示新的一页时,你可以之后在父activity中创建这个fragment的实例:
import android.support.v4.app.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
ViewPager拥有内置的页面间滑动手势并且默认是显示滑动动画的,所以你不需要创建任何动画。 ViewPager使用PagerAdapter作为一个要显示的新页面的提供者,所以PagerAdapter会使用你之前创建的fragment类。
首先,创建一个包含ViewPager的布局:
<!-- activity_screen_slide.xml -->
<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,它完成下列事情:
- 将视图的布局设置为包含了ViewPager的布局。
- 创建一个继承FragmentStatePagerAdapter抽象类的类,并且实现getItem()方法来提供ScreenSlidePageFragment的实例作为新的页面。这个页面适配器(Pager Adapter)还要求你实现getCount()方法,它返回适配器需要创建的页面数量(比如说有五页)。
- 将PagerAdapter与ViewPager关联起来。
- 处理设备的后退按键,让它实现在虚拟堆栈中向后移动。如果用户已经在第一页了,回到activity的后退堆栈。
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
...
public class ScreenSlidePagerActivity extends FragmentActivity {
/**
* The number of pages (wizard steps) to show in this demo.
*/
private static final int NUM_PAGES = 5; /**
* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.
*/
private ViewPager mPager; /**
* The pager adapter, which provides the pages to the view pager widget.
*/
private PagerAdapter mPagerAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide); // Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
} @Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
} /**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
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.PageTransformer接口,并将它提供给ViewPager。该接口有一个共有方法:transformPage()。每次屏幕切换,该方法都会为每一个可见的页面(一般来说都只有一个可见页面)及相邻的离开屏幕范围的页面执行一次。例如,如果当前第三页是可见的,并且用户滑动到了第四页,那么transformPage()方法会在手势执行的过程中,分别为第二页,第三页和第四页进行调用。
在你的transformPage()的实现中,你可以根据当前屏幕所显示的页的位置,确定哪些页需要变化,创建自定义的滑动动画,着可以通过transformPage()方法的position参数获得。
position变量指出了某个页面相对于中心的位置。这个变量会随着用户在页面间切换而动态变化。当一个页面充满屏幕时,它的position值是0。当一个页面被拉出到了屏幕右侧,它的position值是1。如果用户在页面一和页面二切换过程中,那么页面一的position值为-0.5,页面二的position值为0.5。根据页面对于屏幕的位置,你可以通过设置页面的属性,比如:setAlpha(),setTranslationX()或setScaleY(),来创建自定义的滑动动画。
当你有一个PageTransformer的实现,在你的实现中调用setPageTransformer()来应用你的自定义动画。例如,如果你有一个叫ZoomOutPageTransformer的PageTransformer,你可以这样设置你的自定义动画:
ViewPager mPager = (ViewPager) findViewById(R.id.pager);
...
mPager.setPageTransformer(true, new ZoomOutPageTransformer());
拉远页面切换(Zoom-out)
这个动画会缩小页面然后在滑动过程中淡化相邻的页面。在一个页面接近中心的时候,它会回到它的标准大小并且淡入。
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) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
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);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
深度页面动画(Depth)
这个动画对于向左滑动的页面使用默认的滑动动画,而对于从右侧滑入的页面使用深度动画。该动画淡出页面,并且线性地缩小它的大小。
Note:
在深度动画过程中,默认的动画(屏幕滑动)仍然发生,所以你必须用一个负X方向来抵消屏幕滑动,例如
view.setTranslationX(-1 * view.getWidth() * position);
下面的例子展示了如何在一个工作页面中,抵消默认的屏幕滑动动画:
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) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
【Android Developers Training】 70. 使用ViewPager实现屏幕滑动的更多相关文章
- 【Android Developers Training】 12. 支持不同屏幕
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 68. 序言:添加动画
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 10. 序言:支持不同设备
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 60. 在你的UI中显示位图
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 58. 缓存位图
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 55. 序言:高效显示位图
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 9. 覆盖于布局之上的Action Bar
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 7. 添加Action Buttons
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 4. 启动另一个Activity
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
随机推荐
- Kafka学习-复制
复制 Kafka可以通过可配置的服务器数量复制每个主题分区的日志(可以为每个主题设置复制因子).这允许在集群中的服务器发生故障时自动故障转移到其他副本,因此在存在故障的情况下,消息仍然可用. 其他消息 ...
- jQuery选择器的分类
jQuery选择器的分类 jQuery中有很多分类,大类分为四类,四类里面又分为很多小类,下面就为大家一一介绍,这些选择器的使用和好处,Me用的是jQuery1.8.3的版本 选择器都有哪四类?? 1 ...
- 如何使用Handler
什么是Handler? Handler可以发送和处理消息对象或Runnable对象,这些消息对象和Runnable对象与一个线程相关联.每个Handler的实例都关联了一个线程和线程的消息队列.当创建 ...
- MyBatis3入门
这里对mybatis的入门介绍以官方最新MyBatis3.4.1为准,具体文档及jar包请访问:https://github.com/mybatis/mybatis-3/releases. 以前经常都 ...
- 关于QT按键信号槽的总结(原创)
QT界面按钮一般是必填的: 每个按钮都要 Go to slot 下面有几个都是常用的,先说一下 clicked:pressed:releaed的区别 字面意思看:click是点击一下,pressed是 ...
- 7.java 加解密技术系列之 AES
java 加解密技术系列之 AES 序 概念 原理 应用 代码实现 结束语 序 这篇文章继续介绍对称加密算法,至于今天的主角,不用说,也是个厉害的角色 — — AES.AES 的出现,就是为了来替代原 ...
- MySQL高可用方案MHA自动Failover与手动Failover的实践及原理
集群信息 角色 IP地址 ServerID 类型 Master ...
- Java ClassLoader 原理分析
一.ClassLoader(类加载器)的作用 如果一个程序包含不止一个class文件,那么当程序启动时,带有main方法的类的class文件作为程序入口先被JVM加载,然后根据程序调用的需要,再逐步进 ...
- 解决shiro和quartz2 版本冲突问题
修改build.gradle compile ("org.quartz-scheduler:quartz:2.2.3") compile ("org.apache.s ...
- 细说Linux权限
目录: 归属权与访问权 chmod:访问权限设置 chown:所属权限设置 umask:权限掩码 隐藏属性 chattr:写保护.误删保护 单独限权 setfacl 一.归属和访问权限简介 1.归属( ...