今天在开发的时候产品提出需要做类似拖动验证手机号码的功能,看了看原型图,大概构思了一下.脑海浮现出安卓原生的控件SeekBar应该可以实现类似功能,故动手实现了一把.再博主不断努力的3小时里,终于将其拿下.其中一些坑,在此分享以供同样需要的小伙伴们.先上效果图一睹为快.
以上是最终实现效果.
先贴上xml对seekbar的属性设置:
首先改变seekbar默认的高度,用到2个属性maxHeight和minHeight,具体高度自己掌握.其次设置seekbar拖动的颜色变化progressDrawable,这里对它就不过多的介绍了,网上一查一大把.主要来说说最后一个属性: splitTrack,它是做什么的?
如果不设置它,seekbar是这样:
看到了吧?对seekbar设置按钮图,透除了背景颜色.也许各位看官会说,不就一个属性么? 没错,可是这一个属性竟花费了小弟近一个小时的折腾才找到它.
接下来介绍对seekbar设置偏移量的方法:setThumbOffset(),它有什么用呢?上图一看便知:
这他xxx的不是在玩我么?由于seekbar的原始大小(高度,和拖动的图片)被我们做了修改以后,导致错位了?其实仔细想想,并不是错位了,而是拖动按钮的图片的中心位置在进度条的最左侧临界点.使用上面的api可以直截了当的处理这个问题
这里还有个问题,就是设置了偏移量以后,当再想左拖动时候,按钮依然会被拖出进度条的最左侧.这里直接给出解决方法,seekbar可以设置进度,相对api是setProgress. 当拖动的进度小于等于0时,就设置seekbar的进度,让它永远等于0就可以了.
继续,经过上面的苦战,基本问题已经都解决了,seekbar这时候已经可以正常展示和拖动了,可是当多动到最右侧时,问题又来了,上图
向右拖动,过头了?这什么鬼?
右边过头其实和上面的问题基本是相似的,图片中心,其实是在进度条的最右侧,并没有问题.可是效果看起来肯定不能通过.怎么解决呢?博主废了好大周折终于还是搞定了:在拖动到最大值max的时候,获取拖动按钮的宽度,将这个宽度当做seekbar的偏移量设置给它.
ok完美解决.运行,一切正常.
最后,将主要代码贴给大家.虽然大家看起来可能并不觉得很费劲的实现,可是其中一些鲜为人知的属性等问题,实在让博主费了很大的劲,才最终搞定,希望大家不要扔砖.
// 当进度满时切换的图片 final Drawable drawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.seekbar_progress_max_icon); // 设置seekbar滑动监听 sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { if (i <= 0) { // 如果拖动的进度小于0,为了让图片不被拖出左边边界,将进度直接设置为0 sb.setProgress(0); tv.setVisibility(View.VISIBLE); tv.setText("向右滑动验证"); } if (i >= 100) { // 当进度满了的时候,让seekbar不能再被拖动,并切换图片, // 这里重新对seekbar设置偏移量,为切换后图片的宽度 // 同时请求服务器 sb.setEnabled(false); sb.setProgress(100); sb.setThumb(drawable); // sb.setThumbOffset(drawable.getMinimumWidth()); pb.setVisibility(View.VISIBLE); // 模拟请求 new Thread(){ @Override public void run() { super.run(); mHandler.sendMessageDelayed(Message.obtain(), 2000); } }.start(); } // 进度在0和100之前时,不做任何操作 if (i > 0 && i < 100) { tv.setText(""); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { Log.e("Main","----------------onStartTrackingTouch--------------"); } @Override public void onStopTrackingTouch(SeekBar seekBar) { Log.e("Main","----------------onStopTrackingTouch--------------"); } });
布局中对seekbar的设置上面有.