一、需求

ViewPager有个天生的缺陷是View无法重用,此外pk10系统架设详情咨询【企娥166848365】ViewPager的滑动过程会频繁requestLayout,尽管可以通过addViewInLayout和removeViewInLayout配合PagerAdapter 的startUpdate和finishUpdate可以减少重绘,但在ListView和RecyclerView中仍然达不到最好的效果。因此,使用一种新的方式十分必要。

二、代码实现

RecyclerPagerView

public class RecyclerPagerView extends RecyclerView implements Handler.Callback {

    private static final long TASK_TIMEOUT = 3000;
    public OnPageChangeListener onPageChangeListener;

    private final Handler mRecyclerHandler;
    private final int MSG_PLAY_NEXT  = 112233;
    private volatile boolean isPlaying = false;
    private boolean lastIsPlayState = false;
    private int realPosition = -1;

    public RecyclerPagerView(Context context) {
        this(context,null);
    }

    public RecyclerPagerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public RecyclerPagerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mRecyclerHandler = new Handler(Looper.getMainLooper(),this);
    }

    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
        this.onPageChangeListener = onPageChangeListener;
        if(this.onPageChangeListener!=null){
            addOnScrollListener(this.onPageChangeListener);
            int currentItem = getCurrentItem();
            this.onPageChangeListener.onPageSelection(currentItem);
        }
    }

    public int getCurrentItem(){
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
        return linearLayoutManager.findFirstVisibleItemPosition();
    }

    public void setCurrentItem(int position,boolean isAnimate){
        Adapter adapter = getAdapter();
        if(adapter==null || adapter.getItemCount()<=position){
            return;
        }
        if(!isAnimate)
        {
            scrollToPosition(position);
        }else {
            smoothScrollToPosition(position);
        }
    }
    public void setCurrentItem(int position ){
       setCurrentItem(position,true);
    }

    @Override
    public boolean fling(int velocityX, int velocityY) {

        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();

        int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;

        // views on the screen
        int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
        View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
        int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
        View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

        // distance we need to scroll
        int leftMargin = (screenWidth - lastView.getWidth()) / 2;
        int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
        int leftEdge = lastView.getLeft();
        int rightEdge = firstView.getRight();
        int scrollDistanceLeft = leftEdge - leftMargin;
        int scrollDistanceRight = rightMargin - rightEdge;

        int targetPosition;

        if (Math.abs(velocityX) < 1500) {
            // The fling is slow -> stay at the current page if we are less than half through,
            // or go to the next page if more than half through

            if (leftEdge > screenWidth / 2) {
                // go to next page
                smoothScrollBy(-scrollDistanceRight, 0);
                targetPosition = firstVisibleItemPosition;

            } else if (rightEdge < screenWidth / 2) {
                // go to next page
                smoothScrollBy(scrollDistanceLeft, 0);
                targetPosition = firstVisibleItemPosition+1;
            } else {
                // stay at current page
                if (velocityX > 0) {
                    smoothScrollBy(-scrollDistanceRight, 0);
                } else {
                    smoothScrollBy(scrollDistanceLeft, 0);
                }
                targetPosition = firstVisibleItemPosition;
            }
        } else {
            // The fling is fast -> go to next page

            if (velocityX > 0) {
                smoothScrollBy(scrollDistanceLeft, 0);
                targetPosition = firstVisibleItemPosition+1;
            } else {
                smoothScrollBy(-scrollDistanceRight, 0);
                targetPosition = firstVisibleItemPosition;
            }

        }

        Log.e("RecyclerPagerView","nextPage="+targetPosition);
        if(this.onPageChangeListener!=null){
            realPosition = targetPosition;
            this.onPageChangeListener.onPageSelection(targetPosition);
        }
        return true;
    }

    @Override
    public void onScrollStateChanged(final  int state) {
        super.onScrollStateChanged(state);

        if (state == SCROLL_STATE_IDLE) {

            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();

            int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;

            int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
            View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
            int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
            View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

            // distance we need to scroll
            int leftMargin = (screenWidth - lastView.getWidth()) / 2;
            int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
            int leftEdge = lastView.getLeft();
            int rightEdge = firstView.getRight();
            int scrollDistanceLeft = leftEdge - leftMargin;
            int scrollDistanceRight = rightMargin - rightEdge;
            int  targetPosition = -1;
            if (leftEdge > screenWidth / 2) {
                smoothScrollBy(-scrollDistanceRight, 0);
                targetPosition = firstVisibleItemPosition+1;
            } else if (rightEdge < screenWidth / 2) {
                smoothScrollBy(scrollDistanceLeft, 0);
                targetPosition = lastVisibleItemPosition;
            }else{
                targetPosition = firstVisibleItemPosition;
            }
            if(this.onPageChangeListener!=null){
                realPosition = targetPosition;
                this.onPageChangeListener.onPageSelection(targetPosition);
            }
        }

    }

    @Override
    public boolean handleMessage(Message msg) {
        int what = msg.what;
        switch (what){
            case MSG_PLAY_NEXT:
                showNextPage();
                break;
        }

        return false;
    }

    private void showNextPage() {
        if(!isPlaying){
            return;
        }
        if(!canRecyclePlaying()){
            isPlaying = false;
            return;
        }
        Adapter adapter = getAdapter();
        int currentItem = getCurrentItem();
        if(adapter!=null && adapter.getItemCount()>0) {
            if (currentItem == NO_POSITION  ) {
                setCurrentItem(0);
            }else {
                setCurrentItem(currentItem+1);
            }
        }

        mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);
    }

    public void startPlay(){
        if(isPlaying){
            stopPlay();
        }
        if (!canRecyclePlaying()){
            isPlaying = false;
            return;
        }

        isPlaying = true;
        mRecyclerHandler.sendEmptyMessageDelayed(MSG_PLAY_NEXT,TASK_TIMEOUT);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        super.setAdapter(adapter);

        if(canRecyclePlaying()){
            if(realPosition==-1){
                realPosition = 1000;
            }
            setCurrentItem(realPosition,false);
        }
    }

    private boolean canRecyclePlaying() {
        Adapter adapter = getAdapter();
        if(adapter==null || adapter.getItemCount()<1) return false;
        return true;
    }

    private void stopPlay() {
        isPlaying = false;
        mRecyclerHandler.removeMessages(MSG_PLAY_NEXT);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if(lastIsPlayState){
            startPlay();
        }

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        lastIsPlayState = isPlaying;
        stopPlay();
    }

    public static    abstract class OnPageChangeListener extends RecyclerView.OnScrollListener{
            public abstract  void onPageSelection(int position);
    }

}

