LoopScaleView
先看效果圖:
LoopScaleView 是一個自定義的刻度尺風格的選值控件,從上面的動圖大家可以看到 LoopScaleView 的運行效果.可以設置屏幕內顯示的刻度數,也可以設置每一個刻度代表的值得大小。
LoopScaleView.class
Nested class
OnValueChangeListener | 刻度取值監聽接口 |
Public methods
方法名 | 返回值類型 | 說明 |
---|---|---|
getItemsCount() | int | 獲取總的刻度數 |
setCursorColor(int color) | void | 設置游標顏色(游標不采用圖片時) |
setCursorWidth(int width) | void | 設置游標寬度(同上) |
setCursorMap(Bitmap map) | void | 設置圖片作為游標 |
setScaleWidth(int scaleWidth) | void | 設置刻度寬度 |
setShowItemSize(int showItemSize) | void | 設置屏幕內可見的大刻度數 |
setScaleHeight(float scaleHeight) | void | 設置刻度的高度 |
setLineColor(int lineColor) | void | 設置底部直線的顏色 |
setScaleTextColor(int scaleTextColor) | void | 設置刻度標值的顏色 |
setScaleTextSize(int scaleTextSize) | void | 設置刻度標值的文字大小 |
setMaxValue(int maxValue) | void | 設置最大值 |
setOneItemValue(int oneItemValue) | void | 設置一個刻度表示的值的大小 |
setCurrentValue(int currValue) | void | 設置當前的值 |
分解剖析
- onMeasure 方法中初始化一個刻度的像素寬度,整個視圖的寬度
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);viewHeight = MeasureSpec.getSize(heightMeasureSpec);//一個小刻度的寬度(十進制,每5個小刻度為一個大刻度)scaleDistance = getMeasuredWidth() / (showItemSize * 5);//尺子長度總的個數*一個的寬度viewWidth = maxValue / oneItemValue * scaleDistance;maxX = getItemsCount() * scaleDistance;minX = -maxX;}復制代碼
- onDraw() 方法重寫繪制 ScaleView 的視圖
可以看出上面的繪制過程,實際上是繪制出了兩個刻度尺。經過上面的步驟,靜止狀態下的 ScaleView 已經繪制完成,接下來就是要讓他動起來了@Overrideprotected void onDraw(Canvas canvas) {canvas.clipRect(getPaddingStart(), getPaddingTop(), getWidth() - getPaddingRight(), viewHeight - getPaddingBottom());// 繪制底部線條drawLine(canvas);// 繪制游標drawCursor(canvas);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(scaleWidth);// 繪制反向的一個刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 為繪制刻度線的方法drawScale(canvas, i, -1);}//繪制正向的一個刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 為繪制刻度線的方法drawScale(canvas, i, 1);}}復制代碼
手勢識別來處理滑動
在 onTouchEvent() 方法中將觸摸事件交給手勢識別 GestureDetector.SimpleOnGestureListener 來處理:/*** 滑動手勢處理*/private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {return true;}//滾動事件public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {scrollView(distanceX);return true;}//快速滑動時間public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {if (!mScroller.computeScrollOffset()) {mScroller.fling((int) currLocation, 0, (int) (-velocityX / 1.5), 0, minX, maxX, 0, 0);setNextMessage(0);}return true;}@Overridepublic boolean onSingleTapUp(MotionEvent e) {return super.onSingleTapUp(e);}};復制代碼
上述代碼主要注意兩個地方:onScroll() 和 onFling()。當正常左右滑動時,觸發 onScroll 方法調用 srcollView(float distance) 對整個視圖進行重繪。當快速慣性滑動時通過 Scroller 讓慣性滑動變得流暢,慣性滑動的狀態更新是通過 Handler 進行不斷的查詢 Scroller 的執行狀態得到的,當 Scroller 執行完慣性滑動的動畫到達目的地時,停止 Handler 的查詢任務,當 onFling 多次觸發時只會執行第一次的狀態。
- 循環滾動的實現
開始說到的繪制了正向反向兩個方向的刻度尺即是為了實現循環滾動而設定的,在 drawScale() 方法中有如下代碼:
當 currLocation 加上可視視圖一半的距離大于刻度尺的寬度 viewWidth 或者 currLocation 減去可視視圖一半的距離小于 -viewWidth 時(即正向或者反向滑到最大/最小值時)通過為 currLocation 重新賦值將刻度值重置,來達到循環滾動的目的.如果到達臨界點時是在 Scroller 執行快速滑動的過程則重置之后需要再為 Scroller 重新設置初速度來達到流暢的滑動.if (currLocation + showItemSize / 2 * 5 * scaleDistance >= viewWidth) {currLocation = -showItemSize / 2 * 5 * scaleDistance;float speed = mScroller.getCurrVelocity();mScroller.fling((int) currLocation, 0, (int) speed, 0, minX, maxX, 0, 0);setNextMessage(0);} else if (currLocation - showItemSize / 2 * 5 * scaleDistance <= -viewWidth) {currLocation = showItemSize / 2 * 5 * scaleDistance;float speed = mScroller.getCurrVelocity();mScroller.fling((int) currLocation, 0, (int) speed, 0, minX, maxX, 0, 0);setNextMessage(0);}復制代碼
基本思路就是上面所說的這樣了,詳細操作大家自己查看 LoopScaleView 的源碼。接入使用
project's build.gradle (工程的 build.gradle)
module's build.gradle (模塊的build.gradle)allprojects {repositories {jcenter()maven{url "http://dl.bintray.com/huxinyu/maven"}} }復制代碼
dependencies {compile 'com.pandaq:loopscale:1.0.1' }復制代碼
- xml 文件中進行屬性配置,這些屬性也可以通過 Java 代碼進行修改
<com.pandaq.loopscaleview.LoopScaleViewandroid:id="@+id/lsv_4"android:layout_width="match_parent"android:layout_height="50dp"android:layout_margin="8dp"android:background="@drawable/loopscaleview_bg"android:padding="8dp"app:cursorColor="@color/colorAccent"app:maxShowItem="4"app:maxValue="1000"app:oneItemValue="5"app:scaleTextColor="@color/colorPrimary"/>復制代碼
最后
覺得本文對你有幫助
簡書PandaQ404
掘金PandaQ
GithubPandaQAQ
持續分享中,歡迎關注和 star。。。