使用viewPage实现图片轮播
概述
图片循环播放这种效果,在许多的场合都能看到,只要一打开各大主流网站的首页几乎都有一个这样的组件,它可以很显目的提供给用户最近最火热的信息。因为它应用得如此之广泛,今天,我们就来写一下这个组件。
前期准备
首先,分析我们所看到的图片轮播效果,它有:
1.若干张图片,一般为3-6张,不宜太多。
2.一个承载图片的容器。
3.一个线程,实现图片的自动轮播。
4.表示当前图片位置的一个指示器,一般在图片的底部。
以上,便是一个基本的图片轮播控件所需要具备的要素。接下来,我们来找找,安卓里都给我买提供了些什么:
1.图片来源,很丰富。可以在本地,在网上,在项目里。归根结底,我们只要用到它们的url。因为url的变动很小,所以我们可以创建一个公共类来专门保存它们。(在此例子中是 Images.mgIds)
2.容器。首先想到的便是imageView+fragment。通过查看API我们可以发现,一个叫做viewPageer的控件十分适合,它可以放置多张图片,并且可以自动回收那些没有显示出来的图片,十分的节省内存。
3.Thread或Timer
4.指示器当然是呀自己构造了,一个线性布局+对应图片数量的指示点。
布局
基本需要的东西已经分析完毕,接下来,我们便可以来搭载我们的布局了。
同上面分析的一致,我们需要一个ViewPager 和一个LinearLayout 因为指示器的多少是和图片的数量有关的(动态的),因此我们需要在代码中动态的加载它,布局文件如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">  <android.support.v4.view.ViewPager android:id="@+id/viewpage" android:layout_width="match_parent" android:layout_height="match_parent">  </android.support.v4.view.ViewPager>  <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom">  <LinearLayout android:id="@+id/root" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"></LinearLayout> </RelativeLayout></FrameLayout>编码
新建一个类,名为MyViewPager 继承你布局的根类,在这里,我们需要继承FrameLayout 并重写构造函数。这就是我们自定义view的第二种情况,组合已有的控件。
初始化
同在activity中的操作一样,我们需要先初始化我们布局中的控件。
LayoutInflater.from(context).inflate(R.layout.activtity_viewpage,this);
root = (LinearLayout) findViewById(R.id.root);viewPager= (ViewPager) findViewById(R.id.viewpage); adapter=new MyAdapter();viewPager.setAdapter(adapter);viewPager.addOnPageChangeListener(this);使用viewPager时,我们需要自定义一个adapter:
 @Override public int getCount() { return Images.mgIds.length; }  @Override public boolean isViewFromObject(View view, Object object) { return object==view; }  @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(imageViews.get(position)); }  @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(imageViews.get(position)); return imageViews.get(position); }getCount 返回的是数量,这里的Images.mgIds 是我们的图片数据源数组(url)。destroyItem 需要移除当前imageview,而instantiateItem 需要加入imageview。因为imageview需要这么操作,因此我们用一个list来保存它们的引用。
 imageViews=new ArrayList<>(); for (int i = 0; i< Images.mgIds.length; i++){ ImageView img=new ImageView(context); img.setImageResource(Images.mgIds[i]); imageViews.add(img); }同样,因为指示器也需要后续使用,我们也用一个list进行保存
 points = new ArrayList<>(); for (int i = 0; i < Images.mgIds.length; i++) { ImageView img = new ImageView(context); if (i == position) { img.setImageResource(R.drawable.page_indicator_focused); } else { img.setImageResource(R.drawable.page_indicator_unfocused); } root.addView(img); points.add(img); }此时,我们可以使用我们的控件了。但发现一个问题,那就是底部的指示器并没有动。因此,我们需实现viewPager的OnPageChangeListener接口
 /** * 当前展示的第position张图片 * @param position */ @Override public void onPageSelected(int position) { this.position=position; setImageBackGround(position); }增加 自动播放功能
 首先,创建一个timer 和timerTask,这里要先取消原先的任务,否则会报错。
 timer=new Timer(); if (task!=null){ task.cancel(); } task=new viweTask(); timer.schedule(task,2000,3000);/** * 自动播放任务 */ private class viweTask extends TimerTask{  @Override public void run() { if (position == Images.mgIds.length - 1) { position = 0; } else { position++; } handler.sendEmptyMessage(1); } }我们通过hander来更新我们的图片和指示器
private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); viewPager.setCurrentItem(position); setImageBackGround(position); } };我们还可以在onPageScrollStateChanged 中通过状态来判断用户是否想自己进行滑动
 /** * * @param state 1手指触摸屏幕;2 滑动;0 滑动完成 */ @Override public void onPageScrollStateChanged(int state) { if (state==1){ playing=false; }else { playing=true; } }增加 每一项的点击事件回调
直观的想,我们会直接覆盖诸如onclicklistener之类的方法。可是,我们用的是viewPager,每次图片进行切换时,都会销毁原来的图片,加载新的图片。因此,这个方法是没用的。我们应该在onPageSelected 中放置我们的钩子。
在这之前,我们先定义好我们的回调接口:
 //设置回调接口 private OnPageImageItemClick mOnPageImageItemClick; public interface OnPageImageItemClick{ public void PageImageItemClick(ImageView imageItem,int position); }  public void setOnPageImageItemClick(OnPageImageItemClick click){ this.mOnPageImageItemClick=click; }之后,我们便可以放置好我们的接口
 final ImageView nowView=imageViews.get(position); nowView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) {// Log.d(TAG, "position:" + position+" clicked!"); mOnPageImageItemClick.PageImageItemClick(nowView,position); } });测试,在activity中调用
 viewPager.setOnPageImageItemClick(new MyViewPager.OnPageImageItemClick() { @Override public void PageImageItemClick(ImageView imageItem, int position) { Log.d("MainActivity", "position:" + position); } });
    失败是什么?没有什么,只是更走近成功一步;成功是什么?就是走过了所有通向失败的路,只剩下一条路,那就是成功的路。
 
                    
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号