Android ViewPager使用小结

来源:互联网 发布:sqlserver可视化工具 编辑:程序博客网 时间:2024/06/10 02:21

Viewpager在项目中随处可见,通常用来做引导页、图片轮翻,或结合Fragment搭建Tab+Fragment+ViewPager项目整体框架。简单总结了一下ViewPager的常见使用方式,由于比较简单直接上代码!

1、引导页实现

引导页一般分为两种,左右滑动引导,上下滑动引导,通过ViewPager轻松实现左右滑动的引导页,并且实现引导点跟随滑动而移动的引导页。
效果图:

这里写图片描述

activity_main.xml

<RelativeLayout 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.support.v4.view.ViewPager        android:id="@+id/viewPager"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </android.support.v4.view.ViewPager>    <FrameLayout        android:id="@+id/layout_frame"        android:layout_width="match_parent"        android:layout_height="40dp"        android:layout_alignParentBottom="true" >        <LinearLayout            android:id="@+id/layout_point"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:gravity="center_horizontal"            android:orientation="horizontal" >        </LinearLayout>    </FrameLayout>    <Button        android:id="@+id/btn_go"        android:layout_width="wrap_content"        android:layout_height="35dp"        android:layout_above="@id/layout_frame"        android:layout_centerHorizontal="true"        android:layout_marginBottom="30dp"        android:background="@drawable/shape_white_blue_4"        android:padding="5dp"        android:text="立即进入"        android:textColor="@android:color/white"        android:textSize="14sp"        android:visibility="gone" /></RelativeLayout>

引入v4包中的ViewPager,添加引导点的布局,其中FrameLayout包裹LinearLayout是因为,选中点(即亮点)需要跟随移动,当某个Pager被选中时选中点将该Pager之前的未选中点(即暗点)进行了遮挡,所以需要上下层关系,在布局中体现包裹关系。
MainActivity.java

