1. 程式人生 > >android 圖片輪播(自動迴圈輪播)

android 圖片輪播(自動迴圈輪播)

實現思路就是通過viewPager自定義元件,支援圖片點選、手動滑動、自動輪播、初始化定位位置。不廢話了先上圖


元件下載

元件使用

public class BannerAutoActivity extends Activity {
    BannerLayout bannerLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_banner_auto);
        initView();
    }
    private void initView(){
        //介面初始化view
        bannerLayout = (BannerLayout) findViewById(R.id.bannerLayout);
        //組織介面圖片資料
        List<ImageView> ivList = new ArrayList<>();
        for(int i=0;i<6;i++){
            ImageView imageView = new ImageView(this);
            ViewGroup.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.FILL_PARENT);
            imageView.setLayoutParams(layoutParams);
            imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            imageView.setImageResource(R.mipmap.banner_01+i);
            ivList.add(imageView);
        }
        //設定初始展示第幾張
//        bannerLayout.setIdx(0);
        bannerLayout.startBanner(ivList,R.drawable.point_background);
        //圖片點選事件監聽
        bannerLayout.setonClickImg(new BannerLayout.onClickImg() {
            @Override
            public void ItemId(int id) {
                int temp = id+1;
                Toast.makeText(BannerAutoActivity.this,"這是第"+temp+"張圖",Toast.LENGTH_SHORT).show();
            }
        });
    }
}
到此通過元件就可以實現上圖的效果了。繼續向下看,自定義view內部的內容。 自定義View一共用了三個檔案。
Banners.java
ChildViewPager.java
BannerLayout.java

實體類

Banners.java

public class Banners {
	private String picurl;

	private String url;

	private String name;

	public void setPicurl(String picurl) {
		this.picurl = picurl;
	}

	public String getPicurl() {
		return this.picurl;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUrl() {
		return this.url;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

}

自定義viewPager

ChildViewPager.java

主要重寫 onTouchEvent(),實現點選監聽和解決滑動衝突問題。因為在專案中當前介面為ScrollView,所以有滑動衝突問題。
    @Override  
    public boolean onTouchEvent(MotionEvent arg0) {  
        // TODO Auto-generated method stub  
        //每次進行onTouch事件都記錄當前的按下的座標  
        curP.x = arg0.getX();  
        curP.y = arg0.getY();  
  
        if(arg0.getAction() == MotionEvent.ACTION_DOWN){  
            //記錄按下時候的座標  
            //切記不可用 downP = curP ,這樣在改變curP的時候,downP也會改變  
            downP.x = arg0.getX();  
            downP.y = arg0.getY();  
            //此句程式碼是為了通知他的父ViewPager現在進行的是本控制元件的操作,不要對我的操作進行干擾  
            getParent().requestDisallowInterceptTouchEvent(true);  
        }  
  
        if(arg0.getAction() == MotionEvent.ACTION_MOVE){  
            //此句程式碼是為了通知他的父ViewPager現在進行的是本控制元件的操作,不要對我的操作進行干擾  
            getParent().requestDisallowInterceptTouchEvent(true);  
        }  
  
        if(arg0.getAction() == MotionEvent.ACTION_UP){  
            //在up時判斷是否按下和鬆手的座標為一個點  這裡可以把判斷放鬆一點
            //如果是一個點,將執行點選事件,這是我自己寫的點選事件,而不是onclick  
            if(downP.x==curP.x && downP.y==curP.y){  
                onSingleTouch();  
                return true;  
            }  
//        	 return super.onTouchEvent(arg0);  
        }  
  
        return super.onTouchEvent(arg0);  
    }  
  
        /** 
     * 單擊 
     */  
    public void onSingleTouch() {  
        if (onSingleTouchListener!= null) {  
  
            onSingleTouchListener.onSingleTouch();  
        }  
    }  

重頭戲來啦

BannerLayout.java

首先是初始化函式
 public BannerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        LayoutInflater.from(context).inflate(R.layout.viewpager_banner, this);
        setUpView();
    }

