跑马灯效果

最近做项目需要展示一个展示广告的跑马灯效果,网上找到一个继承 HorizontalScrollView 实现的,但是不能循环滚动;还有用 RecyclerView 实现的,比较好,但是会可以手动滑动,也不符合需求,下面自己改一下。

实现效果:
  • 自动滚动
  • 循环滚动
  • 不可手动干预(如果想干预也可以)
  • 任何View都可以(就是个普通的RecyclerView,内容想是啥自己写就可以了)
实现思路:

循环滚动:

和网上一般展示banner的可以循环的轮播图一样,在 RecyclerView.Adapter 中将 getItemCount() 的返回值设为 Integer.MAX_VALUE;然后在 onBindViewHolder 中回调回来的 position 则将会从0一直到 Integer.MAX_VALUE,用 position 和设置的数据长度取余,则会得到真实的 position。

    @Override
    public int getItemCount() {
        return Integer.MAX_VALUE;
    }
    
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        int realPosition = 0;
        if (mDataList.size() != 0) {
            realPosition = position % mDataList.size();
        }
        holder.update(realPosition);
    }

自动滚动:

如何让 RecyclerView 自动向后滚动呢,就像手指向后滑动,因为 View 的 scrollBy() 或 scrollTo() 方法移动的是View 的内容,而不是 View 本身,而 RecyclerView 的大小设置为 Integer.MAX_VALUE,刚好可以满足模拟自动滑动,而且 RecyclerView 有复用机制,也不用担心内存问题,所以可以不断的调用 scrollBy() 和 scrollTo() 实现自动滚动。

scrollBy() 和 scrollTo() :

1、向上移动,dx=0,dy>0;向下移动dx=0,dy<0;
2、向左移动,dy=0,dx>0;向右移动dy=0,dx<0;
3、scrollBy()是表示移动了多少,scrollBy(5,0),会向左移动5,重复调用会一直向左移动;
4、scrollTo()是表示移动到哪里,比如调用scrollTo(5,0),会向左移动5,重复调用也不会再向左了;

根据上面可以一直调用 scrollBy(x,0) 既可向左滚动了,如果用 scrollTo(x,0) 则需要自己维护 x 自增了;

	private Handler mHandler = new Handler();
	
	private Runnable mRUnnable = new Runnable() {
        @Override
        public void run() {
        	// 移动的距离,这个可以自己调一下,不过不可以太大,否则看起来不丝滑
            mRv.scrollBy(3, 0);
            // 每隔多少毫秒自动滚动,想控制速度可以改变下移动的距离和时间
            mHandler.postDelayed(this, 10); 
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        mHandler.postDelayed(mRUnnable, 10);
    }
    
        @Override
    protected void onPause() {
        super.onPause();
        mHandler.removeCallbacks(mRUnnable);
    }

禁止手动滑动:

如果只是禁调 RecyclerView 的滑动,那就很简单了,LinearLayoutManager 的 canScrollHorizontally() 返回false 就可以了,代码如下:

        LinearLayoutManager layoutManager = new LinearLayoutManager(this){
            @Override
            public boolean canScrollHorizontally() {
                return false;
            }
        };

但是这样不只是手动滑动禁止了,自动滚动也禁止了,所以上面方法行不通,可以从 RecyclerView 的触摸事件入手,如下:

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent event) {
        return true;
    }

这样也有问题,表面上看可以,可以自动滚动了,手动滑动也禁止了,不过连点击事件也拦截了,不过到这里已经很好办了,下面处理一下:

    private float downX, downY;

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(event.getX() - downX) < 5 && Math.abs(event.getY() - downY) < 5) {
                    return false;
                } else {
                    return true;
                }
            case MotionEvent.ACTION_UP:
                View childView = rv.findChildViewUnder(event.getX(), event.getY());
                int position = -1;
                if (childView != null)
                    position = rv.getChildLayoutPosition(childView);
                    
                Log.e("Bill", "click item:" + position);
                break;
        }

        return false;
    }

在手指按下时记录按下坐标,这时不能拦截,否则后面不会走了,点击事件也屏蔽掉了,然后在move的时候判断一下,移动的坐标跟按下的坐标一样,不拦截,则可以相应手指up事件,RecyclerView 的点击事件自然也不会被拦截;如果移动的坐标跟按下的坐标不一样,则说明滑动了,这时在move时拦截掉,避免 RecyclerView 被滑动;我这里加了个误差判断,即5以内算点击了;另外在因为有RecyclerView和手指的x、y,所以可以计算点击的是哪个position了,这个可以模仿ListView实现item的点击事件了,不用在Adapter中单独实现了;当然了,在Adapter中实现也可以。

效果图

在这里插入图片描述

项目地址

参考链接:http://www.word666.com/ruanjian/143001.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值