欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的示例代碼

 更新時(shí)間:2023年06月27日 10:02:15   作者:二流小碼農(nóng)  
這篇文章主要為大家詳細(xì)介紹了如何利用Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的效果,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下

拿到下面的UI效果圖,給我的第一印象就是這實(shí)現(xiàn)起來(lái)也太簡(jiǎn)單了吧,SeekBar輕輕松松就搞定了,換個(gè)thumb,加個(gè)漸變不就完成了,說(shuō)搞就搞,搞著搞著就抑郁了,底部坐標(biāo)尺還能搞,等比例分割后,在SeekBar下面多設(shè)置幾個(gè)TextView就行了,中間的等比例小分割線怎么搞?而且滑動(dòng)前滑動(dòng)后都需要有,并且,左右的分割線還要留出一小段間距,漸變顏色要跟著滑動(dòng)的距離進(jìn)行展示,而不是整個(gè)寬度展示,在多種條件下,SeekBar就很難滿足這個(gè)需求了,怎么辦?只能自定義了。

還是按照慣例,粗略的列一個(gè)大綱:

1、分析要素,確定實(shí)現(xiàn)方案

2、主要代碼進(jìn)行刨析

3、開(kāi)源地址及使用方式

4、總結(jié)

一、分析要素,確定實(shí)現(xiàn)方案

Canvas繪制這樣的一個(gè)可拖拽坐標(biāo)尺,基本上可以拆分出四部分,第一部分就是背景和默認(rèn)的離散間隔,第二部分是移動(dòng)的背景和離散間隔,第三部分是移動(dòng)的圖片也就是thumb,最后一部分是底部的文字坐標(biāo)。

四部分基本上就繪制出來(lái)了,但是除了繪制之外,還需要考慮一下其他的因素,比如高度,比如手指的移動(dòng)事件等。

1、設(shè)置默認(rèn)高度

設(shè)置默認(rèn)高度的原因,是為了讓View更好的展示一個(gè)合適的尺寸,不至于設(shè)置wrap_content時(shí)不展示,具體的設(shè)置可以根據(jù)當(dāng)前設(shè)置的模式來(lái)控制,關(guān)于模式呢,有三種,這個(gè)在之前的文章中介紹過(guò),這里就不詳細(xì)介紹了,當(dāng)控件設(shè)置wrap_content時(shí),此時(shí)的模式為MeasureSpec.AT_MOST,在這個(gè)模式下,我們就要給一個(gè)默認(rèn)的高度。

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        var windowHeight = heightMeasureSpec
        if (heightMode == MeasureSpec.AT_MOST) {
            windowHeight = mDefaultHeight.toInt()//默認(rèn)的高度
        }
        setMeasuredDimension(widthMeasureSpec, windowHeight)
    }

2、拖動(dòng)事件

實(shí)現(xiàn)拖動(dòng)效果,我們就需要監(jiān)聽(tīng)用戶的手指移動(dòng)事件了,也就是在自定義View中我們要重寫onTouchEvent方法,在這個(gè)方法里,需要針對(duì)手指的按下、抬起、移動(dòng)做相應(yīng)的處理。

在onTouchEvent里我做了如下處理,一是直接返回,不執(zhí)行事件的消費(fèi),目的是讓自定義View可實(shí)現(xiàn)靜態(tài)展示和動(dòng)態(tài)展示兩種效果,通過(guò)一個(gè)變量mProgressIsIntercept來(lái)控制;第二個(gè)是解決與父View的滑動(dòng)沖突事件,在有橫向或者縱向滑動(dòng)事件時(shí),在拖動(dòng)的時(shí)候,難免會(huì)有沖突,那么就需要通知父View不要消費(fèi)事件,也就是執(zhí)行requestDisallowInterceptTouchEvent方法。

所有的拖拽效果,都是在move事件,不斷的改變坐標(biāo)執(zhí)行更新UI的方式實(shí)現(xiàn)的,mMoveProgress就是手指移動(dòng)的坐標(biāo)。

