Android-使用ViewPager实现相册和轮播图效果
前提准备:写一个简单的ViewPager的demo
布局文件:setting_activity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginBottom="10dp"
>
<!--android:clipChildren="false" 允许子view溢出当前父View-->
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
>
</androidx.viewpager.widget.ViewPager>
</RelativeLayout>
public class SettingsActivity extends AppCompatActivity {
private int[] mDrawables = {R.drawable.a1, R.drawable.a2, R.drawable.a3};
//用来记录是否按压,如果按压,则不滚动
boolean isDown;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
ViewPager viewPager = findViewById(R.id.vp);
viewPager.setAdapter(new TBannerAdapter(this, mDrawables));
viewPager.setPageMargin(20);//item之间的间距
//预加载
viewPager.setOffscreenPageLimit(3);
//默认第一张图 左右都有图
viewPager.setCurrentItem(1);
}
}
package com.android.myapplication;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
/**
* 画廊效果:
* 让ViewPager显示出左右两侧的View android:clipChildren="false"
* 无限滑动 设置个max值---Integer.MAX_VALUE
* 自定义ViewPager滑动动画,滑动过程中中间大,两边小 复写Viewpager的PageTransformer
* 自动播放
*/
public class TBannerAdapter extends PagerAdapter {
private int [] mData;
private Context mContext;
public TBannerAdapter(Context context,int [] data){
mContext = context;
mData = data;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
// return mData.length;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;//过滤和缓存
}
@NonNull
@Override //初始化滑动的布局Item
public Object instantiateItem(@NonNull ViewGroup container, int position) {
View view = View.inflate(container.getContext(),R.layout.viewpager_item,null);
ImageView imageView = view.findViewById(R.id.icon);
imageView.setImageResource(mData[position % mData.length]);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Log.d("tww","当前的Item:"+position);
}
});
//添加到父布局
container.addView(view);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
}
在demo的基础上改动,实现自己想要的效果。
目的:在滑动的时候,让page页滑动时产生我们想要的动画效果,但是我们不知道动画效果添加在哪里?可以去查看Viewpager的源码或者百度?看page页滑动是调用了什么方法?
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//viewPager滑动的时候,设置不让滚动
isDown = true;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
//ViewPager不点击了让滚动
isDown = false;
}
});
ViewPager.java (源码)
@CallSuper
protected void onPageScrolled(int position, float offset, int offsetPixels) {
// Offset any decor views if needed - keep them on-screen at all times.
........
if (mPageTransformer != null) {
final int scrollX = getScrollX();
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.isDecor) continue;
final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
mPageTransformer.transformPage(child, transformPos);
}
}
mCalledSuper = true;
}
当page页滑动是,会调用transformPage()这个方法。
下面就是实例了,代码有注释 ,我也只是拙劣的模仿:
/**
* 缩放,轮播图
*/
//这个方法transformPage在ViewPager.onPageScrolled页面滑动的过程中回调
public class SaclePageTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//不缩放
private static final float MIN_SCALE = 0.80f;//缩放
//对给定页面应用属性转换 换页
@Override
public void transformPage(@NonNull View page, float position) {
// 没有滑动 0(左) 1(当前) 2(右) ====> 滑动一张 -1 0 1
//position != 0 表示 左右两边的page
/*if (position != 0) {
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
} else {
page.setScaleX(MAX_SCALE);
page.setScaleY(MAX_SCALE);
}*/
// 向左滑动: [ position < 0 && position > -1]
// 向右滑动: [position > 0 && position < 1 ]
/*
* for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.isDecor) continue;
final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
mPageTransformer.transformPage(child, transformPos);
}
* */
Log.d("tww", position + "");
if (position < 1) {
//重点:指的就是变化过程中view的大小 动画更丝滑
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);//算法
page.setScaleX(scaleFactor);
page.setScaleY(scaleFactor);
} else {
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
}
}
}
/**
* 相册,stack动画效果
*/
public class StackPageTransformer implements ViewPager.PageTransformer {
private final ViewPager viewPager;
private final float SCALE_VALUE = 1f;
//View 之间的偏移量
private final float DEVIATION = 60f;
//旋转
private final float ROTATION = 60f;
//图片是否叠加【默认不叠加】
private final boolean isStack = false;
public StackPageTransformer(ViewPager viewPager) {
this.viewPager = viewPager;
}
@Override
public void transformPage(@NonNull View view, float position) {
Log.d("tww", position + "");
/*
* 当不滑动状态下:
* position = -1 左侧View
* position = 0 当前View
* position = 1 右侧View
*
* 当滑动状态下:
* 向左滑动: [ position < 0 && position > -1]
* 左侧View position < -1
* 当前View 0 ~ -1
* 右侧View 1 ~ 0
*
* 向右滑动:[position > 0 && position < 1 ]
* 左侧View -1 < position < 0
* 当前View 0 ~ 1
* 右侧View position > 1
*/
int pageWidth = viewPager.getWidth();
//隐藏左侧侧的view
if (position == -1) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
//当前View和右侧的View [让右侧View和当前View叠加起来]
if (position >= 0) {
float translationX;
//这里不要晕! 改变isStack来看看效果吧!!
if (isStack) {
translationX = DEVIATION - (pageWidth) * position;
} else {
translationX = (DEVIATION - pageWidth) * position;
}
Log.d("tww", translationX + "");
view.setTranslationX(translationX);
}
//当前view
if (position == 0) {
view.setScaleX(SCALE_VALUE);
view.setScaleY(SCALE_VALUE);
} else {
//左侧已经隐藏了,所以这里值的是右侧View的偏移量
float scaleFactor = Math.min(SCALE_VALUE - position * 0.1f, SCALE_VALUE);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
//向左滑动
if (position < 0 && position > -1) {
//旋转
view.setRotation(ROTATION * position);
view.setAlpha(1 - Math.abs(position));
} else {
//透明度 其他状态不设置透明度
view.setAlpha(1);
}
//向右滑动
if (position > 0 && position < 1) {
view.setRotation(0);
}
}
}
public class SettingsActivity extends AppCompatActivity {
private int[] mDrawables = {R.drawable.a1, R.drawable.a2, R.drawable.a3};
//用来记录是否按压,如果按压,则不滚动
boolean isDown ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
ViewPager viewPager = findViewById(R.id.vp);
viewPager.setAdapter(new TBannerAdapter(this, mDrawables));
viewPager.setPageMargin(20);//item之间的间距
//预加载
viewPager.setOffscreenPageLimit(3);
//默认第一张图 左右都有图
viewPager.setCurrentItem(1);
//缩放,轮播图
viewPager.setPageTransformer(true,new SaclePageTransformer());
//旋转,相册
//viewPager.setPageTransformer(true,new StackPageTransformer(viewPager));
//利用Timer计时器实现自动轮播
Timer timer = new Timer();
//定时器播放ViewPager
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (!isDown) {
//获取到当前的位置
int page = viewPager.getCurrentItem() + 1;
runOnUiThread(() -> viewPager.setCurrentItem(page));
}
}
};
// 每2.5秒执行一次
timer.schedule(timerTask, 0, 2500);
//Viewpager监听
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//viewPager滑动的时候,设置不让滚动
isDown = true;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
//ViewPager不点击了让滚动
isDown = false;
}
});
}
}