自定义设置刻度控件ScaleView的讲解
来源:互联网 发布:xtw100编程器使用说明 编辑:程序博客网 时间:2024/06/05 19:48
1.ScaleView的简介
ScaleView是一个可以设置身高,体重参数的自定义控件,其中也在github上开源,并被广为流传。因为公司最近的项目里要实现这样的需求,今天我就带着大家学习一下这个自定义控件。先上效果图:
2.ScaleView的用法
1.创建自定义BaseScaleView
public abstract class BaseScaleView extends View { public static final int[] ATTR = { R.attr.scale_view_min, R.attr.scale_view_max, R.attr.scale_view_margin, R.attr.scale_view_height, }; public static final int SCALE_MIN = 0; public static final int SCALE_MAX = 1; public static final int SCALE_MARGIN = 2; public static final int SCALE_HEIGHT = 3; protected int mMax; //最大刻度 protected int mMin; // 最小刻度 protected int mCountScale; //滑动的总刻度 protected int mScaleScrollViewRange; protected int mScaleMargin; //刻度间距 protected int mScaleHeight; //刻度线的高度 protected int mScaleMaxHeight; //整刻度线高度 protected int mRectWidth; //总宽度 protected int mRectHeight; //高度 protected Scroller mScroller; protected int mScrollLastX; protected int mTempScale; // 用于判断滑动方向 protected int mMidCountScale; //中间刻度 protected OnScrollListener mScrollListener; public interface OnScrollListener { void onScaleScroll(int scale); } public BaseScaleView(Context context) { super(context); init(null); } public BaseScaleView(Context context, AttributeSet attrs) { super(context, attrs); init(attrs); } public BaseScaleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public BaseScaleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(attrs); } protected void init(AttributeSet attrs) { // 获取自定义属性 TypedArray ta = getContext().obtainStyledAttributes(attrs, ATTR); mMin = ta.getInteger(SCALE_MIN, 0); mMax = ta.getInteger(SCALE_MAX, 200); mScaleMargin = ta.getDimensionPixelOffset(SCALE_MARGIN, 15); mScaleHeight = ta.getDimensionPixelOffset(SCALE_HEIGHT, 20); ta.recycle(); mScroller = new Scroller(getContext()); initVar(); } @Override protected void onDraw(Canvas canvas) { // 画笔 Paint paint = new Paint(); paint.setColor(Color.GRAY); // 抗锯齿 paint.setAntiAlias(true); // 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰 paint.setDither(true); // 空心 paint.setStyle(Paint.Style.STROKE); // 文字居中 paint.setTextAlign(Paint.Align.CENTER); onDrawLine(canvas, paint); onDrawScale(canvas, paint); //画刻度 onDrawPointer(canvas, paint); //画指针 super.onDraw(canvas); } protected abstract void initVar(); // 画线 protected abstract void onDrawLine(Canvas canvas, Paint paint); // 画刻度 protected abstract void onDrawScale(Canvas canvas, Paint paint); // 画指针 protected abstract void onDrawPointer(Canvas canvas, Paint paint); /** * 使用Scroller时需重写 */ @Override public void computeScroll() { super.computeScroll(); // 判断Scroller是否执行完毕 if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); // 通过重绘来不断调用computeScroll invalidate(); } } public void smoothScrollBy(int dx, int dy) { mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy); } public void smoothScrollTo(int fx, int fy) { int dx = fx - mScroller.getFinalX(); int dy = fy - mScroller.getFinalY(); smoothScrollBy(dx, dy); } /** * 设置回调监听 * * @param listener */ public void setOnScrollListener(OnScrollListener listener) { this.mScrollListener = listener; }}
2.创建自定义HorizontalScrollScaleView
public class HorizontalScaleScrollView extends BaseScaleView { public HorizontalScaleScrollView(Context context) { super(context); } public HorizontalScaleScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public HorizontalScaleScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public HorizontalScaleScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void initVar() { mRectWidth = (mMax - mMin) * mScaleMargin; mRectHeight = mScaleHeight * 8; mScaleMaxHeight = mScaleHeight * 2; // 设置layoutParams ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(mRectWidth, mRectHeight); this.setLayoutParams(lp); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height=MeasureSpec.makeMeasureSpec(mRectHeight, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, height); mScaleScrollViewRange = getMeasuredWidth(); mTempScale = mScaleScrollViewRange / mScaleMargin / 2 + mMin; mMidCountScale = mScaleScrollViewRange / mScaleMargin / 2 + mMin; } @Override protected void onDrawLine(Canvas canvas, Paint paint) { canvas.drawLine(0, mRectHeight, mRectWidth, mRectHeight, paint); } @Override protected void onDrawScale(Canvas canvas, Paint paint) { paint.setTextSize(mRectHeight / 4); for (int i = 0, k = mMin; i <= mMax - mMin; i++) { if (i % 10 == 0) { //整值 canvas.drawLine(i * mScaleMargin, mRectHeight, i * mScaleMargin, mRectHeight - mScaleMaxHeight, paint); //整值文字 canvas.drawText(String.valueOf(k), i * mScaleMargin, mRectHeight - mScaleMaxHeight - 20, paint); k += 10; } else { canvas.drawLine(i * mScaleMargin, mRectHeight, i * mScaleMargin, mRectHeight - mScaleHeight, paint); } } } @Override protected void onDrawPointer(Canvas canvas, Paint paint) { paint.setColor(Color.RED); //每一屏幕刻度的个数/2 int countScale = mScaleScrollViewRange / mScaleMargin / 2; //根据滑动的距离,计算指针的位置【指针始终位于屏幕中间】 int finalX = mScroller.getFinalX(); //滑动的刻度 int tmpCountScale = (int) Math.rint((double) finalX / (double) mScaleMargin); //四舍五入取整 //总刻度 mCountScale = tmpCountScale + countScale + mMin; if (mScrollListener != null) { //回调方法 mScrollListener.onScaleScroll(mCountScale); } canvas.drawLine(countScale * mScaleMargin + finalX, mRectHeight, countScale * mScaleMargin + finalX, mRectHeight - mScaleMaxHeight - mScaleHeight, paint); } @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (mScroller != null && !mScroller.isFinished()) { mScroller.abortAnimation(); } mScrollLastX = x; return true; case MotionEvent.ACTION_MOVE: int dataX = mScrollLastX - x; if (mCountScale - mTempScale < 0) { //向右边滑动 if (mCountScale <= mMin && dataX <= 0) //禁止继续向右滑动 return super.onTouchEvent(event); } else if (mCountScale - mTempScale > 0) { //向左边滑动 if (mCountScale >= mMax && dataX >= 0) //禁止继续向左滑动 return super.onTouchEvent(event); } smoothScrollBy(dataX, 0); mScrollLastX = x; postInvalidate(); mTempScale = mCountScale; return true; case MotionEvent.ACTION_UP: if (mCountScale < mMin) mCountScale = mMin; if (mCountScale > mMax) mCountScale = mMax; int finalX = (mCountScale - mMidCountScale) * mScaleMargin; mScroller.setFinalX(finalX); //纠正指针位置 postInvalidate(); return true; } return super.onTouchEvent(event); }}
3.创建自定义VerticalSrollScaleView
public class VerticalScaleScrollView extends BaseScaleView { public VerticalScaleScrollView(Context context) { super(context); } public VerticalScaleScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public VerticalScaleScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public VerticalScaleScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void initVar() { mRectHeight = (mMax - mMin) * mScaleMargin; mRectWidth = mScaleHeight * 8; mScaleMaxHeight = mScaleHeight * 2; // 设置layoutParams ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(mRectWidth, mRectHeight); this.setLayoutParams(lp); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// int width = MeasureSpec.makeMeasureSpec(mRectWidth, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec); mScaleScrollViewRange = getMeasuredHeight(); mTempScale = mScaleScrollViewRange / mScaleMargin / 2 + mMin; mMidCountScale = mScaleScrollViewRange / mScaleMargin / 2 + mMin; } @Override protected void onDrawLine(Canvas canvas, Paint paint) { canvas.drawLine(0, 0, 0, mRectHeight, paint); } @Override protected void onDrawScale(Canvas canvas, Paint paint) { paint.setTextSize(mRectWidth / 4); for (int i = 0, k = mMin; i <= mMax - mMin; i++) { if (i % 10 == 0) { //整值 canvas.drawLine(0, i * mScaleMargin, mScaleMaxHeight, i * mScaleMargin, paint); //整值文字 canvas.drawText(String.valueOf(k), mScaleMaxHeight + 40, i * mScaleMargin + paint.getTextSize() / 3, paint); k += 10; } else { canvas.drawLine(0, i * mScaleMargin, mScaleHeight, i * mScaleMargin, paint); } } } @Override protected void onDrawPointer(Canvas canvas, Paint paint) { paint.setColor(Color.RED); //每一屏幕刻度的个数/2 int countScale = mScaleScrollViewRange / mScaleMargin / 2; //根据滑动的距离,计算指针的位置【指针始终位于屏幕中间】 int finalY = mScroller.getFinalY(); //滑动的刻度 int tmpCountScale = (int) Math.rint((double) finalY / (double) mScaleMargin); //四舍五入取整 //总刻度 mCountScale = tmpCountScale + countScale + mMin; if (mScrollListener != null) { //回调方法 mScrollListener.onScaleScroll(mCountScale); } canvas.drawLine(0, countScale * mScaleMargin + finalY, mScaleMaxHeight + mScaleHeight, countScale * mScaleMargin + finalY, paint); } @Override public boolean onTouchEvent(MotionEvent event) { int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (mScroller != null && !mScroller.isFinished()) { mScroller.abortAnimation(); } mScrollLastX = y; return true; case MotionEvent.ACTION_MOVE: int dataY = mScrollLastX - y; if (mCountScale - mTempScale < 0) { //向下边滑动 if (mCountScale <= mMin && dataY <= 0) //禁止继续向下滑动 return super.onTouchEvent(event); } else if (mCountScale - mTempScale > 0) { //向上边滑动 if (mCountScale >= mMax && dataY >= 0) //禁止继续向上滑动 return super.onTouchEvent(event); } smoothScrollBy(0, dataY); mScrollLastX = y; postInvalidate(); mTempScale = mCountScale; return true; case MotionEvent.ACTION_UP: if (mCountScale < mMin) mCountScale = mMin; if (mCountScale > mMax) mCountScale = mMax; int finalY = (mCountScale - mMidCountScale) * mScaleMargin; mScroller.setFinalY(finalY); //纠正指针位置 postInvalidate(); return true; } return super.onTouchEvent(event); }}
4.Manifest文件申明
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.lichfaker.views.scaleview.MainActivity"> <com.lichfaker.scaleview.HorizontalScaleScrollView android:id="@+id/horizontalScale" android:layout_centerHorizontal="true" android:layout_below="@+id/horizontalScaleValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" app:scale_view_max="200" app:scale_view_min="20" app:scale_view_height="8dip" app:scale_view_margin="5dip" /> <TextView android:id="@+id/horizontalScaleValue" android:layout_centerHorizontal="true" tools:text="50" android:textSize="16sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.lichfaker.scaleview.VerticalScaleScrollView android:id="@+id/verticalScale" android:layout_below="@+id/horizontalScale" android:layout_marginTop="60dp" app:scale_view_max="200" app:scale_view_min="20" app:scale_view_height="8dip" app:scale_view_margin="5dip" android:layout_width="100dp" android:layout_height="200dp" /> <TextView android:id="@+id/verticalScaleValue" android:layout_toRightOf="@+id/verticalScale" android:layout_centerInParent="true" android:layout_marginLeft="60dp" tools:text="50" android:textSize="16sp" android:layout_width="wrap_content" android:layout_height="wrap_content" /></RelativeLayout>
5.主界面MainActivity
public class MainActivity extends AppCompatActivity { TextView mTvHorizontalScale; TextView mTvVerticalScale; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTvHorizontalScale = (TextView) findViewById(R.id.horizontalScaleValue); HorizontalScaleScrollView scaleScrollView = (HorizontalScaleScrollView) findViewById(R.id.horizontalScale); scaleScrollView.setOnScrollListener(new HorizontalScaleScrollView.OnScrollListener() { @Override public void onScaleScroll(int scale) { mTvHorizontalScale.setText("" + scale); } }); mTvVerticalScale = (TextView) findViewById(R.id.verticalScaleValue); VerticalScaleScrollView vScaleScrollView = (VerticalScaleScrollView) findViewById(R.id.verticalScale); vScaleScrollView.setOnScrollListener(new HorizontalScaleScrollView.OnScrollListener() { @Override public void onScaleScroll(int scale) { mTvVerticalScale.setText("" + scale); } }); }}
ok,这样自定义的设置刻度的控件就诞生了,有木有很兴奋!你可以直接把github中scaleview的mudule导入你的工程里面,然后引用该模块,这样开发起来更有效率,当然你可以好好研究一下底层源码,哈哈,好了,我是张星,欢迎您的关注,后期更精彩!源码地址:http://download.csdn.net/detail/zhangxing52077/9695038
1 0
- 自定义设置刻度控件ScaleView的讲解
- Android 自定义控件之 带刻度的进度条
- 自定义控件的讲解
- Slider控件设置刻度,并按刻度进行移动
- 自定义带刻度的seekbar
- 简单的自定义 刻度seekbar?
- 自定义带刻度的SeekBar
- 可以设置刻度的进度条
- 可以设置刻度的进度条
- 刻度设置
- Android自定义带进度的刻度条
- 实时曲线绘图控件ProEssentials使用实例:自定义坐标刻度
- C# 画图控件CHART 自定义坐标轴刻度标签
- Excel2016中设置X轴的刻度
- 自定义控件属性的设置
- HighCharts自定义坐标轴刻度
- 自定义控件学习:设置自定义控件的属性
- 设置刻度、刻度标签和网格
- Android编程权威指南--CriminalIntent笔记及拓展(一)
- 原生JavaScript实现ajax异步请求代码
- 初识设计模式
- shell学习一基础知识的整理
- 网易云信登录与发送消息 C#
- 自定义设置刻度控件ScaleView的讲解
- 关系型数据库小结
- 进程与线程的简述
- 19_Remove Nth Node From End of List徒手尝试#2(Done)
- Android Hook框架Xposed原理与源代码分析
- [C++]函数与编译预处理(一)
- 结构(struct)&联合(union)
- 微信开放平台开发——网页微信扫码登录(OAuth2.0)
- github使用(通过webstorm创建一个nodejs项目的本地git库,推送到github进行管理,(ssh密钥无用户密码方式))