onTouchEvent(event: MotionEvent?): Boolean {
        super.onTouchEvent(event)
        //如果為true直接返回,不進(jìn)行拖拽
        if (mProgressIsIntercept) {
            return mProgressIsIntercept
        }
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> {
                parent.requestDisallowInterceptTouchEvent(mDisallowIntercept)
                val downX = getChangeX(event.x)
                val startX = mMoveOldX - mProgressMarginLeftRight
                val endX = mMoveOldX + mProgressMarginLeftRight
                return downX in startX..endX
            }
            MotionEvent.ACTION_MOVE -> {
                //移動(dòng)
                var moveX = getChangeX(event.x)
                //滑動(dòng)至最右邊
                //計(jì)算最后邊的坐標(biāo)
                val viewWidth = getViewWidth()
                if (moveX >= viewWidth) {
                    moveX = viewWidth
                }
                mMoveProgress = moveX
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                //手指談起
                mMoveOldX = getChangeX(event.x)
                val viewWidth = getViewWidth()
                if (mMoveOldX >= viewWidth) {
                    mMoveOldX = viewWidth
                }
            }
        }
        return true
    }

二、主要代碼進(jìn)行刨析

1、繪制背景

背景沒(méi)什么好說(shuō)的,就是一個(gè)簡(jiǎn)單的圓角矩形,使用drawRoundRect繪制即可,需要確定的是左上右下的間距。

 /**
     * AUTHOR:AbnerMing
     * INTRODUCE:繪制背景
     */
    private fun canvasBackground(canvas: Canvas) {
        mPaint!!.color = mProgressBackground
        val rect = RectF().apply {
            left = mProgressMarginLeftRight
            top = mProgressMarginTopBottom
            right = width.toFloat() - mProgressMarginLeftRight
            bottom = mProgressHeight + mProgressMarginTopBottom
        }
        canvas.drawRoundRect(rect, mProgressRadius, mProgressRadius, mPaint!!)
    }

2、繪制離散間隔

離散間隔,需要確定,間隔數(shù),然后根據(jù)間隔數(shù)量,動(dòng)態(tài)的計(jì)算每個(gè)間隔的位置,可以使用drawLine繪制一個(gè)小小的豎線,豎線也需要確定距離上下的距離和自身的寬度;特殊情況下,離散間隔,在滑動(dòng)前后的顏色是不一樣的,所以這里也做了一個(gè)動(dòng)態(tài)改變顏色的判斷。

 /**
     * AUTHOR:AbnerMing
     * INTRODUCE:繪制離散間隔
     */
    private fun canvasIntervalLine(canvas: Canvas, isCanvas: Boolean) {
        val rect =
            (width - mProgressMarginLeftRight * 2 - mIntervalParentLeftRight * 2) / mIntervalSize
        if (isCanvas) {
            mPaint!!.color = mIntervalSelectColor
        } else {
            mPaint!!.color = mIntervalColor
        }
        mPaint!!.strokeWidth = mIntervalWidth
        for (a in 0..mIntervalSize) {
            val x = (rect * a) + mProgressMarginLeftRight + mIntervalParentLeftRight
            val y = mIntervalMarginTopBottom + mProgressMarginTopBottom
            canvas.drawLine(
                x,
                y,
                x,
                mProgressHeight + mProgressMarginTopBottom - mIntervalMarginTopBottom,
                mPaint!!
            )
        }
    }

3、繪制移動(dòng)thumb

關(guān)于thumb,首先要確定的就是大小,如果設(shè)置了寬高,那么就需要使用Bitmap重新設(shè)置高度,改變thumb的坐標(biāo),只需要不斷的改變圖片的left坐標(biāo)點(diǎn)即可,也就是通過(guò)上述的Move事件的中移動(dòng)坐標(biāo)來(lái)設(shè)置。

 /**
     * AUTHOR:AbnerMing
     * INTRODUCE:繪制移動(dòng)的圖標(biāo)
     */
    private fun canvasMoveIcon(canvas: Canvas) {
        mProgressThumb?.let {
            var decodeResource = BitmapFactory.decodeResource(resources, it)
            mProgressThumbWidth = decodeResource.width
            if (mThumbWidth != 0f) {
                val height: Int = decodeResource.height
                // 設(shè)置想要的大小
                val newWidth = mThumbWidth
                val newHeight = mThumbHeight
                // 計(jì)算縮放比例
                val scaleWidth = newWidth / width
                val scaleHeight = newHeight / height
                // 取得想要縮放的matrix參數(shù)
                val matrix = Matrix()
                matrix.postScale(scaleWidth, scaleHeight)
                // 得到新的圖片
                decodeResource =
                    Bitmap.createBitmap(decodeResource, 0, 0, width, height, matrix, true)
            }
            var mThumpLeft = mMoveProgress
            if (mThumpLeft < (mProgressThumbWidth / 2 - mIntervalParentLeftRight + mProgressThumbSpacing)) {
                mThumpLeft =
                    mProgressThumbWidth / 2 - mIntervalParentLeftRight + mProgressThumbSpacing
            }
            if (mThumpLeft > (getViewWidth() - mIntervalParentLeftRight + mProgressThumbSpacing)) {
                mThumpLeft = getViewWidth() - mIntervalParentLeftRight + mProgressThumbSpacing
            }
            canvas.drawBitmap(
                decodeResource, mThumpLeft, mThumbMarginTop, mIconPaint!!
            )
        }
    }

