<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
看完效果後,我們先定義控制元件的樣式
<!-- 自定義View的名字 StepView --> <!-- name 屬性名稱 format 格式 string 文字 color 顏色 dimension 字型大小 integer 數位 reference 資源或者顏色 --> <declare-styleable name="StepView"> <attr name="borderWidth" format="dimension" /> <attr name="outColor" format="color" /> <attr name="innerColor" format="color" /> <attr name="unit" format="string" /> <attr name="currentStep" format="integer" /> <attr name="maxStep" format="integer" /> </declare-styleable>
接下來我們自定義一個StepView(記步的View)
package cn.wwj.customview.widget import android.animation.ValueAnimator import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet import android.util.Log import android.util.TypedValue import android.view.animation.AccelerateInterpolator import androidx.appcompat.widget.AppCompatTextView import cn.wwj.customview.R class StepView : AppCompatTextView { /** * 當前走了多少步 */ private var mCurrentStep: Int = 0 /** * 最大走多少步,比如兩萬步 20000步 * 預設100步,有個成語50步笑100步 */ private var mMaxStep: Int = 100 /** * 單位:步 %等 */ private var mUnit: String? /** * 設定圓弧的邊框線寬度 */ private var mBorderWidth: Float = dp2px(6F) /** * 設定外部圓弧的顏色 */ private var mOuterColor: Int = resources.getColor(android.R.color.holo_blue_light) /** * 設定內部圓弧的顏色 */ private var mInnerColor: Int = resources.getColor(android.R.color.holo_red_light) /** * 圓弧畫筆 */ private var mArcPaint: Paint = Paint() /** * 文字畫筆,用於繪畫走了多少步 */ private var mTextPaint: Paint = Paint() /** * 紀錄檔過濾標籤 */ private val TAG = javaClass.simpleName /** * 圓弧起始角度 */ private var mStartAngle = 135F /** * 圓弧從起始角度開始,掃描過的角度 */ private var mSweepAngle = mStartAngle * 2 /** * 比如用於獲取一個圓弧的矩形,onDraw()方法會呼叫多次,不必每次都建立Rect()物件 */ private val mArcRect = RectF() /** * 比如用於獲取文字的大小,onDraw()方法會呼叫多次,不必每次都建立Rect()物件 * 用同一個物件即可 */ private val mTextRect = Rect() /** * 值動畫師 */ private var valueAnimator: ValueAnimator? = null /** * 最大進度 */ private val MAX_PROGRESS = 100F constructor(context: Context) : this(context, null) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { val appearance = context.obtainStyledAttributes(attrs, R.styleable.StepView) mBorderWidth = appearance.getDimension(R.styleable.StepView_borderWidth, mBorderWidth) mOuterColor = appearance.getColor(R.styleable.StepView_outColor, mOuterColor) mInnerColor = appearance.getColor(R.styleable.StepView_innerColor, mInnerColor) mUnit = appearance.getString(R.styleable.StepView_unit) mCurrentStep = appearance.getInt(R.styleable.StepView_currentStep, 0) mMaxStep = appearance.getInt(R.styleable.StepView_maxStep, mMaxStep) appearance.recycle() setPaint() } /** * 設定 圓弧畫筆用於繪製圓弧 和 文字畫筆,用於繪畫走了多少步 */ private fun setPaint() { // 畫筆的顏色 mArcPaint.color = mOuterColor // 抗抖動 mArcPaint.isDither = true // 抗鋸齒 mArcPaint.isAntiAlias = true // 畫筆的樣式描邊,筆劃突出為半圓 mArcPaint.style = Paint.Style.STROKE // 設定描邊的線帽樣式 mArcPaint.strokeCap = Paint.Cap.ROUND // 設定描邊的寬度 mArcPaint.strokeWidth = mBorderWidth // 畫筆的顏色 mTextPaint.color = currentTextColor // 抗抖動 mTextPaint.isDither = true // 抗鋸齒 mTextPaint.isAntiAlias = true // 畫筆的樣式描邊,筆劃突出為半圓 mTextPaint.style = Paint.Style.FILL // 設定描邊的線帽樣式 mTextPaint.strokeCap = Paint.Cap.ROUND // 設定文字大小 mTextPaint.textSize = textSize } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) /** * 獲取控制元件的寬高 */ val widthSize = MeasureSpec.getSize(widthMeasureSpec) val heightSize = MeasureSpec.getSize(heightMeasureSpec) /** * 如果寬度大於高度,取高度 * 否則取寬度 */ val result = if (widthSize > heightSize) { heightSize } else { widthSize } /** * 設定控制元件的寬高 */ setMeasuredDimension(result, result) } override fun onDraw(canvas: Canvas?) { // 將矩形設定為 (0,0,0,0) mArcRect.setEmpty() mTextRect.setEmpty() // 圓弧矩形左邊距,頂邊距,右邊距,底邊距 val left = mBorderWidth / 2 val top = mBorderWidth / 2 val right = width - mBorderWidth / 2 val bottom = height - mBorderWidth / 2 mArcRect.set(left, top, right, bottom) // 繪製外部圓弧 mArcPaint.color = mOuterColor canvas?.drawArc(mArcRect, mStartAngle, mSweepAngle, false, mArcPaint) // 繪製內部部圓弧 mArcPaint.color = mInnerColor val sweepAngle = mCurrentStep * 1F / mMaxStep * mSweepAngle canvas?.drawArc(mArcRect, mStartAngle, sweepAngle, false, mArcPaint) val stepText = if (mUnit != null) { "$mCurrentStep $mUnit" } else { mCurrentStep.toString() } // 獲取文字的寬高 mTextPaint.getTextBounds(stepText, 0, stepText.length, mTextRect) val textX = width / 2F - mTextRect.width() / 2 val textY = height / 2F + getBaseline(mTextPaint) // 繪製文字,第二個引數文字的起始索引,第三個引數要繪製的文字長度 // 開始繪製文字的x 座標 y 座標 canvas?.drawText(stepText, 0, stepText.length, textX, textY, mTextPaint) } /** * @param progress 進入0-100 之間 * @param duration 動畫時長,預設 350毫秒 */ fun setProgress(progress: Int, duration: Long = 350) { valueAnimator?.cancel() valueAnimator = null val step = (progress / MAX_PROGRESS * mMaxStep).toInt() valueAnimator = ValueAnimator.ofInt(mCurrentStep, step.coerceAtMost(mMaxStep)) valueAnimator?.duration = duration valueAnimator?.interpolator = AccelerateInterpolator() valueAnimator?.addUpdateListener { mCurrentStep = it.animatedValue as Int Log.d(TAG, "------$mCurrentStep") invalidate() } valueAnimator?.startDelay = 10 valueAnimator?.start() } /** * @param maxStep 最多走多少步,比如2000步 * @param duration 預設動畫時長200 */ fun setMaxStep(maxStep: Int, duration: Long = 0) { mMaxStep = maxStep val progress = (mCurrentStep * 1F / mMaxStep * 100).toInt() setProgress(progress, duration) } /** * @param currentStep 當前走了多少步 * @param duration 預設動畫時長200 */ fun setCurrentStep(currentStep: Int, duration: Long = 200) { mCurrentStep = currentStep val progress = (mCurrentStep * 1F / mMaxStep * 100).toInt() setProgress(progress, duration) } /** * 檢視從視窗分離時 */ override fun onDetachedFromWindow() { super.onDetachedFromWindow() valueAnimator?.cancel() valueAnimator = null } private fun dp2px(value: Float): Float { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics ) } /** * 計算繪製文字時的基線到中軸線的距離 * @param paint 畫筆 * @return 返回基線的距離 */ private fun getBaseline(paint: Paint): Float { val fontMetrics: Paint.FontMetrics = paint.fontMetrics return (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom } }
繪製圓弧是是從3點中開始,它位於0度。比如我們可以試試繪製0到90度的圓弧,多試試幾次,你很快就能明白了額
繪製文字橫座標是控制元件寬度的一半減去字型寬度的一半,繪製文字的縱座標是控制元件高度的一半加上文字的基線。
文字基線我們看個圖清楚了
Android獲取中線到基線距離的程式碼,實際獲取到的Ascent是負數
/** * 計算繪製文字時的基線到中軸線的距離 * @param paint 畫筆 * @return 返回基線的距離 */ private fun getBaseline(paint: Paint): Float { val fontMetrics: Paint.FontMetrics = paint.fontMetrics return (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom }
專案地址 :https://github.com/githubwwj/MyAndroid
以上就是Android開發Kotlin繪製圓弧計步器範例詳解的詳細內容,更多關於Android Kotlin繪製圓弧計步器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45