Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 輪播圖的實現

Android 輪播圖的實現

編輯:關於Android編程

開始之前

環境准備

開發環境

Android Studio 2.2.1 JDK1.7 API 24 Gradle 2.2.1

開發開始

案例分析

這個案例網上也很多, 質量參差不齊, 我也就根據自己的理解來分析分析需要實現的幾個功能點:

輪播圖有n張圖片和相對應的n個小圓點(指示器 indicator) 實現聯動 除了可以手動滑動外, 也可以自動滾動(輪播) 可以考慮使用Handler實現 實現無限輪回滾動 當手指按下圖片後不再自動滾動

根據上述分析進行開發

接下來搭建布局

activity_main.xml




    
        <framelayout android:layout_height="220dp" android:layout_width="match_parent">
            
            
            
            
        </framelayout>
    


指示器 小點繪制文件

indicator_select.xml



    
    

indicator_no_select.xml



    
    

ViewPager的實現

MyPagerAdapter.java

public class MyPagerAdapter extends PagerAdapter {

    public static final int MAX_SCROLL_VALUE = 10000;

    private List mItems;
    private Context mContext;
    private LayoutInflater mInflater;

    public MyPagerAdapter(List items, Context context) {
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mItems = items;
    }

    /**
     * @param container
     * @param position
     * @return 對position進行求模操作
     * 因為當用戶向左滑時position可能出現負值,所以必須進行處理
     */
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View ret = null;

        //對ViewPager頁號求摸取出View列表中要顯示的項
        position %= mItems.size();
        Log.d("Adapter", "instantiateItem: position: " + position);
        ret = mItems.get(position);
        //如果View已經在之前添加到了一個父組件,則必須先remove,否則會拋出IllegalStateException。
        ViewParent viewParent = ret.getParent();
        if (viewParent != null) {
            ViewGroup parent = (ViewGroup) viewParent;
            parent.removeView(ret);
        }
        container.addView(ret);

        return ret;
    }
    /**
     * 由於我們在instantiateItem()方法中已經處理了remove的邏輯,
     * 因此這裡並不需要處理。實際上,實驗表明這裡如果加上了remove的調用,
     * 則會出現ViewPager的內容為空的情況。
     *
     * @param container
     * @param position
     * @param object
     */
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        //警告:不要在這裡調用removeView, 已經在instantiateItem中處理了
    }


    @Override
    public int getCount() {
        int ret = 0;
        if (mItems.size() > 0) {
            ret = MAX_SCROLL_VALUE;
        }
        return ret;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == (View) object;
    }
}

Note: 一定不要在destroyItem中再調用removeView了, 因為咱們已經instantiateItem中做了處理

在MainActivity.java中給ViewPager設置Adapter

mItems = new ArrayList<>();
mViewPager.setAdapter(mAdapter);

addImageView();
mAdapter.notifyDataSetChanged();
private void addImageView(){
    ImageView view0 = new ImageView(this);
    view0.setImageResource(R.mipmap.pic0);
    ImageView view1 = new ImageView(this);
    view1.setImageResource(R.mipmap.pic1);
    ImageView view2 = new ImageView(this);
    view2.setImageResource(R.mipmap.pic2);

    view0.setScaleType(ImageView.ScaleType.CENTER_CROP);
    view1.setScaleType(ImageView.ScaleType.CENTER_CROP);
    view2.setScaleType(ImageView.ScaleType.CENTER_CROP);

    mItems.add(view0);
    mItems.add(view1);
    mItems.add(view2);

}

Note: 因為咱們做的是Demo, 所以我們傳入的是一個ImageView的集合, 真正開發時, 需要傳入含有圖片url的實體類, 在Adapter中可以使用加載圖片的類庫加載

實現右下角指示器

添加指示器

在onCreate中添加

//獲取指示器(下面三個小點)
mBottomLiner = (LinearLayout) findViewById(R.id.live_indicator);
//右下方小圓點
mBottomImages = new ImageView[mItems.size()];
for (int i = 0; i < mBottomImages.length; i++) {
    ImageView imageView = new ImageView(this);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20, 20);
    params.setMargins(5, 0, 5, 0);
    imageView.setLayoutParams(params);
    //如果當前是第一個 設置為選中狀態
    if (i == 0) {
        imageView.setImageResource(R.drawable.indicator_select);
    } else {
        imageView.setImageResource(R.drawable.indicator_no_select);
    }
    mBottomImages[i] = imageView;
    //添加到父容器
    mBottomLiner.addView(imageView);
}

實現聯動

添加ViewPager的監聽事件, 實現ViewPager.OnPageChangeListener接口

mViewPager.addOnPageChangeListener(this);

回調事件


///////////////////////////////////////////////////////////////////////////
// ViewPager的監聽事件
///////////////////////////////////////////////////////////////////////////
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {

    currentViewPagerItem = position;
    if (mItems != null) {
        position %= mBottomImages.length;
        int total = mBottomImages.length;

        for (int i = 0; i < total; i++) {
            if (i == position) {
                mBottomImages[i].setImageResource(R.drawable.indicator_select);
            } else {
                mBottomImages[i].setImageResource(R.drawable.indicator_no_select);
            }
        }
    }
}

@Override
public void onPageScrollStateChanged(int state) {

}

實現自動滾動

在mBottomImages初始化之後 開啟一個線程 進行定時發送一個空消息給Handler處理, 由Handler決定切換到下一頁

//讓其在最大值的中間開始滑動, 一定要在 mBottomImages初始化之前完成
int mid = MyPagerAdapter.MAX_SCROLL_VALUE / 2;
mViewPager.setCurrentItem(mid);
currentViewPagerItem = mid;

//定時發送消息
mThread = new Thread(){
    @Override
    public void run() {
        super.run();
        while (true) {
            mHandler.sendEmptyMessage(0);
            try {
                Thread.sleep(MainActivity.VIEW_PAGER_DELAY);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
};
mThread.start();

自定義Handler

///////////////////////////////////////////////////////////////////////////
// 為防止內存洩漏, 聲明自己的Handler並弱引用Activity
///////////////////////////////////////////////////////////////////////////
private static class MyHandler extends Handler {
    private WeakReference mWeakReference;

    public MyHandler(MainActivity activity) {
        mWeakReference = new WeakReference(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case 0:
                MainActivity activity = mWeakReference.get();
                if (activity.isAutoPlay) {

                    activity.mViewPager.setCurrentItem(++activity.currentViewPagerItem);
                }

                break;
        }

    }
}

Note: 其中isAutoPlay是一個用來判斷當前是否是自動輪播的boolean值變量, 主要用於實現我們接下來說的 當手指按下圖片後不再滾動

實現當手指按下圖片後不再滾動

思路: 我們可以考慮對ViewPager的觸摸事件進行監聽, 然後設置一個上節說到的isAutoPlay的boolean變量用來讓Handler判斷是否進行輪播滾動

代碼實現:

ViewPager設置監聽

mViewPager.setOnTouchListener(this);

事件回調

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            isAutoPlay = false;
            break;
        case MotionEvent.ACTION_UP:
            isAutoPlay = true;
            break;
    }
    return false;
}

注: 細心的同學可能會看出來, 我們沒有單獨說 無限循環 如何實現, 其實, 它的實現已經隱藏在了代碼中, 在這裡我簡單的說一下思路:
給ViewPager的條目個數設置個較大值, 該案例中為10000, 然後我們剛進入時選中的位置為 10000/2=5000, 也就是說我們可以向左或向右滑動約5000多張圖片, 但這是不現實的, 所以就給用戶造成了無限循環的假象

我把源碼放在了github 上, 希望大家多多支持

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved