Android 垂直seekbar
2016-06-01 23:58
337 查看
android系统自带的拖动条(seekbar)只有横向,这里分享一个垂直的seekbar。
原理很简单:
(1)在测量控件大小(包括发现控件大小改变时)时,把宽度和高度互换
(2)在绘制时将画布顺时针旋转90度,即将拖动条逆时针旋转90度,为了保证从画布的原点开始绘制需要将画布上移视图高度
(3)自定义触摸事件,根据触摸的相对位置来修改progress变量的值。
代码分享如下(这个代码是很久以前网上找的,老外写的):
原理很简单:
(1)在测量控件大小(包括发现控件大小改变时)时,把宽度和高度互换
(2)在绘制时将画布顺时针旋转90度,即将拖动条逆时针旋转90度,为了保证从画布的原点开始绘制需要将画布上移视图高度
(3)自定义触摸事件,根据触摸的相对位置来修改progress变量的值。
代码分享如下(这个代码是很久以前网上找的,老外写的):
import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewParent; import android.widget.SeekBar; /** * 竖向拖动条 */ 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) { this.isInScrollingContainer = isInScrollingContainer; } /** * On touch, this offset plus the scaled value from the position of the * touch will form the progress value. Usually 0. */ float mTouchProgressOffset; public VerticalSeekBar(Context 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.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (isInScrollingContainer()) { mTouchDownY = event.getY(); } else { setPressed(true); invalidate(); onStartTrackingTouch(); trackTouchEvent(event); attemptClaimDrag(); onSizeChanged(getWidth(), 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(), 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(), 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 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.0f; } else if (y < top) { scale = 1.0f; } 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((int) progress); } /** * 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); } }
相关文章推荐
- Android ViewPager多页面滑动切换以及底部滑动导航
- RecyclerView中利用GridLayoutManager实现item四周都带有分割线效果(更正版!!!)
- Android socket通信
- [Android] Android使用序列化接口Parcelable、Serializable
- Android开发笔记之SeekBar 时间的显示 快进快退 Mediaplayer
- android无法监听软键盘收起解决方案
- Android 使用service实现多线程断点续传下载
- 简单优雅的使用tablayout和viewpager打造导航栏
- Android模块化编程之引用本地的aar
- Android优秀资源整理合集
- android老知识,我只是忘记了__PreferenceActivity的应用
- 浅谈Android和java中的多线程下载
- Android Material Design 一些属性详解
- Android Cannot perform this operation because the transaction has already been marked successful
- Android基础--报错信息65536
- Android属性动画AnimatorSet源码简单分析
- Android 创建第一个jni文件
- Canvas之基本形状操作
- Canvas之画布操作
- 实习入职第十二天:Android中Bitmap,byte[],Drawable,InputStream相互转化工具类