4、繪制移動(dòng)進(jìn)度

移動(dòng)的進(jìn)度,和背景的繪制是一樣的,只不過(guò)需要按照手指的坐標(biāo)一點(diǎn)一點(diǎn)的移動(dòng)距離,也就是不斷的改變右邊的坐標(biāo)值,同樣的,也是通過(guò)Move事件中的mMoveProgress進(jìn)度來(lái)動(dòng)態(tài)的計(jì)算。進(jìn)度的漸變比較簡(jiǎn)單,使用的是畫筆的shader屬性,當(dāng)前使用的是橫向的線性漸變LinearGradient。

/**
     * AUTHOR:AbnerMing
     * INTRODUCE:繪制進(jìn)度
     */
    private fun canvasMoveProgress(canvas: Canvas) {
        //為空
        if (mColorArray.isEmpty()) {
            mColorArray = intArrayOf(
                ContextCompat.getColor(context, R.color.text_ff3e3e93),
                ContextCompat.getColor(context, R.color.text_ff8548d2),
            )
        }
        val linearShader = LinearGradient(
            0f,
            0f,
            mMoveProgress + mProgressMarginLeftRight,
            mProgressHeight,
            mColorArray,
            floatArrayOf(0f, 1f),
            Shader.TileMode.CLAMP
        )
        mProgressPaint!!.shader = linearShader
        //等于0時(shí)
        val rect = RectF()
        rect.left = mProgressMarginLeftRight
        rect.top = mProgressMarginTopBottom
        rect.right = mMoveProgress + mProgressMarginLeftRight
        rect.bottom = mProgressHeight + mProgressMarginTopBottom
        canvas.drawRoundRect(rect, mProgressRadius, mProgressRadius, mProgressPaint!!)
        //計(jì)算比例
        mGraduationResult =
            ((mMoveProgress / getViewWidth()) * mMaxProgress).roundToInt()//(endProgress * mMaxProgress).roundToInt()
        if (mGraduationResult < 1) {
            mGraduationResult = if (mGraduationSectionZero) {
                0
            } else {
                1
            }
        }
        if (mGraduationResult >= mMaxProgress) {
            mGraduationResult = mMaxProgress
        }
        mMoveProgressCallback?.invoke(mGraduationResult)
    }

5、繪制文字刻度

其實(shí)大家可以發(fā)現(xiàn),離散間隔和底部的坐標(biāo)文字刻度,其實(shí)是一一對(duì)應(yīng)的,既然是相互關(guān)聯(lián),我們直接放到一起就可以,也就是在遍歷離散間隔的時(shí)候,我們直接繪制底部的坐標(biāo)尺刻度。

坐標(biāo)刻度,有四種效果,第一種是不要刻度值,第二種是只要開(kāi)始和結(jié)尾刻度值,第三種是展示所有的刻度值,第四種是刻度值是從0還是從1開(kāi)始。

