99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學院 頭像
蘋果6袋
6
麥子學院

Android滾動刻度尺實現(xiàn)

發(fā)布時間:2017-06-12 12:06  回復:0  查看:2318   最后回復:2017-06-12 12:06  

本文和大家分享的主要是android中滾動刻度尺的實現(xiàn),一起來看看吧,希望對大家學習android有所幫助。

  最近在幫人做一個計步器,其中涉及到身高、體重等信息的采集;我參考了眾多app的實現(xiàn),覺得"樂動力"中滑動刻度的方式比較優(yōu)雅。于是乎,反編譯了該app,結(jié)果發(fā)現(xiàn)它是采用圖片的方式實現(xiàn)的,即ScrollView內(nèi)嵌了一張帶刻度的圖片。

  個人覺得該方式太不靈活,且對美工的依賴較大,于是便想自定義一個刻度尺控件。

  需求分析

  1. 繪制刻度,區(qū)分整值刻度和普通刻度

  2. 紅色指針始終在刻度尺的中間,表示當前的刻度

  3. 刻度的最大值和最小值可動態(tài)設(shè)置

  4. 刻度尺的高度或?qū)挾瓤稍O(shè)置,設(shè)置后中間刻度不變

  5. 可滑動,滑動后當前刻度隨之改變

  涉及的知識點

  1. View的機制

  2. canvas繪圖

  3. Scroller工具類的使用

  4. 自定義View的屬性

  5. 點擊、滑動事件的處理

  最終效果

  由于簡書上無法嵌入gif,為不影響效果,請移步github查看,如果覺得不錯,幫忙給個star ^_^

  https://github.com/LichFaker/ScaleView

  實現(xiàn)過程

  1. 新建一個classHorizontalScaleScrollView, 繼承自View

  2. 在構(gòu)造方法中獲取自定義屬性:

  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.

  4. 重寫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;

  }

  5.

  6.

  重寫onDraw,繪制刻度和指針

  7.

  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);

  }

  }

  }

  8.

  protected void onDrawPointer(Canvas canvas, Paint paint) {

  paint.setColor(Color.RED);

  //每一屏幕刻度的個數(shù)/2

  int countScale = mScaleScrollViewRange / mScaleMargin / 2;

  //根據(jù)滑動的距離,計算指針的位置【指針始終位于屏幕中間】

  int finalX = mScroller.getFinalX();

  //滑動的刻度

  int tmpCountScale = (int) Math.rint((double) finalX / (double) mScaleMargin);//四舍五入取整

  //總刻度

  mCountScale = tmpCountScale + countScale + mMin;

  if (mScrollListener != null) { //回調(diào)方法

  mScrollListener.onScaleScroll(mCountScale);

  }

  canvas.drawLine(countScale * mScaleMargin + finalX, mRectHeight,

  countScale * mScaleMargin + finalX, mRectHeight - mScaleMaxHeight - mScaleHeight, paint);

  }

  9.

  10.

  處理滑動事件

  11.

  1. 在手指按下時,記錄當前的x坐標(針對水平刻度尺)。

  2. 在手指滑動過程中,判斷當前指針所指的刻度是否已經(jīng)超出了邊界,如果超出,則禁止滑動,同時刷新當前界面。

  3. 在手指抬起時,校正當前的刻度。

  @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) //禁止繼續(xù)向右滑動

  return super.onTouchEvent(event);

  } else if (mCountScale - mTempScale > 0) { //向左邊滑動

  if (mCountScale >= mMax && dataX >= 0) //禁止繼續(xù)向左滑動

  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);

  }

  最后的說明

  以上只是針對水平滑動刻度的實現(xiàn),垂直滑動原理一致,在源碼中已經(jīng)實現(xiàn),其中也有許多不夠完善的地方,如:

  1. 第一次快速滑動時,可以超出邊界,之后則不會;

  2. 開放的自定義屬性不夠(根據(jù)具體情況);

  3. 可以考慮將水平和垂直的實現(xiàn),在一個類中完成,因為在實現(xiàn)過程中發(fā)現(xiàn)其實有很多代碼都是類似的,只是個別參數(shù)屬性的不同,在坐標系中,垂直可以看成是水平旋轉(zhuǎn)了90°,之后有時間可以朝這個方向嘗試下。

 

 

來源:簡書

您還未登錄,請先登錄

熱門帖子

最新帖子

?