/** * Created by magic on 2016年9月28日.引导点跟随移动的引导页 */public class MainActivity extends Activity implements OnPageChangeListener {    ViewPager viewPager;    FrameLayout layout_frame;    LinearLayout layout_point;    // 带颜色的引导点    ImageView img_colorPoint;    Button btn_go;    List<View> list_view = new ArrayList<View>();    List<ImageView> list_pointView = new ArrayList<ImageView>();    //ViewPager 适配器    ViewPagerAdapter adapter;    // 两点之间间距    int pointSpacing;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initGuideView();    }    /**     * 初始化引导页相关     */    private void initGuideView() {        //添加展示的View        LayoutInflater inflater = LayoutInflater.from(this);        list_view.add(inflater.inflate(R.layout.guide_one, null));        list_view.add(inflater.inflate(R.layout.guide_two, null));        list_view.add(inflater.inflate(R.layout.guide_three, null));        adapter = new ViewPagerAdapter(list_view);        viewPager.setAdapter(adapter);        //添加引导点        for (int i = 0; i < list_view.size(); i++) {            ImageView point = new ImageView(this);            //设置暗点            point.setBackgroundResource(R.drawable.img_guide_point);            LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,                    LayoutParams.WRAP_CONTENT);            lp.setMargins(10, 0, 10, 0);            point.setLayoutParams(lp);            list_pointView.add(point);            layout_point.addView(point);        }        //添加选中的引导点        img_colorPoint = new ImageView(MainActivity.this);        //设置亮点        img_colorPoint.setBackgroundResource(R.drawable.img_guide_point_selected);        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,                LayoutParams.WRAP_CONTENT);        img_colorPoint.setLayoutParams(lp);        layout_frame.addView(img_colorPoint);        layout_frame.post(new Runnable() {            @Override            public void run() {                //待布局绘制完毕  设置选中白点 的初始化位置                FrameLayout.LayoutParams l = (FrameLayout.LayoutParams) img_colorPoint.getLayoutParams();                l.leftMargin = list_pointView.get(0).getLeft();                img_colorPoint.setLayoutParams(l);            }        });        layout_point.post(new Runnable() {            @Override            public void run() {                // 获取引导的之间的间隔                pointSpacing = layout_point.getChildAt(1).getLeft()- layout_point.getChildAt(0).getLeft();            }        });    }    private void initView() {        viewPager = (ViewPager) findViewById(R.id.viewPager);        layout_frame = (FrameLayout) findViewById(R.id.layout_frame);        layout_point = (LinearLayout) findViewById(R.id.layout_point);        btn_go = (Button) findViewById(R.id.btn_go);        viewPager.setOnPageChangeListener(this);        btn_go.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(MainActivity.this,TwoActivity.class));            }        });    }    @Override    public void onPageScrollStateChanged(int arg0) {    }    @Override    public void onPageScrolled(int arg0, float arg1, int arg2) {        FrameLayout.LayoutParams l = (FrameLayout.LayoutParams) img_colorPoint                .getLayoutParams();        //根据滑动动态设置左外边距        l.leftMargin = (int) (list_pointView.get(arg0).getLeft() + pointSpacing                * arg1);        img_colorPoint.setLayoutParams(l);    }    @Override    public void onPageSelected(int arg0) {        //根据Pager位置设置btn的显示        if (arg0 == list_view.size() - 1) {            btn_go.setVisibility(View.VISIBLE);        } else {            btn_go.setVisibility(View.GONE);        }    }}

ViewPager的onPageScrolled(int arg0, float arg1, int arg2)回调在滑动过程中会一直调用,参数arg0 :当前页面,点击滑动的页面;arg1:当前页面偏移的百分比;arg2:当前页面偏移的像素位置 。有个这个方法就可以计算小白点的偏移位置了,两引导点之间间距相对两个Pager之间的间距即ViewPager的“宽度”,因此偏移百分比是相同的。
ViewPagerAdapter.java

/** * Created by magic on 2016年9月28日.ViewPager适配器 */public class ViewPagerAdapter extends PagerAdapter {    private List<View> views;    public ViewPagerAdapter(List<View> list) {        super();        this.views = list;    }    // 从当前container中删除指定位置(position)的View    @Override    public void destroyItem(View container, int position, Object object) {        ((ViewPager) container).removeView(views.get(position));    }    // 第一:将当前视图添加到container中,第二:返回当前View    @Override    public Object instantiateItem(View container, int position) {        // 将当前视图添加到container中        ((ViewPager) container).addView(views.get(position));        // 设置当前视图的唯一标示Key        return views.get(position);    }    // getCount():返回要滑动的View的个数    @Override    public int getCount() {        return views.size();    }    // 通过标识arg1找到view    @Override    public boolean isViewFromObject(View arg0, Object arg1) {        return arg0 == arg1;    }}

2、图片轮翻实现

图片轮翻和引导页代码几乎是一致的,只是添加了定时器,用于自动切换界面。
效果图:

这里写图片描述

activity_two.xml

<RelativeLayout 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" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="180dp" >        <android.support.v4.view.ViewPager            android:id="@+id/viewPager"            android:layout_width="match_parent"            android:layout_height="match_parent" >        </android.support.v4.view.ViewPager>        <FrameLayout            android:id="@+id/layout_frame"            android:layout_width="match_parent"            android:layout_height="40dp"            android:layout_alignParentBottom="true" >            <LinearLayout                android:id="@+id/layout_point"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:gravity="center_horizontal"                android:orientation="horizontal" >            </LinearLayout>        </FrameLayout>    </RelativeLayout></RelativeLayout>

TwoActivity.java

/** * Created by magic on 2016年9月28日.图片轮番 */public class TwoActivity extends Activity implements OnPageChangeListener {    ViewPager viewPager;    FrameLayout layout_frame;    LinearLayout layout_point;    // 带颜色的引导点    ImageView img_colorPoint;    List<View> list_view = new ArrayList<View>();    List<ImageView> list_pointView = new ArrayList<ImageView>();    ViewPagerAdapter adapter;    // 两点之间间距    int pointSpacing;    //当前ViewPager选中位置    int pageSelect = 0;    //定时器    Timer timer;    Task task;    @SuppressLint("HandlerLeak")    private Handler handler = new Handler() {        public void handleMessage(android.os.Message msg) {            viewPager.setCurrentItem(pageSelect);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_two);        initView();        initGuideView();        timer = new Timer();        task = new Task();        //设置定时延迟1000开始  时间周期1500        timer.schedule(task, 1000, 1500);    }    private void initGuideView() {        LayoutInflater inflater = LayoutInflater.from(this);        list_view.add(inflater.inflate(R.layout.guide_one, null));        list_view.add(inflater.inflate(R.layout.guide_two, null));        list_view.add(inflater.inflate(R.layout.guide_three, null));        adapter = new ViewPagerAdapter(list_view);        viewPager.setAdapter(adapter);        for (View view : list_view) {            view.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    startActivity(new Intent(TwoActivity.this,ThreeActivity.class));                }            });        }        for (int i = 0; i < list_view.size(); i++) {            ImageView point = new ImageView(this);            point.setBackgroundResource(R.drawable.img_guide_point);            LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,                    LayoutParams.WRAP_CONTENT);            lp.setMargins(10, 0, 10, 0);            point.setLayoutParams(lp);            list_pointView.add(point);            layout_point.addView(point);        }        img_colorPoint = new ImageView(TwoActivity.this);        img_colorPoint                .setBackgroundResource(R.drawable.img_guide_point_selected);        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,                LayoutParams.WRAP_CONTENT);        img_colorPoint.setLayoutParams(lp);        layout_frame.addView(img_colorPoint);        layout_frame.post(new Runnable() {            @Override            public void run() {                FrameLayout.LayoutParams l = (FrameLayout.LayoutParams) img_colorPoint                        .getLayoutParams();                l.leftMargin = list_pointView.get(0).getLeft();                img_colorPoint.setLayoutParams(l);            }        });        layout_point.post(new Runnable() {            @Override            public void run() {                // 获取引导的之间的间隔                pointSpacing = layout_point.getChildAt(1).getLeft()                        - layout_point.getChildAt(0).getLeft();            }        });    }    private void initView() {        viewPager = (ViewPager) findViewById(R.id.viewPager);        layout_frame = (FrameLayout) findViewById(R.id.layout_frame);        layout_point = (LinearLayout) findViewById(R.id.layout_point);        viewPager.setOnPageChangeListener(this);    }    @Override    public void onPageScrollStateChanged(int arg0) {    }    @Override    public void onPageScrolled(int arg0, float arg1, int arg2) {        System.out.println("arg0:" + arg0 + " arg1:" + arg1 + " arg2:" + arg2);        FrameLayout.LayoutParams l = (FrameLayout.LayoutParams) img_colorPoint                .getLayoutParams();        l.leftMargin = (int) (list_pointView.get(arg0).getLeft() + pointSpacing                * arg1);        img_colorPoint.setLayoutParams(l);    }    @Override    public void onPageSelected(int arg0) {        pageSelect = arg0;    }    /**     * 定时任务类     */    class Task extends TimerTask {        @Override        public void run() {            pageSelect++;            if (pageSelect >= list_view.size()) {                pageSelect = 0;            }            handler.sendEmptyMessage(pageSelect);        }    }}

ViewPagerAdapter.java同上~~~

3、图片循环轮翻实现

上面的图片轮翻可自动切换,也可手动滑动切换。但是存在一个问题就是当手动切换的时候滑动到第一个Pager或最后一个Pager时,再向前或向后滑动就不能滑了,这样的体验是不太好的 。
为了解决这个问题,自己冥思苦想,加上查找资源,无奈人丑脑笨,未能合理解决,利用ViewPager去做总会存在或多或少的bug,例如白屏、Pager数量影响滑动效果等问题。最后求助朋友,得到一前人写的自定义控件(该实现并非使用Viewpager,但和ViewPager实现图片轮翻效果一致就放一块整理了),完美解决了,哈哈~
效果图:

这里写图片描述

先上布局activity_three.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="180dp" >        <com.magic.custom.MyPagerGalleryView            android:id="@+id/mypager_galleryview"            android:layout_width="match_parent"            android:layout_height="match_parent" />        <LinearLayout            android:id="@+id/layout_point"            android:layout_width="match_parent"            android:layout_height="15dp"            android:layout_alignParentBottom="true"            android:layout_marginBottom="20dp"            android:gravity="center_horizontal"            android:orientation="horizontal" >        </LinearLayout>    </RelativeLayout></LinearLayout>

主界面ThreeActivity.java

/** * Created by magic on 2016年9月29日.图片轮翻循环效果 */public class ThreeActivity extends Activity {    MyPagerGalleryView mypager_galleryview;    LinearLayout layout_point;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_three);        mypager_galleryview = (MyPagerGalleryView) findViewById(R.id.mypager_galleryview);        layout_point = (LinearLayout) findViewById(R.id.layout_point);        mypager_galleryview                .start(this, new ArrayList<String>(), new int[] { R.drawable.img_guide_one,                        R.drawable.img_guide_two, R.drawable.img_guide_three },                        1500, layout_point,                        R.drawable.img_guide_point_selected,                        R.drawable.img_guide_point);    }}

自定义控件:MyPagerGalleryView.java

/** * 无限滚动广告栏组件 */@SuppressWarnings("deprecation")public class MyPagerGalleryView extends Gallery implements        android.widget.AdapterView.OnItemClickListener,        android.widget.AdapterView.OnItemSelectedListener, OnTouchListener {    /** 显示的Activity */    private Context mContext;    /** 条目单击事件接口 */    private MyOnItemClickListener mMyOnItemClickListener;    /** 图片切换时间 */    private int mSwitchTime;    /** 自动滚动的定时器 */    private Timer mTimer;    /** 圆点容器 */    private LinearLayout mOvalLayout;    /** 当前选中的数组索引 */    private int curIndex = 0;    /** 上次选中的数组索引 */    private int oldIndex = 0;    /** 圆点选中时的背景ID */    private int mFocusedId;    /** 圆点正常时的背景ID */    private int mNormalId;    /** 图片资源ID组 */    private int[] mAdsId;    /** 图片网络路径数组 */    private List<String> list;    /** ImageView组 */    private List<ImageView> listImgs;    /** 广告条上面textView控件 */    private TextView adgallerytxt;    /** 广告条上的每一条文字的数组 */    private String[] txtViewpager;    private ImageLoader il;    public MyPagerGalleryView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public MyPagerGalleryView(Context context) {        super(context);    }    public MyPagerGalleryView(Context context, AttributeSet attrs) {        super(context, attrs);    }    /**     * 对外开放方法     *      * @param context     *            显示的Activity ,不能为null     * @param mris     *            图片的网络路径数组 ,为空时 加载 adsId     * @param adsId     *            图片组资源ID ,测试用     * @param switchTime     *            图片切换时间 写0 为不自动切换     * @param ovalLayout     *            圆点容器 ,可为空     * @param focusedId     *            圆点选中时的背景ID,圆点容器可为空写0     * @param normalId     *            圆点正常时的背景ID,圆点容器为空写0     * @param adgallerytxt     *            广告条上面textView控件     * @param txtViewpager     *            广告条上的每一条文字的数组     *      */    public void start(Context context, List<String> list, int[] adsId,            int switchTime, LinearLayout ovalLayout, int focusedId, int normalId) {        this.mContext = context;        this.list = list;        this.mAdsId = adsId;        this.mSwitchTime = switchTime;        this.mOvalLayout = ovalLayout;        this.mFocusedId = focusedId;        this.mNormalId = normalId;        ininImages();// 初始化图片组        setAdapter(new AdAdapter());        this.setOnItemClickListener(this);        this.setOnTouchListener(this);        this.setOnItemSelectedListener(this);        this.setSoundEffectsEnabled(false);        this.setAnimationDuration(700); // 动画时间        this.setUnselectedAlpha(1); // 未选中项目的透明度        // 不包含spacing会导致onKeyDown()失效!!! 失效onKeyDown()前先调用onScroll(null,1,0)可处理        setSpacing(0);        // 取靠近中间 图片数组的整倍数        setSelection((getCount() / 2 / listImgs.size()) * listImgs.size()); // 默认选中中间位置为起始位置        setFocusableInTouchMode(true);        initOvalLayout();// 初始化圆点        startTimer();// 开始自动滚动任务    }    /** 初始化图片组 */    private void ininImages() {        listImgs = new ArrayList<ImageView>(); // 图片组        int len = list.size() != 0 ? list.size() : mAdsId.length;        for (int i = 0; i < len; i++) {            ImageView imageview = new ImageView(mContext); // 实例化ImageView的对象            imageview.setScaleType(ImageView.ScaleType.FIT_XY); // 设置缩放方式            imageview.setLayoutParams(new Gallery.LayoutParams(                    Gallery.LayoutParams.MATCH_PARENT,                    Gallery.LayoutParams.MATCH_PARENT));            if (list.size() == 0) {// 本地加载图片                imageview.setImageResource(mAdsId[i]); // 为ImageView设置要显示的图片            } else { // 网络加载图片                il = ImageLoader.getInstance();                il.init(ImageLoaderConfiguration.createDefault(mContext));                il.displayImage(list.get(i), imageview);            }            listImgs.add(imageview);        }    }    /** 初始化圆点 */    private void initOvalLayout() {        if (mOvalLayout != null && listImgs.size() < 2) {// 如果只有一第图时不显示圆点容器            mOvalLayout.removeAllViews();            mOvalLayout.getLayoutParams().height = 0;        } else if (mOvalLayout != null) {            mOvalLayout.removeAllViews();            // 圆点的大小是 圆点窗口的 70%;            int Ovalheight = (int) (mOvalLayout.getLayoutParams().height * 0.7);            // 圆点的左右外边距是 圆点窗口的 20%;            int Ovalmargin = (int) (mOvalLayout.getLayoutParams().height * 0.2);            android.widget.LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(                    Ovalheight, Ovalheight);            layoutParams.setMargins(Ovalmargin, 0, Ovalmargin, 0);            for (int i = 0; i < listImgs.size(); i++) {                View v = new View(mContext); // 员点                v.setLayoutParams(layoutParams);                v.setBackgroundResource(mNormalId);                mOvalLayout.addView(v);            }            // 选中第一个            mOvalLayout.getChildAt(0).setBackgroundResource(mFocusedId);        }    }    /** 无限循环适配器 */    class AdAdapter extends BaseAdapter {        @Override        public int getCount() {            if (listImgs.size() < 2)// 如果只有一张图时不滚动                return listImgs.size();            return Integer.MAX_VALUE;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            return listImgs.get(position % listImgs.size()); // 返回ImageView        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return position;        }    }    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,            float velocityY) {        int kEvent;        if (isScrollingLeft(e1, e2)) { // 检查是否往左滑动            kEvent = KeyEvent.KEYCODE_DPAD_LEFT;        } else { // 检查是否往右滑动            kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;        }        onKeyDown(kEvent, null);        return true;    }    /** 检查是否往左滑动 */    private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {        return e2.getX() > (e1.getX() + 50);    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,            float distanceY) {        return super.onScroll(e1, e2, distanceX, distanceY);    }    @Override    public boolean onTouch(View v, MotionEvent event) {        if (MotionEvent.ACTION_UP == event.getAction()                || MotionEvent.ACTION_CANCEL == event.getAction()) {            startTimer();// 开始自动滚动任务        } else {            stopTimer();// 停止自动滚动任务        }        return false;    }    /** 图片切换事件 */    @Override    public void onItemSelected(AdapterView<?> arg0, View arg1, int position,            long arg3) {        curIndex = position % listImgs.size();        if (mOvalLayout != null && listImgs.size() > 1) { // 切换圆点            mOvalLayout.getChildAt(oldIndex).setBackgroundResource(mNormalId); // 圆点取消            mOvalLayout.getChildAt(curIndex).setBackgroundResource(mFocusedId);// 圆点选中            oldIndex = curIndex;        }        // adgallerytxt.setText("" + curIndex);    }    @Override    public void onNothingSelected(AdapterView<?> arg0) {    }    /** 项目点击事件 */    @Override    public void onItemClick(AdapterView<?> arg0, View arg1, int position,            long arg3) {        if (mMyOnItemClickListener != null) {            mMyOnItemClickListener.onItemClick(curIndex);        }    }    /** 设置项目点击事件监听器 */    public void setMyOnItemClickListener(MyOnItemClickListener listener) {        mMyOnItemClickListener = listener;    }    /** 项目点击事件监听器接口 */    public interface MyOnItemClickListener {        /**         * @param curIndex         *            //当前条目在数组中的下标         */        void onItemClick(int curIndex);    }    /** 停止自动滚动任务 */    public void stopTimer() {        if (mTimer != null) {            mTimer.cancel();            mTimer = null;        }    }    /** 开始自动滚动任务 图片大于1张才滚动 */    public void startTimer() {        if (mTimer == null && listImgs.size() > 1 && mSwitchTime > 0) {            mTimer = new Timer();            mTimer.schedule(new TimerTask() {                public void run() {                    handler.sendMessage(handler.obtainMessage(1));                }            }, mSwitchTime, mSwitchTime);        }    }    /** 处理定时滚动任务 */    @SuppressLint("HandlerLeak")    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            // 不包含spacing会导致onKeyDown()失效!!!            // 失效onKeyDown()前先调用onScroll(null,1,0)可处理            onScroll(null, null, 1, 0);            onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);        }    };}

在此感谢MyPagerGalleryView控件的作者,让我们少做轮子~虽然我觉得造轮子是技术提升的一个重要手段。

4、Tab+Fragment+ViewPager的封装

未完待续……

曾经沧海难为水,除却巫山不是云。

2 0
原创粉丝点击