继承HorizontalScrollView的自定义轮播控件

HorizontalScrollView自定义轮播控件

最近由于项目需要,需要每屏显示一张半图片且滚动时从后半张开始滚动,查了很多资料发现没有符合自己项目的第三方于是就自己写了个简洁版的,相比较传统viewpager轮播控件,更简洁,不需要adapter方便使用。

  • 首先需要自定义个view继承HorizontalScrollView;
  • 接下来就是在自定义的view中添加子控件了;
private View addView(final int position) {
        ImageView imageView = new ImageView(context);
        imageView.setLayoutParams(paramsImage);
        imageView.setImageResource(list.get(position));
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onChildrenClickListener.onImageClickListener(position);
            }
        });
        return imageView;
    }

由于项目只需要图片轮播,所以只添加了图片,如果需要其他的布局各位可以在这个方法中添加直接的布局。
注意:由于图片尺寸是服务器发来,需要动态计算,需要用的LayoutParams,至于怎么选需要看父布局,比如本项目中的布局是LinearLayout,就需要选LinearLayout.LayoutParams,具体的要具体问题具体分析。

  • 子控件加完后,滚动比较好写了,用HorizontalScrollView自带的scrollTo和smoothScrollTo方法就好,这两个方法都能实现滚动的功能,唯一的区别是scrollTo滚动不带动画,smoothScrollTo滚动带动画,所以我选择了smoothScrollTo。
this.smoothScrollTo(count * scrollWidth, 0);

注意:count图片位置,scrollWidth你想要的滚动距离。

  • 由于就需要让控件能滚动一定的指定距离,而不是 HorizontalScrollView的跟随手势滑动,所以需要重写dispatchTouchEvent方法来计算手指滑动了指定距离,并使控件滚动你想要的距离。由于备注比较详细就不啰嗦了,代码如下:
public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:  //手指按下ViewPageer时
                //获得按下时XY轴的坐标
                downX = ev.getX();
                downY = ev.getY();
                break;
            case MotionEvent.ACTION_UP: //抬起触摸View的手指时
                float diffx = ev.getX() - downX;
                float diffy = ev.getY() - downY;

                if (Math.abs(diffx) > Math.abs(diffy)) {
//                            用户手指从左往右
//                            如果是在第一个页面,手指从左往右,父容器响应
                    LogUtil.d("zqr", "水平滑动距离" + diffx);
                    if (diffx > 0) {
//                                手指从左往右滑动,自己响应touch
                        if (diffx > MyUtils.getScreenWidth(context) / 3) {
                            handler.sendEmptyMessage(1);
                            LogUtil.d("zqr", "手指从左往右滑动,自己响应touch");
                            getParent().requestDisallowInterceptTouchEvent(false);
                        } else {
                            LogUtil.d("zqr", "手指从左往右滑动,子控件响应touch");
                            getParent().requestDisallowInterceptTouchEvent(true);
                        }
                    } else {
//                                手指从右往左滑动,自己响应touch
                        if (diffx < -MyUtils.getScreenWidth(context) / 3) {
                            handler.sendEmptyMessage(0);
                            LogUtil.d("zqr", "手手指从右往左滑动,自己响应touch");
                        } else {
                            LogUtil.d("zqr", "手手指从右往左滑动,子控件响应touch");
                        }
                    }
                } else {
//                            touch交给父容器
                    LogUtil.d("zqr", "垂直滑动大于水平滑动,父容器响应touch");
                }

                isPlay = true;
                break;
            case MotionEvent.ACTION_MOVE: //在View里面滑动手指时
                LogUtil.d("zqr", "滑动" + MotionEvent.ACTION_MOVE);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }
  • 对你没看错我上面的代码了用到了handler,大部分童鞋肯定猜出来了,我是要用来实现自动播放功能,毕竟现在轮播都带自动播放功能,所以我们也得与时俱进嘛。
  • 那么就来说说自动轮播的实现吧,实现方法有很多,不过我觉得用Timer来实现比较方便,其他的比如Thread什么的大家可以自己根据需求修改。Timer和TimerTask用完需要调用cancel()方法否则,会影响性能,代码如下:
