自定义 View 循环滚动刻度控件
LoopScaleView
先看效果圖:
enter description hereLoopScaleView 是一個(gè)自定義的刻度尺風(fēng)格的選值控件,從上面的動(dòng)圖大家可以看到 LoopScaleView 的運(yùn)行效果.可以設(shè)置屏幕內(nèi)顯示的刻度數(shù),也可以設(shè)置每一個(gè)刻度代表的值得大小。
LoopScaleView.class
Nested class
| OnValueChangeListener | 刻度取值監(jiān)聽接口 |
Public methods
| getItemsCount() | int | 獲取總的刻度數(shù) |
| setCursorColor(int color) | void | 設(shè)置游標(biāo)顏色(游標(biāo)不采用圖片時(shí)) |
| setCursorWidth(int width) | void | 設(shè)置游標(biāo)寬度(同上) |
| setCursorMap(Bitmap map) | void | 設(shè)置圖片作為游標(biāo) |
| setScaleWidth(int scaleWidth) | void | 設(shè)置刻度寬度 |
| setShowItemSize(int showItemSize) | void | 設(shè)置屏幕內(nèi)可見的大刻度數(shù) |
| setScaleHeight(float scaleHeight) | void | 設(shè)置刻度的高度 |
| setLineColor(int lineColor) | void | 設(shè)置底部直線的顏色 |
| setScaleTextColor(int scaleTextColor) | void | 設(shè)置刻度標(biāo)值的顏色 |
| setScaleTextSize(int scaleTextSize) | void | 設(shè)置刻度標(biāo)值的文字大小 |
| setMaxValue(int maxValue) | void | 設(shè)置最大值 |
| setOneItemValue(int oneItemValue) | void | 設(shè)置一個(gè)刻度表示的值的大小 |
| setCurrentValue(int currValue) | void | 設(shè)置當(dāng)前的值 |
分解剖析
- onMeasure 方法中初始化一個(gè)刻度的像素寬度,整個(gè)視圖的寬度 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);viewHeight = MeasureSpec.getSize(heightMeasureSpec);//一個(gè)小刻度的寬度(十進(jìn)制,每5個(gè)小刻度為一個(gè)大刻度)scaleDistance = getMeasuredWidth() / (showItemSize * 5);//尺子長(zhǎng)度總的個(gè)數(shù)*一個(gè)的寬度viewWidth = maxValue / oneItemValue * scaleDistance;maxX = getItemsCount() * scaleDistance;minX = -maxX;}復(fù)制代碼
- onDraw() 方法重寫繪制 ScaleView 的視圖 protected void onDraw(Canvas canvas) {canvas.clipRect(getPaddingStart(), getPaddingTop(), getWidth() - getPaddingRight(), viewHeight - getPaddingBottom());// 繪制底部線條drawLine(canvas);// 繪制游標(biāo)drawCursor(canvas);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(scaleWidth);// 繪制反向的一個(gè)刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 為繪制刻度線的方法drawScale(canvas, i, -1);}//繪制正向的一個(gè)刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 為繪制刻度線的方法drawScale(canvas, i, 1);}}復(fù)制代碼可以看出上面的繪制過(guò)程,實(shí)際上是繪制出了兩個(gè)刻度尺。經(jīng)過(guò)上面的步驟,靜止?fàn)顟B(tài)下的 ScaleView 已經(jīng)繪制完成,接下來(lái)就是要讓他動(dòng)起來(lái)了
手勢(shì)識(shí)別來(lái)處理滑動(dòng)
/*** 滑動(dòng)手勢(shì)處理*/private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {public boolean onDown(MotionEvent e) {return true;}//滾動(dòng)事件public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {scrollView(distanceX);return true;}//快速滑動(dòng)時(shí)間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;}public boolean onSingleTapUp(MotionEvent e) {return super.onSingleTapUp(e);}};復(fù)制代碼
在 onTouchEvent() 方法中將觸摸事件交給手勢(shì)識(shí)別 GestureDetector.SimpleOnGestureListener 來(lái)處理:上述代碼主要注意兩個(gè)地方:onScroll() 和 onFling()。當(dāng)正常左右滑動(dòng)時(shí),觸發(fā) onScroll 方法調(diào)用 srcollView(float distance) 對(duì)整個(gè)視圖進(jìn)行重繪。當(dāng)快速慣性滑動(dòng)時(shí)通過(guò) Scroller 讓慣性滑動(dòng)變得流暢,慣性滑動(dòng)的狀態(tài)更新是通過(guò) Handler 進(jìn)行不斷的查詢 Scroller 的執(zhí)行狀態(tài)得到的,當(dāng) Scroller 執(zhí)行完慣性滑動(dòng)的動(dòng)畫到達(dá)目的地時(shí),停止 Handler 的查詢?nèi)蝿?wù),當(dāng) onFling 多次觸發(fā)時(shí)只會(huì)執(zhí)行第一次的狀態(tài)。
- 循環(huán)滾動(dòng)的實(shí)現(xiàn)
開始說(shuō)到的繪制了正向反向兩個(gè)方向的刻度尺即是為了實(shí)現(xiàn)循環(huán)滾動(dòng)而設(shè)定的,在 drawScale() 方法中有如下代碼: 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);}復(fù)制代碼當(dāng) currLocation 加上可視視圖一半的距離大于刻度尺的寬度 viewWidth 或者 currLocation 減去可視視圖一半的距離小于 -viewWidth 時(shí)(即正向或者反向滑到最大/最小值時(shí))通過(guò)為 currLocation 重新賦值將刻度值重置,來(lái)達(dá)到循環(huán)滾動(dòng)的目的.如果到達(dá)臨界點(diǎn)時(shí)是在 Scroller 執(zhí)行快速滑動(dòng)的過(guò)程則重置之后需要再為 Scroller 重新設(shè)置初速度來(lái)達(dá)到流暢的滑動(dòng).
基本思路就是上面所說(shuō)的這樣了,詳細(xì)操作大家自己查看 LoopScaleView 的源碼。接入使用
project's build.gradle (工程的 build.gradle)allprojects {repositories {jcenter()maven{url "http://dl.bintray.com/huxinyu/maven"}} }復(fù)制代碼module's build.gradle (模塊的build.gradle)dependencies {compile 'com.pandaq:loopscale:1.0.1' }復(fù)制代碼 - xml 文件中進(jìn)行屬性配置,這些屬性也可以通過(guò) Java 代碼進(jìn)行修改 <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"/>復(fù)制代碼
最后
覺得本文對(duì)你有幫助
簡(jiǎn)書PandaQ404
掘金PandaQ
GithubPandaQAQ
持續(xù)分享中,歡迎關(guān)注和 star。。。
總結(jié)
以上是生活随笔為你收集整理的自定义 View 循环滚动刻度控件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 梦到出门打工什么意思
- 下一篇: vxlan 资料及其在 neutron