Adapter+Holder 适配器

该类的作用主要用于约束和快速接入

public class QuickViewHolder extends RecyclerView.ViewHolder{
    private SparseArray<View> mViews;
    private View mConvertView;

    private QuickViewHolder(View v){
        super(v);
        mConvertView = v;
        mViews = new SparseArray<>();
    }

    public static QuickViewHolder get(ViewGroup parent, int layoutId){
        View convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
        return new QuickViewHolder(convertView);
    }

    public <T extends View> T getView(int id){
        View v = mViews.get(id);
        if(v == null){
            v = mConvertView.findViewById(id);
            mViews.put(id, v);
        }
        return (T)v;
    }

}

BannerAdapter实现,该类继承QuickAdapter

public class BannerAdapter extends QuickAdapter<String> {

    public BannerAdapter(List<String> datas) {
        super(datas);
    }

    @Override
    public int getLayoutId(int viewType) {
        return R.layout.item_banner_image;
    }

    @Override
    public void convert(QuickViewHolder holder, String url, int position) {

        final Resources resources = holder.itemView.getResources();
        final int drawableId = resources.getIdentifier(url, "drawable", holder.itemView.getContext().getPackageName());
        if(drawableId!=0) {
            ImageView bannerImage = holder.getView(R.id.banner_image_item);
            bannerImage.setImageResource(drawableId);
        }

    }
}

三、使用

        final RecyclerPagerView rpv  = findViewById(R.id.recycler_pager);
        tipTextView                  = findViewById(R.id.tip_text);
        LinearLayoutManager lm = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
        rpv.setLayoutManager(lm);

        List<String> imagelist = new ArrayList<>();
        imagelist.add("banner_t1");
        imagelist.add("banner_t2");
        imagelist.add("banner_t3");
        imagelist.add("banner_t4");

        rpv.setAdapter(new BannerAdapter(imagelist));
        rpv.setOnPageChangeListener(new PagerChangeListener(tipTextView,imagelist.size()));
        rpv.startPlay();

监听器


    public static class  PagerChangeListener extends RecyclerPagerView.OnPageChangeListener {

        private TextView tipTextView;
        private int size;

        public PagerChangeListener(TextView tipTextView,int size) {
            this.tipTextView = tipTextView;
            this.size = size;
        }

        @Override
        public void onPageSelection(int position) {
            tipTextView.setText((position%size+1)+"/"+size);
        }
    }

