viewpager轮播图的实现(简洁易懂)
来源:互联网 发布:热敏标签打印软件 编辑:程序博客网 时间:2024/04/30 06:53
在做这个效果的时候,我第一时间看了网上的轮播方式,发现问题很多,有的人在代码里大量的判断手动滑动和自动滑动的状态改变,有的人的轮播是定义了一个很大的Int值,通过顺序播放相同的图片来实现的伪轮播,看过这些代码感觉并不满意,所以尝试自己实现。
在轮播更新UI的时候,我尝试了Thread+handler,handler.postdelay,和timer+timertask+handler的方式,前两种方式都会出现一些小Bug,并且不利于功能扩展,读者可自行尝试,所以我采用了第三种方式。
在解决手动滑动和自动滑动的上,其实根本不用设置什么标志位进行大量的判断,这是一个思维误区,因为我们根本不需要解决这两者之间的冲突,我们只需要关注当前页面是不是改变成功了,当前页面是第几个就可以了。所以我们只需要判断onPageScrollStateChanged的state为2的时候,这个页面的position就可以解决上述问题。
如果要给自己的轮播增加一些文字描述也非常的简单,具体可以看我下面的代码分析。
效果图:
直接看核心代码:
MainActivity.java
public class MainActivity extends AppCompatActivity { private Context ctx; //viewpager初始化 private ViewPager viewPager; private List<View> list; private LPagerAdapter adapter; //轮播控制 private Handler handler; private Timer timer; private TimerTask task; private int mPosition; //轮播内容 private LinearLayout point_container; private ImageView[] imgs; private List<ImageTip> tips; private TextView tip1; private TextView tip2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); tip1 = (TextView) findViewById(R.id.tv_tip1); tip2 = (TextView) findViewById(R.id.tv_tip2); ctx = this; initdata(); initpoint(); initTip(); //自定义adapter adapter = new LPagerAdapter(ctx, list, new LPagerImgClickListener() { @Override public void ImgClick(int position) { Toast.makeText(ctx, "点击了" + mPosition, Toast.LENGTH_SHORT).show(); Intent intent = new Intent(ctx, SecondActivity.class); intent.putExtra("position", position); startActivity(intent); } }); //第一种动画// viewPager.setPageTransformer(true, new ZoomOutPageTransformer()); //第二种动画 viewPager.setPageTransformer(true,new DepthPageTransformer()); viewPager.setAdapter(adapter); //监听页面的改变 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// Log.i("LHD", "onPageScrolled" + " positionOffset:" + positionOffset + " positionOffsetPixels:" + positionOffsetPixels); } @Override public void onPageSelected(final int position) {// Log.i("LHD", "onPageSelected" + position); } @Override public void onPageScrollStateChanged(int state) {// Log.i("LHD", "onPageScrollStateChanged:" + state); if (state == 2) {//图片切换成功的状态为2 mPosition = viewPager.getCurrentItem(); Log.i("LHD", "当前页是:" + mPosition); for (int i = 0; i < list.size(); i++) {//设置所有原点 imgs[i].setImageResource(R.drawable.point1); } //设置当前页的小圆点图片和文字信息 imgs[mPosition].setImageResource(R.drawable.point2); tip1.setText(tips.get(mPosition).getTip1()); tip2.setText(tips.get(mPosition).getTip2()); } } }); imgPlay(); } private void imgPlay() { //循环播放 task = new TimerTask() { @Override public void run() { Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } }; timer = new Timer(); timer.schedule(task, 3000, 3000); handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { if (mPosition == (list.size() - 1)) { viewPager.setCurrentItem(0, true); } else { Log.i("LHD", "bbbb: " + mPosition + "当前的进程ID: " + Thread.currentThread().getId()); viewPager.setCurrentItem(mPosition + 1, true); Log.i("LHD", "cccc: " + mPosition); } } } }; } private void imgStop() { handler.removeMessages(1); timer.cancel(); task.cancel(); } private void initdata() { list = new ArrayList<View>(); ImageView iv = new ImageView(ctx); ImageView iv2 = new ImageView(ctx); ImageView iv3 = new ImageView(ctx); ImageView iv4 = new ImageView(ctx); ImageView iv5 = new ImageView(ctx); ImageView iv6 = new ImageView(ctx); iv.setImageResource(R.drawable.image3); iv2.setImageResource(R.drawable.image4); iv3.setImageResource(R.drawable.image5); iv4.setImageResource(R.drawable.image6); iv5.setImageResource(R.drawable.image7); iv6.setImageResource(R.drawable.image8); list.add(iv); list.add(iv2); list.add(iv3); list.add(iv4); list.add(iv5); list.add(iv6); imgs = new ImageView[list.size()]; } private void initpoint() { point_container = (LinearLayout) findViewById(R.id.point_container); for (int i = 0; i < list.size(); i++) { ImageView imageView = new ImageView(ctx); imageView.setImageResource(R.drawable.point1); //对布局控件添加相对属性 LinearLayout.LayoutParams param = new LinearLayout.LayoutParams( 20, 20); //添加规则,示例 靠父控件最右边 param.setMargins(10, 0, 0, 0); Log.i("LHD", "添加小圆点:" + list.size()); imgs[i] = imageView;//添加到图片数组 point_container.addView(imageView, param); imgs[0].setImageResource(R.drawable.point2); } } private void initTip() { tips = new ArrayList<ImageTip>(); tips.add(new ImageTip("山治:我要寻找all bule", "2016/6/23")); tips.add(new ImageTip("弗兰奇:我要飞上天", "2016/6/24")); tips.add(new ImageTip("乌索普:我要成为勇敢的海上战士", "2016/6/25")); tips.add(new ImageTip("罗宾:我要寻找历史原文", "2016/6/26")); tips.add(new ImageTip("娜美:我要环绕世界一周", "2016/6/27")); tips.add(new ImageTip("路飞:我要成为海贼王!", "2016/6/28")); tip1.setText(tips.get(0).getTip1()); tip2.setText(tips.get(0).getTip2()); } @Override protected void onPause() { super.onPause(); Log.i("LHD", "onPause"); //保存当前页位置 mPosition = viewPager.getCurrentItem(); //停止轮播 imgStop(); } @Override protected void onRestart() { super.onRestart(); Log.i("LHD", "onRestart"); //重新启动轮播 imgPlay(); }}
分析:
imgPlay()
这个函数就是用来控制图片轮播的函数,
在这个函数里,使用了Timer+TimerTask+handler的方式来更新UI。
imgStop()
这个函数用来取消图片轮播,当按下HOME键或者返回键的时候需要将动画取消,再次启动Activity的时候再恢复。
initdata()
将需要轮播的图片存放在一个List里,并且定义了一个存放图片的数组。
initpoint()
根据图片数量来添加小圆点
initTip()
图片下面文字的初始化
重写了onPause方法和onRestart方法,在onPause方法里保存图片位置,停止动画,在onRestart方法里重启动画。
接下来看ViewPager的适配器:
LPagerAdapter.java
/** * Created by LHD on 2016/6/29. */public class LPagerAdapter extends PagerAdapter { private Context ctx; private List<View> mlist; private LPagerImgClickListener mlistener; public LPagerAdapter(Context ctx, List<View> mlist, LPagerImgClickListener listener) { this.ctx = ctx; this.mlist = mlist; this.mlistener = listener; } @Override public int getCount() { return mlist.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, final int position) { container.addView(mlist.get(position)); mlist.get(position).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {// Toast.makeText(ctx, "点击了" + position, Toast.LENGTH_SHORT).show(); if (mlistener != null) { mlistener.ImgClick(position); } } }); return mlist.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mlist.get(position)); }}
和普通的viewpager适配器没有区别,只是增加了一个监听,当点击图片的时候,调用mlistener.ImgClick(position);
接口:
LPagerImgClickListener.java
public interface LPagerImgClickListener { public void ImgClick(int position);}
另外提供了两种viewpager的动画,这两种动画都是谷歌官方提供,可以根据需要修改里面的参数。
动画1:
DepthPageTransformer.java
/** * Created by LHD on 2016/6/30. */public class DepthPageTransformer implements ViewPager.PageTransformer{ private static float MIN_SCALE = 0.75f; @SuppressLint("NewApi") @Override 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); } }}
动画2:
ZoomOutPageTransformer.java
package com.example.eventbus.imagecarousellhd;import android.support.v4.view.ViewPager;import android.view.View;/** * Created by LHD on 2016/6/30. */public class ZoomOutPageTransformer implements ViewPager.PageTransformer{ private static float MIN_SCALE = 0.85f; private static float MIN_ALPHA = 0.5f; @Override 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); } }}
代码下载:
http://dl.download.csdn.net/down11/20160630/0d6a1d49d94dc37ad2d036876956b959.zip?response-content-disposition=attachment%3Bfilename%3D%22ImageCarouselLHD.zip%22&OSSAccessKeyId=9q6nvzoJGowBj4q1&Expires=1467270036&Signature=9MhZGsUC9qiLVG7y2YSWjj1EbIo%3D
- viewpager轮播图的实现(简洁易懂)
- greendao的使用(简洁易懂)
- eventbus的使用(一)简洁易懂
- eventbus的使用(二)简洁易懂
- rxjava的使用(简洁易懂)
- DataBinding的用法(简洁易懂)
- greendao的使用(简洁易懂)
- android实现表情输入(极其简洁易懂)
- Android里的Binder机制(简洁易懂)
- 简洁的Fragment+viewPager
- ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)
- ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)
- ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)
- ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)
- ViewPager实现页卡的最新方法--简洁的TabLayout(谷歌支持包)
- 最简单的MVP模式,简洁易懂。
- 归并排序(分治法+简洁易懂)
- Retrofit2使用(非常简洁易懂)
- 脏纱窗不用拆!小媳妇只用一张旧报纸,奇迹就发生了······
- Android之CalendarView日历视图
- startActivityForResult源码分析
- Time类解析
- Android的消息机制
- viewpager轮播图的实现(简洁易懂)
- Python用户存储加密及登录验证系统(乞丐版)
- IOS_函数
- 在低版本中让按钮显示阴影
- Android基本知识
- Linux上利用nginx域名转发
- ContentProvider学习笔记
- Linux命令积累_find
- 基于Deep Learning 的视频识别方法概览