Android实现图片轮播主要有以下方式,汇总一下:


一、ViewPager + PagerAdapter + Handler

private class ImageAdapter extends PagerAdapter{                     private ArrayList viewlist;             public ImageAdapter(ArrayList viewlist) {              this.viewlist = viewlist;          }             @Override          public int getCount() {              //设置成最大整数,使用户看不到边界              return Integer.MAX_VALUE;          }             @Override          public boolean isViewFromObject(View arg0, Object arg1) {              return arg0==arg1;          }           @Override             public void destroyItem(ViewGroup container, int position,                     Object object) {                 // Warning:不要在这里调用removeView           }             @Override             public Object instantiateItem(ViewGroup container, int position) {               // 对ViewPager页号求模取出View列表中要显示的项               position %= viewlist.size();               if (position<0){                   position = viewlist.size()+position;               }               ImageView view = viewlist.get(position);               // 如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。               ViewParent vp =view.getParent();               if (vp!=null){                   ViewGroup parent = (ViewGroup)vp;                   parent.removeView(view);               }               container.addView(view);                 // add listeners here if necessary               return view;             }        }

这里有几个地方需要注意:
getCount() 方法的返回值:这个值直接关系到ViewPager的“边界”,因此当我们把它设置为Integer.MAX_VALUE之后,用户基本就看不到这个边界了。
instantiateItem() 方法position的处理:由于我们设置了count为 Integer.MAX_VALUE,因此这个position的取值范围很大很大,但我们实际要显示的内容肯定没这么多(往往只有几项),所以这里肯定会有求模操作。但是,简单的求模会出现问题:考虑用户向左滑的情形,则position可能会出现负值。所以我们需要对负值再处理一次,使其落在正确的区间内。
instantiateItem() 方法父组件的处理:通常我们会直接addView,但这里如果直接这样写,则会抛出IllegalStateException。假设一共有三个view,则当用户滑到第四个的时候就会触发这个异常,原因是我们试图把一个有父组件的View添加到另一个组件。但是,如果直接写成下面这样:

(ViewGroup)view.getParent().removeView(view);  

则又会因为一开始的时候组件并没有父组件而抛出NullPointerException。因此,需要进行一次判断。也就是上面的代码。
destroyItem() 方法:由于我们在instantiateItem()方法中已经处理了remove的逻辑,因此这里并不需要处理。实际上,实验表明这里如果加上了remove的调用,则会出现ViewPager的内容为空的情况。


轮播效果的实现:使用Handler进行更新
这里我定义了一个Handler来处理ViewPager的轮播。所谓的“轮播”效果实现起来是这样的:每隔一定时间(这里是3秒)切换一次显示的页面。通过控制各页面以一定顺序循环播放,就达到了轮播的效果。为此,我们可以使用Handler的sendEmptyMessageDelayed()方法来实现定时更新,并
注意用户也可能会对带有轮播效果的ViewPager手动进行滑动操作,因此我认为用户这时候是希望查看指定页面的,这时候应该取消轮播。下面是这个Handler的实现:

private static class ImageHandler extends Handler{                 /**         * 请求更新显示的View。         */        protected static final int MSG_UPDATE_IMAGE  = 1;        /**         * 请求暂停轮播。         */        protected static final int MSG_KEEP_SILENT   = 2;        /**         * 请求恢复轮播。         */        protected static final int MSG_BREAK_SILENT  = 3;        /**         * 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。         * 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,         * 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。         */        protected static final int MSG_PAGE_CHANGED  = 4;                 //轮播间隔时间        protected static final long MSG_DELAY = 3000;                 //使用弱引用避免Handler泄露.这里的泛型参数可以不是Activity,也可以是Fragment等        private WeakReference weakReference;        private int currentItem = 0;                 protected ImageHandler(WeakReference wk){            weakReference = wk;        }                 @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            Log.d(LOG_TAG, "receive message " + msg.what);            MainActivity activity = weakReference.get();            if (activity==null){                //Activity已经回收,无需再处理UI了                return ;            }            //检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。            if (activity.handler.hasMessages(MSG_UPDATE_IMAGE)){                activity.handler.removeMessages(MSG_UPDATE_IMAGE);            }            switch (msg.what) {            case MSG_UPDATE_IMAGE:                currentItem++;                activity.viewPager.setCurrentItem(currentItem);                //准备下次播放                activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);                break;            case MSG_KEEP_SILENT:                //只要不发送消息就暂停了                break;            case MSG_BREAK_SILENT:                activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);                break;            case MSG_PAGE_CHANGED:                //记录当前的页号,避免播放的时候页面显示不正确。                currentItem = msg.arg1;                break;            default:                break;            }         }    }


集成代码:MainActivity
下面是MainActivity的代码,主要是加载View和对ViewPager进行初始化设置:

public class MainActivity extends Activity {         private static final String LOG_TAG = "MainActivity";    private ImageHandler handler = new ImageHandler(new WeakReference(this));    private ViewPager viewPager;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //初始化iewPager的内容        viewPager = (ViewPager) findViewById(R.id.main_viewpager);        LayoutInflater inflater = LayoutInflater.from(this);        ImageView view1 = (ImageView) inflater.inflate(R.layout.item, null);        ImageView view2 = (ImageView) inflater.inflate(R.layout.item, null);        ImageView view3 = (ImageView) inflater.inflate(R.layout.item, null);        view1.setImageResource(R.drawable.ics);        view2.setImageResource(R.drawable.jellybean);        view3.setImageResource(R.drawable.kitkat);        ArrayList views = new ArrayList();        views.add(view1);        views.add(view2);        views.add(view3);        viewPager.setAdapter(new ImageAdapter(views));        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {                         //配合Adapter的currentItem字段进行设置。            @Override            public void onPageSelected(int arg0) {                handler.sendMessage(Message.obtain(handler, ImageHandler.MSG_PAGE_CHANGED, arg0, 0));            }                         @Override            public void onPageScrolled(int arg0, float arg1, int arg2) {            }                         //覆写该方法实现轮播效果的暂停和恢复            @Override            public void onPageScrollStateChanged(int arg0) {                switch (arg0) {                case ViewPager.SCROLL_STATE_DRAGGING:                    handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);                    break;                case ViewPager.SCROLL_STATE_IDLE:                    handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);                    break;                default:                    break;                }            }        });        viewPager.setCurrentItem(Integer.MAX_VALUE/2);//默认在中间,使用户看不到边界        //开始轮播效果        handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);    }//end of onCreate}//end of MainActivity


二、Gallery(deprecated) + Timer


package com.zms.demo2;import java.util.Timer;import java.util.TimerTask;import android.content.Context;import android.os.Handler;import android.util.AttributeSet;import android.util.Log;import android.view.KeyEvent;import android.view.MotionEvent;import android.widget.Gallery;public class MyGallery extends Gallery{/** * 这里的数值,限制了每次滚动的最大长度,图片宽度为480PX。这里设置600效果好一些。 这个值越大,滚动的长度就越大。 * 也就是会出现一次滚动跨多个Image。这里限制长度后,每次滚动只能跨一个Image */private static final int timerAnimation = 1;private final Handler mHandler = new Handler(){public void handleMessage(android.os.Message msg){switch (msg.what){case timerAnimation:int position = getSelectedItemPosition();Log.i("msg", "position:"+position);if (position >= (getCount() - 1)){onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);} else{onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);}break;default:break;}};};private final Timer timer = new Timer();private final TimerTask task = new TimerTask(){public void run(){mHandler.sendEmptyMessage(timerAnimation);}};public MyGallery(Context paramContext){super(paramContext);timer.schedule(task, 3000, 3000);}public MyGallery(Context paramContext, AttributeSet paramAttributeSet){super(paramContext, paramAttributeSet);timer.schedule(task, 3000, 3000);}public MyGallery(Context paramContext, AttributeSet paramAttributeSet,int paramInt){super(paramContext, paramAttributeSet, paramInt);timer.schedule(task, 3000, 3000);}private boolean isScrollingLeft(MotionEvent paramMotionEvent1,MotionEvent paramMotionEvent2){float f2 = paramMotionEvent2.getX();float f1 = paramMotionEvent1.getX();if (f2 > f1)return true;return false;}public boolean onFling(MotionEvent paramMotionEvent1,MotionEvent paramMotionEvent2, float paramFloat1, float paramFloat2){int keyCode;if (isScrollingLeft(paramMotionEvent1, paramMotionEvent2)){keyCode = KeyEvent.KEYCODE_DPAD_LEFT;} else{keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;}onKeyDown(keyCode, null);return true;}public void destroy(){timer.cancel();}}


三、ImageView + CountDownTimer


package com.zms.demo3;import android.os.Bundle;import android.os.CountDownTimer;import android.os.Handler;import android.R.integer;import android.app.Activity;import android.content.Intent;import android.content.Loader.ForceLoadContentObserver;import android.content.res.Resources;import android.graphics.drawable.Drawable;import android.view.Menu;import android.widget.ImageView;import android.widget.Toast;public class MainActivity extends Activity {private ImageView imageView;private int sre[] = { R.drawable.ab1, R.drawable.ab2, R.drawable.ab3,R.drawable.ab4, R.drawable.ab5, R.drawable.ab6, R.drawable.ab7,R.drawable.ab8, R.drawable.ab9, R.drawable.ab10, R.drawable.ab11,R.drawable.ab12, R.drawable.ab13, R.drawable.ab14, R.drawable.ab15,R.drawable.ab16, R.drawable.ab17, R.drawable.ab18, R.drawable.ab19,R.drawable.ab20, R.drawable.ab21,};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);imageView = (ImageView) this.findViewById(R.id.imageView1);Resources res = getResources();Drawable drawable = res.getDrawable(R.drawable.bkcolor);this.getWindow().setBackgroundDrawable(drawable);CountDownTimer timer1 = new CountDownTimer(105000, 5000) {int j = 0;@Overridepublic void onTick(long millisUntilFinished) {// TODO Auto-generated method stubimageView.setImageResource(sre[j]);imageView.refreshDrawableState();j++;}@Overridepublic void onFinish() {// TODO Auto-generated method stubimageView.setImageResource(sre[j]);imageView.refreshDrawableState();// j++;}};timer1.start();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}


更多相关文章

  1. Android中声音处理流程
  2. Android三种实现定时器的方法
  3. Android(安卓)强制停止RecyclerView滑动方法
  4. Android之ViewFlipper的使用与ListView的分页加载
  5. 相对布局
  6. Android(安卓)之 ImageView(图片组件)
  7. Android中thread.start()出现的thread already exist错误
  8. Android(安卓)禁止转屏的方法
  9. PackageManagerService的启动过程分析

随机推荐

  1. android 切换activity动画
  2. android adapter 异步加载图片
  3. Android之Fragment动态添加和移除Fragmen
  4. Android(安卓)USB Host and Accessory
  5. StringTokenizer用法
  6. Android(安卓)代码实现的动画
  7. Android(安卓)通过HTTP POST 上传图片文
  8. Android(安卓)Dex文件结构
  9. Android(安卓)中 上下文Context理解
  10. Android(安卓)获取手机本地IP