自定義視圖CycleViewpager廣告圖循環輪播

先上效果圖:

本項目是用到兩種輪播圖,參考了網上一些大神的代碼,自己做了一點點修改,一種是自定義視圖輪播。還有一種是常見的APP首頁廣告圖片輪播。

下面貼上關鍵類的代碼:

實現自定義視圖輪播的類:CycleMyViewPager

package cn.cnpp.cycleviewpager;

import android.app.Fragment;
import android.os.Bundle;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

/**
 * @author dyl
 *         實現可循環,可輪播的viewpager
 */
public class CycleMyViewPager extends Fragment implements OnPageChangeListener {

    private List<View> viewList = new ArrayList<>();
    private ImageView[] indicators;
    private FrameLayout viewPagerFragmentLayout;
    /**
     * 指示器
     */
    private LinearLayout indicatorLayout;
    private BaseViewPager viewPager;
    private ViewPagerAdapter adapter;
    private CycleViewPagerHandler handler;
    /**
     * 默認輪播時間
     */
    private int time = 5000;
    /**
     * 輪播當前位置
     */
    private int currentPosition = 0;
    /**
     * 滾動框是否滾動着
     */
    private boolean isScrolling = false;
    /**
     * 是否循環
     */
    private boolean isCycle = false;
    /**
     * 是否輪播
     */
    private boolean isWheel = false;
    /**
     * 手指鬆開、頁面不滾動時間,防止手機鬆開後短時間進行切換
     */
    private long releaseTime = 0;
    /**
     * 轉動
     */
    private int WHEEL = 100;
    /**
     * 等待
     */
    private int WHEEL_WAIT = 101;