mIsGraduation是用于判斷是否需要刻度值的變量,為true則需要繪制,否則就不繪制,也就是不需要刻度值。mHideGraduationSectionCenter為隱藏中間刻度的變量,為true隱藏,否則為不隱藏,具體的代碼如下:

 /**
     * AUTHOR:AbnerMing
     * INTRODUCE:繪制離散間隔
     */
    private fun canvasIntervalLine(canvas: Canvas, isCanvas: Boolean) {
        val rect =
            (width - mProgressMarginLeftRight * 2 - mIntervalParentLeftRight * 2) / mIntervalSize
        if (isCanvas) {
            mPaint!!.color = mIntervalSelectColor
        } else {
            mPaint!!.color = mIntervalColor
        }
        mPaint!!.strokeWidth = mIntervalWidth
        for (a in 0..mIntervalSize) {
            val x = (rect * a) + mProgressMarginLeftRight + mIntervalParentLeftRight
            val y = mIntervalMarginTopBottom + mProgressMarginTopBottom
            canvas.drawLine(
                x,
                y,
                x,
                mProgressHeight + mProgressMarginTopBottom - mIntervalMarginTopBottom,
                mPaint!!
            )
            //繪制刻度值
            if (mIsGraduation && isCanvas) {
                if (mHideGraduationSectionCenter && (a != 0 && a != mIntervalSize)) {
                    //隱藏中間
                    continue
                }
                var graduation = a * mGraduationSection
                //是否從0開(kāi)始記錄
                if (graduation == 0 && !mGraduationSectionZero) {
                    graduation = 1
                }
                //如果移動(dòng)到了,改變顏色
                if (mGraduationResult >= graduation && mGraduationResult < graduation + mGraduationSection) {
                    mGraduationPaint?.color = mGraduationSelectTextColor
                } else {
                    mGraduationPaint?.color = mGraduationTextColor
                }
                val text = graduation.toString()
                val rectText = Rect()
                mGraduationPaint!!.getTextBounds(text, 0, text.length, rectText)
                val textWidth = rectText.width()
                val textHeight = rectText.height()
                canvas.drawText(
                    text,
                    x - textWidth / 2,
                    mProgressHeight + mProgressMarginTopBottom * 2 + textHeight + mGraduationMarginTop,
                    mGraduationPaint!!
                )
            }
        }
    }

三、開(kāi)源地址及使用方式

目前已經(jīng)上傳到了Github,本身就一個(gè)簡(jiǎn)單的類,沒(méi)多少東西,需要的鐵子,可以直接查看源碼即可。

地址:github.com/AbnerMing888/MoveProgress

如果懶得下載源碼,想直接使用,沒(méi)得問(wèn)題,我已經(jīng)上傳到了遠(yuǎn)程Maven,大家可以依賴使用。

1、在你的根項(xiàng)目下的build.gradle文件下,引入maven。

allprojects {
    repositories {
        maven { url "https://gitee.com/AbnerAndroid/almighty/raw/master" }
    }
}

2、在你需要使用的Module中build.gradle文件下,引入依賴。

dependencies {
    implementation 'com.vip:moveprogress:1.0.0'
}

3、XML引入即可

 <com.vip.moveprogress.MoveProgress
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:ms_graduation_hide_center="true" />

相關(guān)屬性

屬性類型概述
ms_heightdimensionView視圖的高度
ms_progress_heightdimension進(jìn)度條的高度
ms_progress_thumbreference進(jìn)度條的Icon
ms_progress_margin_top_bottomdimension進(jìn)度條距離icon的上下距離
ms_progress_margin_left_rightdimension進(jìn)度條距離左右的邊距
ms_progress_radiusdimension進(jìn)度條的圓角
ms_progress_backgroundcolor進(jìn)度條的背景顏色
ms_interval_colorcolor間隔線顏色
ms_interval_select_colorcolor間隔線選中顏色
ms_interval_parent_margin_left_rightdimension間隔線距離父左右
ms_interval_sizeinteger間隔線數(shù)量
ms_interval_widthdimension間隔線寬度
ms_interval_margin_top_bottomdimension間隔線上下邊距
ms_progress_move_colorreference定義的移動(dòng)顏色
ms_progress_maxinteger最大進(jìn)度
ms_progress_defaultinteger默認(rèn)進(jìn)度
ms_is_graduationboolean是否顯示刻度尺
ms_graduation_text_sizedimension刻度尺文字大小
ms_graduation_text_colorcolor刻度尺文字顏色
ms_graduation_select_text_colorcolor刻度尺文字選中顏色
ms_graduation_sectioninteger刻度值段
ms_graduation_section_zeroboolean刻度值段從零開(kāi)始
ms_graduation_hide_centerboolean刻度值段中間是否隱藏
ms_graduation_margin_topdimension刻度值距離上邊的距離
ms_progress_thumb_widthdimensionicon的寬
ms_progress_thumb_heightdimensionicon的高
ms_progress_thumb_margin_topdimensionicon距離上邊的高度
ms_progress_thumb_spacingdimensionicon的內(nèi)邊距
ms_progress_disallow_interceptboolean是否攔截
ms_progress_is_interceptboolean是否禁止拖拽

相關(guān)方法

