packagecom.example.helloverticalseekbarv2;importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Rect;importandroid.graphics.drawable.Drawable;importandroid.util.AttributeSet;importandroid.view.MotionEvent;importandroid.view.View;importandroid.view.ViewConfiguration;importandroid.view.ViewGroup;importandroid.view.ViewParent;importandroid.widget.SeekBar;public class VerticalSeekBar extendsSeekBar
{private booleanmIsDragging;private floatmTouchDownY;private intmScaledTouchSlop;private boolean isInScrollingContainer = false;public booleanisInScrollingContainer()
{returnisInScrollingContainer;
}public void setInScrollingContainer(booleanisInScrollingContainer)
{this.isInScrollingContainer =isInScrollingContainer;
}/*** On touch, this offset plus the scaled value from the position of the
* touch will form the progress value. Usually 0.*/
floatmTouchProgressOffset;public VerticalSeekBar(Context context, AttributeSet attrs, intdefStyle)
{super(context, attrs, defStyle);
mScaledTouchSlop=ViewConfiguration.get(context).getScaledTouchSlop();
}publicVerticalSeekBar(Context context, AttributeSet attrs)
{super(context, attrs);
}publicVerticalSeekBar(Context context)
{super(context);
}
@Overrideprotected void onSizeChanged(int w, int h, int oldw, intoldh)
{super.onSizeChanged(h, w, oldh, oldw);
}
@Overrideprotected synchronized void onMeasure(intwidthMeasureSpec,intheightMeasureSpec)
{super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Overrideprotected synchronized voidonDraw(Canvas canvas)
{
canvas.rotate(-90);
canvas.translate(-getHeight(), 0);super.onDraw(canvas);
}
@Overridepublic booleanonTouchEvent(MotionEvent event)
{if (!isEnabled())
{return false;
}switch(event.getAction())
{caseMotionEvent.ACTION_DOWN:if(isInScrollingContainer())
{
mTouchDownY=event.getY();
}else{
setPressed(true);
invalidate();
onStartTrackingTouch();
trackTouchEvent(event);
attemptClaimDrag();
onSizeChanged(getWidth(), getHeight(),0, 0);
}break;caseMotionEvent.ACTION_MOVE:if(mIsDragging)
{
trackTouchEvent(event);
}else{final float y =event.getY();if (Math.abs(y - mTouchDownY) >mScaledTouchSlop)
{
setPressed(true);
invalidate();
onStartTrackingTouch();
trackTouchEvent(event);
attemptClaimDrag();
}
}
onSizeChanged(getWidth(), getHeight(),0, 0);break;caseMotionEvent.ACTION_UP:if(mIsDragging)
{
trackTouchEvent(event);
onStopTrackingTouch();
setPressed(false);
}else{//Touch up when we never crossed the touch slop threshold//should//be interpreted as a tap-seek to that location.
onStartTrackingTouch();
trackTouchEvent(event);
onStopTrackingTouch();
}
onSizeChanged(getWidth(), getHeight(),0, 0);//ProgressBar doesn't know to repaint the thumb drawable//in its inactive state when the touch stops (because the//value has not apparently changed)
invalidate();break;
}return true;
}private voidtrackTouchEvent(MotionEvent event)
{final int height =getHeight();final int top =getPaddingTop();final int bottom =getPaddingBottom();final int available = height - top -bottom;int y = (int) event.getY();floatscale;float progress = 0;//下面是最小值
if (y > height -bottom)
{
scale= 0.0f;
}else if (y
{
scale= 1.0f;
}else{
scale= (float) (available - y + top) / (float) available;
progress=mTouchProgressOffset;
}final int max =getMax();
progress+= scale *max;
setProgress((int) progress);
}/*** This is called when the user has started touching this widget.*/
voidonStartTrackingTouch()
{
mIsDragging= true;
}/*** This is called when the user either releases his touch or the touch is
* canceled.*/
voidonStopTrackingTouch()
{
mIsDragging= false;
}private voidattemptClaimDrag()
{
ViewParent p=getParent();if (p != null)
{
p.requestDisallowInterceptTouchEvent(true);
}
}
@Overridepublic synchronized void setProgress(intprogress)
{super.setProgress(progress);
onSizeChanged(getWidth(), getHeight(),0, 0);
}
}