    private ItemCycleViewListener mImageCycleViewListener;
    private ItemScrollCycleViewListener itemScrollCycleViewListener;
    private int[] intInfos;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.view_cycle_viewpager_contet, null);
        viewPager = view.findViewById(R.id.viewPager);
        indicatorLayout = view.findViewById(R.id.layout_viewpager_indicator);
        viewPagerFragmentLayout = view.findViewById(R.id.layout_viewager_content);

        handler = new CycleViewPagerHandler(getActivity()) {

            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == WHEEL && viewList.size() != 0) {
                    if (!isScrolling) {
                        int max = viewList.size() + 1;
                        int position = (currentPosition + 1) % viewList.size();
                        viewPager.setCurrentItem(position, true);
                        // 最後一頁時回到第一頁
                        if (position == max) {
                            viewPager.setCurrentItem(1, false);
                        }
                    }
                    releaseTime = System.currentTimeMillis();
                    handler.removeCallbacks(runnable);
                    handler.postDelayed(runnable, time);
                    return;
                }
                if (msg.what == WHEEL_WAIT && viewList.size() != 0) {
                    handler.removeCallbacks(runnable);
                    handler.postDelayed(runnable, time);
                }
            }
        };

        return view;
    }

    public void setCycleViewData(List<View> views, int[] list, ItemCycleViewListener listener, ItemScrollCycleViewListener scrollListener) {
        setData(views, list, listener, 0, scrollListener);
    }

    /**
     * 初始化viewpager
     *
     * @param views        要顯示的views
     * @param showPosition 默認顯示位置
     */
    public void setData(List<View> views, int[] list, ItemCycleViewListener listener, int showPosition, ItemScrollCycleViewListener scrollListener) {
        mImageCycleViewListener = listener;
        itemScrollCycleViewListener = scrollListener;
        intInfos = list;
        this.viewList.clear();
        if (views.size() == 0) {
            viewPagerFragmentLayout.setVisibility(View.GONE);
            return;
        }
        for (View item : views) {
            this.viewList.add(item);
        }

        int ivSize = views.size();
        // 設置指示器
        indicators = new ImageView[ivSize - 2];
        indicatorLayout.removeAllViews();
        for (int i = 0; i < indicators.length; i++) {
            View view = LayoutInflater.from(getActivity()).inflate(R.layout.view_cycle_viewpager_indicator, null);
            indicators[i] = view.findViewById(R.id.image_indicator);
            indicatorLayout.addView(view);
        }
        adapter = new ViewPagerAdapter();
        // 默認指向第一項,下方viewPager.setCurrentItem將觸發重新計算指示器指向
        setIndicator(0);
        viewPager.setOffscreenPageLimit(3);
        viewPager.setOnPageChangeListener(this);
        viewPager.setAdapter(adapter);
        if (showPosition < 0 || showPosition >= views.size()) {
            showPosition = 0;
        }
        if (isCycle) {
            showPosition = showPosition + 1;
        }
        viewPager.setCurrentItem(showPosition);
    }

    /**
     * 設置指示器居中,默認指示器在右方
     */
    public void setIndicatorCenter() {
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        params.addRule(RelativeLayout.CENTER_HORIZONTAL);
        indicatorLayout.setLayoutParams(params);
    }

    /**
     * 是否循環,默認不開啓,開啓前,請將views的最前面與最後面各加入一個視圖,用於循環
     *
     * @param isCycle 是否循環
     */
    public void setCycle(boolean isCycle) {
        this.isCycle = isCycle;
    }

    /**
     * 設置是否輪播,默認不輪播,輪播一定是循環的
     *
     * @param isWheel
     */
    public void setWheel(boolean isWheel) {
        this.isWheel = isWheel;
        isCycle = true;
        if (isWheel) {
            handler.postDelayed(runnable, time);
        }
    }

    final Runnable runnable = new Runnable() {

        @Override
        public void run() {
            if (getActivity() != null && !getActivity().isFinishing() && isWheel) {
                long now = System.currentTimeMillis();
                // 檢測上一次滑動時間與本次之間是否有觸擊(手滑動)操作,有的話等待下次輪播
                if (now - releaseTime > time - 500) {
                    handler.sendEmptyMessage(WHEEL);
                } else {
                    handler.sendEmptyMessage(WHEEL_WAIT);
                }
            }
        }
    };

    /**
     * 設置輪播暫停時間,即沒多少秒切換到下一張視圖.默認5000ms
     *
     * @param time 毫秒爲單位
     */
    public void setTime(int time) {
        this.time = time;
    }


    /**
     * 設置viewpager是否可以滾動
     *
     * @param enable
     */
    public void setScrollable(boolean enable) {
        viewPager.setScrollable(enable);
    }

    /**
     * 刷新數據,當外部視圖更新後,通知刷新數據
     */
    public void refreshData() {
        if (adapter != null) {
            adapter.notifyDataSetChanged();
        }
    }

    /**
     * 頁面適配器 返回對應的view
     *
     * @author Yuedong Li
     */
    private class ViewPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return viewList.size();
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

        @Override
        public View instantiateItem(ViewGroup container, final int position) {
            View v = viewList.get(position);
            if (mImageCycleViewListener != null) {
                v.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        mImageCycleViewListener.onItemClick(intInfos[currentPosition - 1], currentPosition, v);
                    }
                });
            }
            container.addView(v);
            return v;
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        // viewPager滾動狀態
        if (state == 1) {
            isScrolling = true;
            return;
        } else if (state == 0) {
            releaseTime = System.currentTimeMillis();
            viewPager.setCurrentItem(currentPosition, false);

        }
        isScrolling = false;
    }

    @Override
    public void onPageScrolled(int position, float offset, int offsetPixels) {
    }

    @Override
    public void onPageSelected(int pos) {
        int max = viewList.size() - 1;
        int position = pos;
        currentPosition = pos;
        if (isCycle) {
            if (pos == 0) {
                currentPosition = max - 1;
            } else if (pos == max) {
                currentPosition = 1;
            }
            position = currentPosition - 1;
        }
        setIndicator(position);
        itemScrollCycleViewListener.onScrollListener(position + 1);
    }

    /**
     * 設置指示器
     *
     * @param selectedPosition 默認指示器位置
     */
    private void setIndicator(int selectedPosition) {
        for (int i = 0; i < indicators.length; i++) {
            indicators[i].setBackgroundResource(R.mipmap.dot_grey);
        }
        if (indicators.length > selectedPosition) {
            indicators[selectedPosition].setBackgroundResource(R.mipmap.dot_yellow);
        }
    }

    /**
     * 輪播控件的監聽事件
     *
     * @author minking
     */
    public interface ItemCycleViewListener {

        /**
         * 單擊圖片事件
         *
         * @param info
         * @param position
         * @param imageView
         */
        void onItemClick(int info, int position, View imageView);
    }

    /**
     * 輪播控件的滾動監聽事件
     *
     * @author minking
     */
    public interface ItemScrollCycleViewListener {

        /**
         * 單擊圖片事件
         *
         * @param position
         */
        void onScrollListener(int position);
    }
}

MainActivity初始化頁面

