The Android system has its own drag bar (Seekbar) only horizontally, where a vertical seekbar is shared.
The principle is simple:
(1) to exchange width and height when measuring the size of the control (including when the control is found to be changed)
(2) Rotate the canvas 90 degrees clockwise while drawing, and then drag the bar counterclockwise to rotate 90 degrees, in order to ensure that the canvas is drawn from the origin of the canvas to move up the view height
(3) Customize the touch event to modify the value of the progress variable according to the relative position of the touch.
Code sharing is as follows (this code is a long time ago on the internet, the Foreigner wrote):
The import android. The content. The Context;
The import android. Graphics. Canvas;
The import android. Util. AttributeSet;
The import android. View. MotionEvent;
The import android. View. ViewConfiguration;
The import android. View. ViewParent;
The import android. Widget. SeekBar;
/ * *
* drag the bar vertically
* /
Public class VerticalSeekBar extends SeekBar {
Private Boolean mIsDragging;
Private float mTouchDownY;
Private int mScaledTouchSlop;
Private Boolean isInScrollingContainer = false;
Public Boolean isInScrollingContainer () {
Return isInScrollingContainer;
}
Public void setInScrollingContainer(Boolean isInScrollingContainer) {
Enclosing isInScrollingContainer = isInScrollingContainer;
}
/ * *
* On touch, this offset plus the scaled value from the position of the
* the URL: http://www.bianceng.cn/OS/extra/201609/50429.htm
* touch will form the progress value. Usually 0.
* /
Float mTouchProgressOffset;
Public VerticalSeekBar(Context, AttributeSet attrs, int defStyle) {
Super (context, attrs, defStyle);
MScaledTouchSlop = ViewConfiguration. Get (context). GetScaledTouchSlop ();
}
Public VerticalSeekBar(Context Context, AttributeSet attrs) {
Super (context, attrs);
}
Public VerticalSeekBar Context (Context) {
Super (context);
}
@ Override
Protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Super. OnSizeChanged (h, w, oldh, oldw);
}
@ Override
Protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Super. OnMeasure (heightMeasureSpec, widthMeasureSpec);
SetMeasuredDimension (getMeasuredHeight (), getMeasuredWidth ());
}
@ Override
Protected synchronized void onDraw(Canvas Canvas) {
Canvas. Rotate (90);
Canvas. Translate (0 - getWidth ());
Super. Ontouch (canvas);
}
@ Override
Public Boolean onTouchEvent(MotionEvent event) {
If (! IsEnabled ()) {
Return false;
}
The switch (event. GetAction ()) {
Case MotionEvent. ACTION_DOWN:
If (isInScrollingContainer ()) {
MTouchDownY = event. GetY ();
} else {
SetPressed (true);
Invalidate ().
OnStartTrackingTouch ();
TrackTouchEvent (event);
AttemptClaimDrag ();
OnSizeChanged (getWidth () and getHeight (), 0, 0).
}
Break;
Case MotionEvent. 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 () and getHeight (), 0, 0).
Break;
Case MotionEvent. 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 () and 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 necessarily changed)
Invalidate ().
Break;
}
Return true;
}
Private void trackTouchEvent(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 ();
Float scale;
Float progress = 0;
If (y > height-bottom) {
Scale = 0.0 f;
} else if (y < top) {
Scale = 1.0 f;
} else {
Scale = (float) (available-y + top)/(float) available;
Progress = mTouchProgressOffset;
}
Final int Max = getMax();
// progress += scale * Max;
Progress = math.round (Max * (1-scale) -progress);
SetProgress (progress) (int);
}
/ * *
* This is called when the user has started touching This widget.
* /
Void onStartTrackingTouch () {
MIsDragging = true;
}
/ * *
* This is called when the user either releases his touch or the touch is
* canceled.
* /
Void onStopTrackingTouch () {
MIsDragging = false;
}
Private void attemptClaimDrag () {
ViewParent p = getParent();
if (p != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
}