Android 使用pk10系统架设RecyclerView实现轮播图的更多相关文章

  1. Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View

    最近开发中需要做一个类似京东首页那样的广告轮播效果,于是采用ViewPager自己自定义了一个轮播图效果的View. 主要原理就是利用定时任务器定时切换ViewPager的页面. 效果图如下: 主页面 ...

  2. 小程序实践(二):swiper组件实现轮播图效果

    swiper组件类似于Android中的ViewPager,实现类似轮播图的效果,相对于Android的Viewpager,swiper实现起来更加方便,快捷. 效果图: 首先看下swiper支持的属 ...

  3. Android零基础入门第56节:翻转视图ViewFlipper打造引导页和轮播图

    原文:Android零基础入门第56节:翻转视图ViewFlipper打造引导页和轮播图 前面两期学习了 ViewAnimator及其子类ViewSwitcher的使用,以及ViewSwitcher的 ...

  4. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

  5. Android自定义控件之轮播图控件

    背景 最近要做一个轮播图的效果,网上看了几篇文章,基本上都能找到实现,效果还挺不错,但是在写的时候感觉每次都要单独去重新在Activity里写一堆代码.于是自己封装了一下.本篇轮播图实现原理原文出处: ...

  6. Android ViewPager轮播图

    Android客户端开发中很多时候需要用到轮播图的方式进行重点新闻的推送或者欢迎页面的制作,下面这个轮播图效果的Deamo来自互联网再经过修改而成. 1.布局文件activity_main.xml中添 ...

  7. android中广告轮播图总结

    功能点:无限轮播.指示点跟随.点击响应.实现思路: 1.指示点跟随,指示点通过代码动态添加,数量由图片数量决定. 在viewpager的页面改变监听中,设置点的状态选择器enable,当前页时,set ...

  8. android项目实战 --ListView 头部ViewPager广告轮询图效果

    看开源框架:https://github.com/tianshaojie/AndroidFine,里面有如下效果,特记录学习下,以后项目中用也好能够立刻想起来.   如上面所示,是常见项目中的图片轮训 ...

  9. Android 轮播图Banner切换图片的效果

    Android XBanner使用详解 2018年03月14日 08:19:59 AND_Devil 阅读数:910   版权声明:本文为博主原创文章,未经博主允许不得转载. https://www. ...

随机推荐

  1. 04_java之基本语法02

    01switch语句解构 * A:switch语句解构 a:switch只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码. b:格式如下: swtich(表达式){ case 常量1 : 要 ...

  2. Rhythmk 一步一步学 JAVA (17):Servlet 文件上传

    1.环境 : JDK 1.6 , Tomcat 7.0 2.第三方类库: commons-fileupload-1.3.1.jar commons-io-2.4.jar 3.web.xml配置: &l ...

  3. halcon连续采集图像

    dev_close_window()dev_update_window('off')create_bar_code_model ([], [], BarCodeHandle)dev_open_wind ...

  4. 引用rtmp编译报错:rtmp.obj : error LNK2001: 无法解析的外部符号 __imp__timeGetTime@0

    如题vs下引用librtmp的时候报错:rtmp.obj : error LNK2001: 无法解析的外部符号 __imp__timeGetTime@0 在link 里加入 winmm.lib 就可以 ...

  5. MyBatis 学习记录6 TypeHandler

    主题 因为对MyBatis在JDBC数据和Java对象之间数据转化比较感兴趣,所以就记录并学习一下TypeHandler. 使用场景 如上图所示,观察下接口方法就能明白.TypeHandler主要用于 ...

  6. 搭建一个Web API项目(DDD)

    传送阵:写在最后 一.创建一个能跑的起来的Web API项目 1.建一个空的 ASP.NET Web应用 (为什么不直接添加一个Web API项目呢,那样会有些多余的内容(如js.css.Areas等 ...

  7. Excel 数字处理

    说明 最近在做一个比较小型的网站,需要批量导入注册用户.用户的信息写在一张excel表格里面. 所以就需要读取excel.所以就记录下遇到的问题,以及以后查看. 相关技术 使用的POI解析Excel需 ...

  8. MySQL内置功能之事务、函数和流程控制

    主要内容: 一.事务 二.函数 三.流程控制 1️⃣  事务 一.何谓事务? 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. # ...

  9. 读书笔记 Week6 2018-4-12

    Chap 24 重构 读书笔记 一.需求的变更 单纯就科目学习中的小项目来说,目标在一开始便被明确下来,即可定义一份严谨的列表来描述功能.故在原来的编程经历中,只要上交了程序便一切都没事儿了,也没有重 ...

  10. HoloLens的显示分辨率有多少?

    作者:胡痴儿2.0链接:https://www.zhihu.com/question/27737626/answer/92339648来源:知乎著作权归作者所有,转载请联系作者获得授权. 左右眼各,7 ...