private void timer() {
        timer = new Timer();
        timerTask = new TimerTask() {
            @Override
            public void run() {
                if (isPlay) {
                    handler.sendEmptyMessage(0);
                }
            }
        };
        timer.scheduleAtFixedRate(timerTask, time, time);
    }

写到这基本上自动轮播的功能就实现了,因为一般轮播图片都需要监听点击事件,在这就有个小问题,只要手指滑动控件就会执行图片的监听事件,这就不是我想要的了,我们需要的是手指滑动一定距离图片换上一张或者下一张而不执行点击事件,只有在手指按下时才执行点击事件。所以还需要重写onTouchEvent方法,getParent().requestDisallowInterceptTouchEvent(true)返回true 就是本次触摸自己消耗掉响应,不传给子控件,代码如下:

public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                LogUtil.d("zqr", "按下" + MotionEvent.ACTION_DOWN);
                isPlay = false;
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_UP:
                LogUtil.d("zqr", "按上" + MotionEvent.ACTION_UP);
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_CANCEL:
                LogUtil.d("zqr", "取消" + MotionEvent.ACTION_CANCEL);
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            case MotionEvent.ACTION_MOVE:
                LogUtil.d("zqr", "滑动" + MotionEvent.ACTION_MOVE);
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    • 大家肯定会说,轮播没有指示器怎么可以,是的指示器肯定有啊,也是我自己写的,十分的简单,就是继承LinearLayout ,原理和轮播添加子控件差不多,在这就不多说了之后会有完整的项目上传的。
  • 至此,基本上自定义半图轮播就完成了,而且这个控件的扩展性也不错,可以同屏显示2.5,3.5等等多种需求的轮播效果。
  • 完整demo下载地址:http://download.csdn.net/download/zqrdy10/10139666 -
  • 代码中肯定存在很多不足的地方,欢迎大家多多发表意见,可以私信我哦
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要修改 Android HorizontalScrollView 内动态添加控件时的宽度以适应滚动条的宽度,可以使用以下代码: ```java HorizontalScrollView scrollView = findViewById(R.id.horizontal_scroll_view); LinearLayout linearLayout = findViewById(R.id.linear_layout); // 添加控件 Button button = new Button(this); linearLayout.addView(button); // 设置控件宽度 int width = 200; // 设置控件宽度为200像素 int height = LinearLayout.LayoutParams.MATCH_PARENT; LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(width, height); button.setLayoutParams(layoutParams); ``` 在上面的代码中,我们首先获取了 HorizontalScrollView 和 LinearLayout 的实例。然后我们向 LinearLayout 中动态添加了一个 Button 控件。接着,我们使用 LinearLayout.LayoutParams 来设置控件的宽度和高度。在这里,我们将控件的宽度设置为 200 像素,并将高度设置为 MATCH_PARENT,以填充 LinearLayout 的高度。 如果你希望控件的宽度与滚动条的宽度相同,可以使用以下代码来获取 HorizontalScrollView 的宽度,并将控件的宽度设置为相同的值: ```java HorizontalScrollView scrollView = findViewById(R.id.horizontal_scroll_view); LinearLayout linearLayout = findViewById(R.id.linear_layout); // 添加控件 Button button = new Button(this); linearLayout.addView(button); // 设置控件宽度 int width = scrollView.getWidth(); // 设置控件宽度为 ScrollView 的宽度 int height = LinearLayout.LayoutParams.MATCH_PARENT; LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(width, height); button.setLayoutParams(layoutParams); ``` 在这里,我们使用 getWidth() 方法获取 HorizontalScrollView 的宽度,并将控件的宽度设置为相同的值。这样,控件的宽度就与滚动条的宽度相同了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值