package cn.cnpp.cycleviewpager;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private CycleMyViewPager cycleViewPager;
    private List<View> viewArrayList = new ArrayList<>();

    private CycleImageViewPager cycleImageViewPager;
    private List<ImageView> imageViewList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initMyViewPager();
        initImageViewPager();
    }

    private void initMyViewPager() {
        cycleViewPager = (CycleMyViewPager) getFragmentManager().findFragmentById(R.id.fragment_cycle_viewpager);
        viewArrayList.clear();
        //測試所用數據源
        int[] imgs = {R.mipmap.cate_test1, R.mipmap.cate_test2, R.mipmap.cate_test3, R.mipmap.cate_test4, R.mipmap.cate_test5, R.mipmap.cate_test6,
                R.mipmap.cate_test7, R.mipmap.cate_test8};
        viewArrayList.add(cycleViewItem(imgs[imgs.length - 1]));
        for (int i = 0; i < imgs.length; i++) {
            viewArrayList.add(cycleViewItem(imgs[i]));
        }
        // 將第一個ImageView添加進來
        viewArrayList.add(cycleViewItem(imgs[0]));
        //循環
        cycleViewPager.setCycle(true);
        //設置指示器居中顯示
        cycleViewPager.setIndicatorCenter();
        //開啓輪播
        cycleViewPager.setWheel(true);
        //設置可滑動
        cycleViewPager.setScrollable(true);
        cycleViewPager.setCycleViewData(viewArrayList, imgs, mAdCycleViewListener, mScrollListener);
    }

    private View cycleViewItem(int date) {
        View view = LayoutInflater.from(this).inflate(R.layout.view_cycleview_item, null);
        ImageView iv = view.findViewById(R.id.img_address);
        TextView tv = view.findViewById(R.id.tv_name);
        iv.setImageResource(date);
        tv.setText("cnpp" + date);
        return view;
    }

    private CycleMyViewPager.ItemCycleViewListener mAdCycleViewListener = new CycleMyViewPager.ItemCycleViewListener() {

        @Override
        public void onItemClick(int info, int position, View imageView) {
            showToastShort(MainActivity.this, "您點擊了" + position);
        }
    };

    private CycleMyViewPager.ItemScrollCycleViewListener mScrollListener = new CycleMyViewPager.ItemScrollCycleViewListener() {

        @Override
        public void onScrollListener(int position) {
            showToastShort(MainActivity.this, "您滑動到了" + position);
        }
    };

    private void initImageViewPager() {
        cycleImageViewPager = (CycleImageViewPager) getFragmentManager().findFragmentById(R.id.fragment_image_viewpager);
        // 將最後一個ImageView添加進來
        imageViewList.clear();
        int[] imgs = {R.mipmap.ad_img1, R.mipmap.ad_img2, R.mipmap.ad_img3};
        imageViewList.add(setImageResource(imgs[imgs.length - 1]));
        for (int i = 0; i < imgs.length; i++) {
            imageViewList.add(setImageResource(imgs[i]));
        }
        // 將第一個ImageView添加進來
        imageViewList.add(setImageResource(imgs[0]));
        // 設置循環,在調用setData方法前調用
        cycleImageViewPager.setCycle(true);
        // 在加載數據前設置是否循環
        cycleImageViewPager.setIntData(imageViewList, imgs, mCycleViewListener);
        // 設置輪播
        cycleImageViewPager.setWheel(true);
        // 設置輪播時間,默認5000ms
        cycleImageViewPager.setTime(3000);
        // 設置圓點指示圖標組居中顯示,默認靠右
        cycleImageViewPager.setIndicatorCenter();
    }

    private CycleImageViewPager.ImageCycleViewListener mCycleViewListener = new CycleImageViewPager.ImageCycleViewListener() {

        @Override
        public void onImageClick(int info, int position, View imageView) {
            if (cycleImageViewPager.isCycle()) {
            }
        }
    };

    private ImageView setImageResource(int img) {
        ImageView imageView = (ImageView) LayoutInflater.from(this).inflate(R.layout.view_imageview, null);
        imageView.setImageResource(img);
        return imageView;
    }

    private void showToastShort(Context context, String str) {
        Toast toast = Toast.makeText(context, str, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }
}

佈局文件activity_main.xml.

這裏有一點要注意的是,fragment這裏的name屬性是自定義ViewPager的類名,如果用到自己的項目中去需要修改這個包名。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="cn.cnpp.cycleviewpager.MainActivity">

    <fragment
        android:id="@+id/fragment_cycle_viewpager"
        android:name="cn.cnpp.cycleviewpager.CycleMyViewPager"
        android:layout_width="match_parent"
        android:layout_height="150dp" />

    <fragment
        android:id="@+id/fragment_image_viewpager"
        android:name="cn.cnpp.cycleviewpager.CycleImageViewPager"
        android:layout_width="match_parent"
        android:layout_marginTop="20dp"
        android:layout_height="100dp" />

</LinearLayout>

主要的類就是這些了,需要查看完整的代碼可以下載demo




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章