Android实现滚动刻度尺效果

Android实现滚动刻度尺效果,第1张

概述缘起最近在帮人做一个计步器,其中涉及到身高、体重等信息的采集;我参考了众多app的实现,觉得\"乐动力\"中滑动刻度的方式比较优雅。于是乎,反编译了该app,结果发现它是采用图片的方式实现的,即ScrollView内嵌了

缘起

最近在帮人做一个计步器,其中涉及到身高、体重等信息的采集;我参考了众多app的实现,觉得"乐动力"中滑动刻度的方式比较优雅。于是乎,反编译了该app,结果发现它是采用图片的方式实现的,即ScrollVIEw内嵌了一张带刻度的图片。
个人觉得该方式太不灵活,且对美工的依赖较大,于是便想自定义一个刻度尺控件。

需求分析

绘制刻度,区分整值刻度和普通刻度 红色指针始终在刻度尺的中间,表示当前的刻度 刻度的最大值和最小值可动态设置 刻度尺的高度或宽度可设置,设置后中间刻度不变 可滑动,滑动后当前刻度随之改变

涉及的知识点

VIEw的机制 canvas绘图 Scroller工具类的使用 自定义view的属性 点击、滑动事件的处理

最终效果

由于简书上无法嵌入gif,为不影响效果,请移步github查看,如果觉得不错,帮忙给个star ^_^https://github.com/LichFaker/ScaleView

实现过程

1、新建一个class:HorizontalScaleScrollVIEw, 继承自VIEw

2、在构造方法中获取自定义属性:

protected voID init(AttributeSet attrs) {   // 获取自定义属性   TypedArray ta = getContext().obtainStyledAttributes(attrs,ATTR);   mMin = ta.getInteger(LF_SCALE_MIN,0);   mMax = ta.getInteger(LF_SCALE_MAX,200);   mScalemargin = ta.getDimensionPixelOffset(LF_SCALE_margin,15);   mScaleHeight = ta.getDimensionPixelOffset(LF_SCALE_HEIGHT,20);   ta.recycle();   mScroller = new Scroller(getContext());  }

3、重写onMeasure,计算中间刻度

@OverrIDeprotected 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;}

4、重写onDraw,绘制刻度和指针

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),mRectHeight - mScaleMaxHeight - 20,paint);     k += 10;   } else {     canvas.drawline(i * mScalemargin,mRectHeight - mScaleHeight,paint);    } }}
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,countScale * mScalemargin + finalX,mRectHeight - mScaleMaxHeight - mScaleHeight,paint);}

处理滑动事件

在手指按下时,记录当前的x坐标(针对水平刻度尺)。 在手指滑动过程中,判断当前指针所指的刻度是否已经超出了边界,如果超出,则禁止滑动,同时刷新当前界面。 在手指抬起时,校正当前的刻度。
@OverrIDepublic 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);}

最后的说明

以上只是针对水平滑动刻度的实现,垂直滑动原理一致,在源码中已经实现,其中也有许多不够完善的地方,如:

第一次快速滑动时,可以超出边界,之后则不会; 开放的自定义属性不够(根据具体情况); 可以考虑将水平和垂直的实现,在一个类中完成,因为在实现过程中发现其实有很多代码都是类似的,只是个别参数属性的不同,在坐标系中,垂直可以看成是水平旋转了90°,之后有时间可以朝这个方向尝试下。 总结

以上是内存溢出为你收集整理的Android实现滚动刻度尺效果全部内容,希望文章能够帮你解决Android实现滚动刻度尺效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1146185.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存