Android ViewPager 自定义翻页动画
来源:互联网 发布:《南风知我意》 编辑:程序博客网 时间:2024/06/07 23:14
最近有用到ViewPager的翻页动画,结合无限循环后,发现有一些坑需要填,这里就稍微整理下
先建一个Activity,很简单 只有4个按钮,分别对应四个效果,前两个为非无限循环模式,后两个为伪无限循环模式(坑就是在这里,稍后说明), 先贴代码
package com.example.viewpagertransformer;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.RotatePagerTransformer).setOnClickListener(this); findViewById(R.id.ZoomPagerTransformer).setOnClickListener(this); findViewById(R.id.LoopRotatePagerTransformer).setOnClickListener(this); findViewById(R.id.LoopZoomPagerTransformer).setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.RotatePagerTransformer: RotatePagerTransformer(); break; case R.id.ZoomPagerTransformer: ZoomPagerTransformer(); break; case R.id.LoopRotatePagerTransformer: LoopRotatePagerTransformer(); break; case R.id.LoopZoomPagerTransformer: LoopZoomPagerTransformer(); break; } } /** * 旋转式翻页 */ private void RotatePagerTransformer() { startActivity(new Intent(this, ViewPagerTransformerActivity.class)); } /** * 缩放式翻页 */ private void ZoomPagerTransformer() { startActivity(new Intent(this, ViewPagerTransformerActivity.class).putExtra("type", 1)); } /** * 循环旋转式翻页 */ private void LoopRotatePagerTransformer() { startActivity(new Intent(this, ViewPagerTransformerActivity.class).putExtra("type", 2)); } /** * 循环缩放式翻页 */ private void LoopZoomPagerTransformer() { startActivity(new Intent(this, ViewPagerTransformerActivity.class).putExtra("type", 3)); }}
对应布局文档
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/RotatePagerTransformer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="旋转式翻页" /> <Button android:id="@+id/ZoomPagerTransformer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="缩放式翻页" /> <Button android:id="@+id/LoopRotatePagerTransformer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="循环旋转式翻页" /> <Button android:id="@+id/LoopZoomPagerTransformer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="循环缩放式翻页" /></LinearLayout>
很简单 4个按钮 对应4个翻页效果 , 再贴出动效的activity ,这里为了节省代码量 就整合在一起了 ,有注释说明
package com.example.viewpagertransformer;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;/** * @author: xiewenliang * @Filename: * @Description: * @Copyright: Copyright (c) 2017 Tuandai Inc. All rights reserved. * @date: 2017/4/12 10:24 */public class ViewPagerTransformerActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final int type = getIntent().getIntExtra("type", 0); setContentView(R.layout.viewpager_transformer_layout); ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager); viewPager.setPageTransformer(true, getPageTransformer()); viewPager.setOffscreenPageLimit(6); viewPager.setAdapter(new PagerAdapter() { @Override public int getCount() { return type > 1 ? Integer.MAX_VALUE : 20;//type大余1 为伪无限循环 } @Override public boolean isViewFromObject(View view, Object object) { return view.equals(object); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { ImageView imageView = new ImageView(container.getContext()); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getResources().getDimensionPixelOffset(R.dimen.dp_100)); imageView.setLayoutParams(lp); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setAdjustViewBounds(true); imageView.setImageResource(getResId(position)); container.addView(imageView); return imageView; } private int getResId(int position) { switch (position % 5 + 1) { case 1: return R.drawable.p001; case 2: return R.drawable.p002; case 3: return R.drawable.p003; case 4: return R.drawable.p004; case 5: return R.drawable.p005; default: return R.drawable.p001; } } }); if (type > 1) { viewPager.setCurrentItem(Integer.MAX_VALUE / 2); } } private ViewPager.PageTransformer getPageTransformer() { int type = getIntent().getIntExtra("type", 0); ViewPager.PageTransformer pageTransformer; if (type == 0 || type == 2) { // type为0 或者2 为上下翻页动画 pageTransformer = new ViewPager.PageTransformer() { private float margin = getResources().getDimension(R.dimen.dp_10); @Override public void transformPage(View page, float position) { page.setTranslationY(-position * margin); if (position >= -1.0f && position <= 0.0f) { // 控制左侧滑入或者划出View相对X坐标为0 page.setTranslationX(-page.getWidth() * (position)); // 旋转 page.setPivotX(0); page.setPivotY(0); page.setRotation(-90f * position); } else if (position > 0.0f) { // 控制右侧滑入或者划出控制View相对X坐标为0 page.setTranslationX(-page.getWidth() * (position)); page.setPivotX(0); page.setPivotY(0); page.setRotation(0f); } else { // 控制左侧其它缓存View旋转状态固定 page.setPivotX(0); page.setPivotY(0); page.setRotation(90f); } } }; } else { // type 为1或者3为缩放翻页动画 pageTransformer = new ViewPager.PageTransformer() { @Override public void transformPage(View page, float position) { if (position >= -1.0f && position <= 0.0f) { // 控制左侧滑入或者划出View缩放比例 page.setScaleX(1 + position * 0.1f); page.setScaleY(1 + position * 0.2f); } else if (position > 0.0f && position <= 1.0f) { // 控制右侧滑入或者划出View缩放比例 page.setScaleX(1 - position * 0.1f); page.setScaleY(1 - position * 0.2f); } else { // 控制其它View缩放比例 page.setScaleX(0.9f); page.setScaleY(0.8f); } } }; } return pageTransformer; }}
布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:gravity="center" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="30dp" /></LinearLayout>
本类 关键代码就在于获取PageTransformer动效对象,该对象中,关键就再于position的值的范围
当position在-1到0之间 代表的就是 向左滑动viewpager时 左侧滑出的那个Pager 或者向右滑动ViewPager时 左侧滑入的那个pager,
当position在0到1之间 代表的就是 向左滑动viewpager时 右侧滑入的那个pager 或者向右滑动viewpager时 右侧滑出的那个pager,
当position小于1 代表的是当前pager的左侧pager 当 position大于1时代表的就是当前viewpager右侧范围的pager (都需排除正在滑入和滑出的两个pager)
搞清楚了这些position代表的含义,自定义动画就会简单很多了,
这里还有一点也需要说明下 关于pager相对位置问题,正常情况下 pager的X轴坐标会随着滑动 实时变化,在做一些动画需求的时候 需要固定住pager在X轴的位置 使每个pager不再按照顺序在X轴平铺开来,而是要重叠起来,就比如本Demo的第一种效果,旋转翻页式效果 ,这时可以使用page.setTranslationX(-page.getWidth() * (position))来抵消pager在横向位置的移动 , 好了 下面贴上前两种效果的图片
接下来说说遇到的坑, 在做viewpager无限循环的时候 有两种模式 ,第一种模式 是在首尾各添加两张图片(具体的大家自行搜索),排列顺序大改就是 34123412 实际如果向左滑动 到顺序第二张 即4这张 这时 会主动跳转到 倒数第3张 也是4这张 如果是向左滑动到倒数第二张 即1这张 会主动跳转到顺序第3张 从而达到伪无限循环模式
第二种模式 也就是我上面用到的模式 定义item为整型最大值 定位到折中点,实现伪无限循环
这里 遇到的坑就是第一种模式, 该模式下 会出现直接跳转 达到无限循环 ,直接跳转时 由于之前的pager已经被回收 会造成左右pager以及当前pager直接重构 从而不执行自定义动画PageTransformer(该动画 只有在滑动,或者setCurrentItem(positon,true)第二个参数为true的时候才会执行),也就造成pager页面直接按照原始值(未缩放或者平移之类的动画效果)显示,目前没有很有效的办法, 所以这里可以考虑第二种无限循环模式
- Android ViewPager 自定义翻页动画
- ViewPager的翻页动画
- Android --自定义ViewPager切换动画
- (自定义View)自动翻页ViewPager
- Android自定义ViewPager的过渡动画
- 不用ViewPager一样做翻页,简单讲讲自定义3D动画
- Android为ViewPager增加切换动画——自定义ViewPager
- Android为ViewPager增加切换动画——自定义ViewPager
- android翻页动画
- android 动画之翻页
- 50.为ViewPager添加翻页动画
- 炫酷的ViewPager翻页动画
- Android TV ViewPager翻页控制
- ViewPager自定义切换动画
- 自定义ViewPager切换动画
- 自定义viewpager切换动画
- android开发游记:viewpager关联tabs,自定义tabs实现翻页滚动效果
- 【Android进阶】自定义带动画切换效果的ViewPager
- oracle 9i/10g/11g 各版本和patch下载列表
- 方形图片,高度铺满,宽度居中裁剪
- 设计师应该关注的科技发展方向(四)
- SQL Server 密码过期
- Python selenium —— 将你的自动化脚本打包成一个exe
- Android ViewPager 自定义翻页动画
- ArcGIS API For Javascript之编辑服务器端图层(通过要素服务feature进行增删改查 )
- Linux c==网络编程的理论知识-并发服务器,分布式服务器(34)
- <C语言漫谈录>5——原码,反码,补码,大端模式与小端模式
- 《图解HTTP》学习笔记之(二)
- bzoj 4602: [Sdoi2016]齿轮(加权并查集)
- linux shell注意点
- 【xamarin】xamarin debug exited
- 类方法 和 对象方法(实例方法) 区别的误区