标签:
Android中的控件中有一类是ProgressBar,其子类中有一个是AbsSeekBar。相信有不少童鞋对这个拖动条的父类比较感兴趣吧!尤其 是看到网易云音乐的进度条上面是可以处理播放与暂停事件,是不是很羡慕的哈~ 俺在这里告诉大家,不用羡慕,看了我下面的代码分析,你也是可以做出那样的效果的哦。Let‘s go.
下面先给大家列表一下AbsSeekBar的成员变量有哪些。
- private final Rect mTempRect = new Rect();
- private Drawable mThumb;
- private ColorStateList mThumbTintList = null;
- private PorterDuff.Mode mThumbTintMode = null;
- private boolean mHasThumbTint = false;
- private boolean mHasThumbTintMode = false;
- private int mThumbOffset;
- private boolean mSplitTrack;
在变量中我们大致需要知道一下几点:
1、mTempRect是与SeekBar整个轨迹绘制相关的变量
2、mThumb是SeekBar上面的滑块的Drawable的图片
3、mThumbOffset是滑块是距离x左边距的距离
对于AbsSeekBar的成员方法,下面选取一个比较重要的,在实际的开发工作中经常用到的几个方法给大家讲解一下。
1、setThumbOffset
这个方法是设置滑块距离左边距的位置
2、
- public synchronized void setMax(int max) {
- super.setMax(max);
- if ((mKeyProgressIncrement == 0) || (getMax() / mKeyProgressIncrement > 20)) {
-
-
-
- setKeyProgressIncrement(Math.max(1, Math.round((float) getMax() / 20)));
- }
- }
这个方法实际关联到两个功能。
1、设置当前的SeekBar的最大值
2、由于存在部分手机有向左的按键与向右的按键,就比如我曾经遇到过的一款三星的商务机。按照源码的逻辑,控制左按键与右按键一次位移的边距不要超过20.
关于轨迹的绘制与滑块的绘制的更新,主要关注下面的一段代码
- if (track != null) {
- track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft,
- h - mPaddingBottom - trackOffset - mPaddingTop);
- }
- if (thumb != null) {
- setThumbPos(w, thumb, getScale(), thumbOffset);
- }
轨迹的绘制比较重要,我们一起看看吧;
- void drawTrack(Canvas canvas) {
-
- final Drawable thumbDrawable = mThumb;
- if (thumbDrawable != null && mSplitTrack) {
- final Insets insets = thumbDrawable.getOpticalInsets();
- final Rect tempRect = mTempRect;
- thumbDrawable.copyBounds(tempRect);
- tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
- tempRect.left += insets.left;
- tempRect.right -= insets.right;
-
- final int saveCount = canvas.save();
-
- canvas.clipRect(tempRect, Op.DIFFERENCE);
- super.drawTrack(canvas);
- canvas.restoreToCount(saveCount);
- } else {
- super.drawTrack(canvas);
- }
- }
针对上面的代码块,主要讲下面的几点:
1、mSlitTrack这个变量存在的原因是,我们通常遇到滑块的左右的颜色不一样,这个变量就是起到分割左右两边的目的。
滑块的绘制也是比较重要的哦,下面也一起来看看吧:
- void drawThumb(Canvas canvas) {
- if (mThumb != null) {
- canvas.save();
-
-
-
- canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
-
- mThumb.draw(canvas);
- canvas.restore();
- }
- }
我们知道,滑块的位置会随着进度而不断的位移,而绘制的本质实际上都利用了画布类Canvas,因此本质上是画布在不断的进行位移。也就是这一行代码的含义:
- canvas.translate(mPaddingLeft - mThumbOffset, mPaddingTop);
下面的内容主要是讲解AbsSeekBar是如何处理touch事件,而我上面的所说的网易云音乐如果做到点击进度条实现播放与暂停的效果也与下面的讲解有关:
与上面一样,咱们先上代码:
- public boolean onTouchEvent(MotionEvent event) {
- if (!mIsUserSeekable || !isEnabled()) {
- return false;
- }
-
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- if (isInScrollingContainer()) {
- mTouchDownX = event.getX();
- } else {
-
- setPressed(true);
- if (mThumb != null) {
- invalidate(mThumb.getBounds());
- }
- onStartTrackingTouch();
- trackTouchEvent(event);
- attemptClaimDrag();
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mIsDragging) {
- trackTouchEvent(event);
- } else {
- final float x = event.getX();
-
- if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) {
- setPressed(true);
- if (mThumb != null) {
- invalidate(mThumb.getBounds());
- }
- onStartTrackingTouch();
- trackTouchEvent(event);
- attemptClaimDrag();
- }
- }
- break;
-
- case MotionEvent.ACTION_UP:
- if (mIsDragging) {
- trackTouchEvent(event);
- onStopTrackingTouch();
- setPressed(false);
- } else {
-
-
- onStartTrackingTouch();
- trackTouchEvent(event);
- onStopTrackingTouch();
- }
-
-
-
- invalidate();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (mIsDragging) {
- onStopTrackingTouch();
- setPressed(false);
- }
- invalidate();
- break;
- }
- return true;
- }
上面的代码,各位看官不要着急,且听在下一一道来:
1、如果当前的SeekBar已经设置了不能够touch操作,废话不用多说,直接return。
2、按照源码的解释,当当前的控件处于按下的状态,主要进行下面的处理:
2、1 设置当前的状态为Press的状态
2、2 刷新当前的视图
如果我们需要仿造网易云音乐,需要处理暂停音乐的逻辑,
需要注意两点
1、判断当前的event的x的坐标是否是在滑块的内部,如果是,不论当前的位移是多少,均不要改变当前的进度
2、修改当前的滑块的图片
好了,整个的源码的讲解就到这里了,相信大家看到这里,对Android中的SeekBar有了比以前更进一步的了解了吧!
管窥Android中的滑动条SeekBar的父类AbsSeekBar的源码
标签:
原文地址:http://www.cnblogs.com/6060b/p/4192715.html