方法參數(shù)概述
getProgress無(wú)參返回當(dāng)前進(jìn)度
changeProgressInt改變當(dāng)前進(jìn)度
getMoveProgress返回Int回調(diào)函數(shù)
setProgressIsInterceptBoolean設(shè)置是否進(jìn)行攔截

四、總結(jié)

關(guān)于漸變,需要注意,漸變的范圍不是默認(rèn)的從左到右固定的距離,而是從左到手指滑動(dòng)的距離,這一點(diǎn)需要注意,也就是在設(shè)置漸變的時(shí)候,終止的X坐標(biāo)需要根據(jù)手勢(shì)的左邊動(dòng)態(tài)設(shè)置。

從這個(gè)簡(jiǎn)單的拖拽進(jìn)度條,我們可以了解到,canvas繪制線,圓角矩形,圖片以及和手勢(shì)結(jié)合的相關(guān)知識(shí)點(diǎn),本身并沒(méi)有難點(diǎn)。

以上就是Android實(shí)現(xiàn)可拖拽帶有坐標(biāo)尺進(jìn)度條的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Android可拖拽進(jìn)度條的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android實(shí)現(xiàn)懸浮可拖拽的Button

    Android實(shí)現(xiàn)懸浮可拖拽的Button

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)懸浮可拖拽的Button,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • 基于android實(shí)現(xiàn)五子棋開(kāi)發(fā)

    基于android實(shí)現(xiàn)五子棋開(kāi)發(fā)

    這篇文章主要為大家詳細(xì)介紹了基于android實(shí)現(xiàn)五子棋開(kāi)發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • Android Flutter實(shí)現(xiàn)原理淺析

    Android Flutter實(shí)現(xiàn)原理淺析

    這篇文章主要介紹了Android Flutter的實(shí)現(xiàn)原理是怎么樣的,flutter可以說(shuō)是當(dāng)下最流行的跨平臺(tái)技術(shù)了,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • android中sqlite的按條件查找的小例子

    android中sqlite的按條件查找的小例子

    android中內(nèi)嵌輕量級(jí)數(shù)據(jù)庫(kù)sqlite,涉及到的操作無(wú)外乎增刪改查,今天就來(lái)說(shuō)一說(shuō)其中的查找操作,更多的時(shí)候我們用到的查找是要按條件查找的 例如表的結(jié)構(gòu)如下:
    2013-06-06
  • Android模仿知乎的回答詳情頁(yè)的動(dòng)畫效果

    Android模仿知乎的回答詳情頁(yè)的動(dòng)畫效果

    這篇文章主要介紹了Android模仿“知乎”的回答詳情頁(yè)的動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 使用IntelliJ IDEA 配置安卓(Android)開(kāi)發(fā)環(huán)境的教程詳解(新手必看)

    使用IntelliJ IDEA 配置安卓(Android)開(kāi)發(fā)環(huán)境的教程詳解(新手必看)

    這篇文章主要介紹了使用IntelliJ IDEA 配置安卓(Android)開(kāi)發(fā)環(huán)境的教程詳解(新手必看),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Android編譯出現(xiàn)Warning:Mapping?new?ns?to?old?ns報(bào)錯(cuò)的解決方案

    Android編譯出現(xiàn)Warning:Mapping?new?ns?to?old?ns報(bào)錯(cuò)的解決方案

    android在編譯的過(guò)程中難免會(huì)出現(xiàn)些錯(cuò)誤,下面這篇文章主要給大家介紹了關(guān)于Android編譯出現(xiàn)Warning:Mapping?new?ns?to?old?ns報(bào)錯(cuò)的解決方案,需要的朋友可以參考下
    2023-02-02
  • Android小程序?qū)崿F(xiàn)訪問(wèn)聯(lián)系人

    Android小程序?qū)崿F(xiàn)訪問(wèn)聯(lián)系人

    這篇文章主要為大家詳細(xì)介紹了Android小程序?qū)崿F(xiàn)訪問(wèn)聯(lián)系人,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一
    2020-05-05
  • Android實(shí)現(xiàn)遮罩層(蒙板)效果

    Android實(shí)現(xiàn)遮罩層(蒙板)效果

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)遮罩層效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Android跑馬燈MarqueeView源碼解析

    Android跑馬燈MarqueeView源碼解析

    這篇文章主要為大家詳細(xì)介紹了Android跑馬燈MarqueeView源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01

最新評(píng)論