    private void setUpView() {
        mViewPager = (ChildViewPager) findViewById(R.id.viewpager);
        llPoints = (LinearLayout) findViewById(R.id.ll_points);
        mViewPager.setOnSingleTouchListener(new ChildViewPager.OnSingleTouchListener() {
            @Override
            public void onSingleTouch() {
                // TODO Auto-generated method stub
                onClickImg.ItemId(currentId%ivList.size());
            }
        });
        ivList = new ArrayList<>();
        llPoints.removeAllViews();
    }


這裡就能看到使用中的影子了,設定資料
 /**
     * @param dotId  圓點資源id
     * @param ivList 引數的size必需相等,不然報錯
     */
    public void startBanner(List<ImageView> ivList, int dotId) {
        this.ivList = ivList;
        for (int i = 0; i < ivList.size(); i++) {
            view = new View(context);
            view.setBackgroundDrawable(getResources()
                    .getDrawable(dotId));
            initPoint(view, pointSmall);
            view.setEnabled(false);
            llPoints.addView(view);
        }
        initDataImg();
    }

    /**
     * 設定資料
     */
    private void initDataImg() {
        ViewPagerAdapter adapter = new ViewPagerAdapter();
        mViewPager.setAdapter(adapter);
        mViewPager.setOnPageChangeListener(this);

        llPoints.getChildAt(0).setEnabled(true);
        initPoint(llPoints.getChildAt(0), pointBig);
        mViewPager.setCurrentItem(idx);
        imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
    }

這些都是viewPager的慣用方法。下邊說說自動輪播的實現。 自動輪播通過handle佇列機制呼叫實現,handle設定如下
    /**
     * 請求更新顯示的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 long MSG_DELAY = 3000;
    private Handler imgHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            // 檢查訊息佇列並移除未傳送的訊息,這主要是避免在複雜環境下訊息出現重複等問題。
            if (imgHandler.hasMessages(MSG_UPDATE_IMAGE)) {
                imgHandler.removeMessages(MSG_UPDATE_IMAGE);
            }
            switch (msg.what) {
                case MSG_UPDATE_IMAGE:
                    mViewPager.setCurrentItem(currentId + 1);
                    // 準備下次播放
                    sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                    break;
                case MSG_KEEP_SILENT:
                    // 只要不傳送訊息就暫停了
                    break;
                case MSG_BREAK_SILENT:
                    sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                    break;
                case MSG_PAGE_CHANGED:
                    // 記錄當前的頁號,避免播放的時候頁面顯示不正確。
                    // currentIcon = msg.arg1;
                    break;
                default:
                    break;
            }

        }

    };

在viewPager的監聽器onPageScrollStateChanged中我們以使用handle中的方法達到想要的效果
    @Override
    public void onPageScrollStateChanged(int arg0) {
        // Auto-generated method stub
        switch (arg0) {
            case ViewPager.SCROLL_STATE_DRAGGING:
                imgHandler.sendEmptyMessage(MSG_KEEP_SILENT);
                break;
            case ViewPager.SCROLL_STATE_IDLE:
                imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                break;
            default:
                break;
        }
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
        // Auto-generated method stub

    }

    @Override
    public void onPageSelected(int position) {
        // 切換選中的點
        llPoints.getChildAt(previousSelectPosition).setEnabled(false); // 把前一個點置為normal狀態
        initPoint(llPoints.getChildAt(previousSelectPosition), pointSmall);
        llPoints.getChildAt(position % ivList.size()).setEnabled(true); // 把當前選中的position對應的點置為enabled狀態
        initPoint(llPoints.getChildAt(position % ivList.size()), pointBig);
        previousSelectPosition = position % ivList.size();
        currentId = position;
        imgHandler.sendMessage(Message.obtain(imgHandler, MSG_PAGE_CHANGED,
                position, 0));
    }
元件下載