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 方法中初始化一個刻度的畫素寬度,整個檢視的寬度
@Override protected 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 已經繪製完成,接下來就是要讓他動起來了@Override protected 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() { @Override public 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; } @Override public 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.LoopScaleView android: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。。。