Android實(shí)現(xiàn)兩圓點(diǎn)之間來(lái)回移動(dòng)加載進(jìn)度
本文實(shí)例為大家分享了Android實(shí)現(xiàn)兩圓點(diǎn)之間來(lái)回移動(dòng)加載進(jìn)度的具體代碼,供大家參考,具體內(nèi)容如下
一、前言
最近喜歡上自定義控件,喜歡實(shí)現(xiàn)一些簡(jiǎn)約有趣的控件,也好鞏固下以前學(xué)得知識(shí)和不斷的學(xué)習(xí)新知識(shí),程序員嘛,活到老學(xué)到老。
這篇文章接著上一篇文章:Android_自定義控件之水平圓點(diǎn)加載進(jìn)度條,類似的實(shí)現(xiàn)方式,都是些比較簡(jiǎn)單的view繪制。
二、實(shí)現(xiàn)
先看下實(shí)現(xiàn)的效果吧:
說(shuō)下實(shí)現(xiàn)思路:圓點(diǎn)x軸會(huì)有個(gè)位移變化量,當(dāng)位移達(dá)到圓點(diǎn)直徑+圓點(diǎn)間距之和就回改變方向(改變方向就是通過(guò)變化量值不斷增加和不斷減少來(lái)實(shí)現(xiàn)),可能寫(xiě)的有點(diǎn)模糊,接下來(lái)看代碼:
package com.kincai.testcustomview_dotalternatelyprogress; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.util.Log; import android.view.View; /** * Copyright (C) 2015 The KINCAI Open Source Project * . * Create By KINCAI * . * Time 2017-06-16 21:44 * . * Desc 兩個(gè)源點(diǎn)來(lái)回移動(dòng) */ public class DotAlternatelyView extends View { private final String TAG = this.getClass().getSimpleName(); private Paint mPaint = new Paint(); /** * 可視為左邊圓點(diǎn)顏色值 */ private int mLeftColor; /** * 可視為右邊圓點(diǎn)顏色值 */ private int mRightColor; /** * 圓點(diǎn)半徑 */ private int mDotRadius; /** * 圓點(diǎn)間距 */ private int mDotSpacing; /** * 圓點(diǎn)位移量 */ private float mMoveDistance; /** * 圓點(diǎn)移動(dòng)率 */ private float mMoveRate; /** * 以剛開(kāi)始左邊圓點(diǎn)為準(zhǔn) 向右移 */ private final int DOT_STATUS_RIGHT = 0X101; /** * 以剛開(kāi)始左邊圓點(diǎn)為準(zhǔn) 圓點(diǎn)移動(dòng)方向-向左移 */ private final int DOT_STATUS_LEFT = 0X102; /** * 以剛開(kāi)始左邊圓點(diǎn)為準(zhǔn),圓點(diǎn)移動(dòng)方向 */ private int mDotChangeStatus = DOT_STATUS_RIGHT; /** * 圓點(diǎn)透明度變化最大(也就是透明度在255-mAlphaChangeTotal到255之間) */ private int mAlphaChangeTotal = 130; /** * 透明度變化率 */ private float mAlphaChangeRate; /** * 透明度改變量 */ private float mAlphaChange; public DotAlternatelyView(Context context) { this(context, null); } public DotAlternatelyView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public DotAlternatelyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DotAlternatelyView, defStyleAttr, 0); initAttributes(typedArray); typedArray.recycle(); init(); } private void initAttributes(TypedArray Attributes) { mLeftColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_dark_color, ContextCompat.getColor(getContext(), R.color.colorPrimary)); mRightColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_light_color, ContextCompat.getColor(getContext(), R.color.colorAccent)); mDotRadius = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_radius, DensityUtils.dp2px(getContext(), 3)); mDotSpacing = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_spacing, DensityUtils.dp2px(getContext(), 6)); mMoveRate = Attributes.getFloat(R.styleable.DotAlternatelyView_dot_move_rate, 1.2f); } /** * 初始化 */ private void init() { //移動(dòng)總距離/移動(dòng)率 = alpha總變化/x //x = 移動(dòng)率 * alpha總變化 / 移動(dòng)總距離 mAlphaChangeRate = mMoveRate * mAlphaChangeTotal / (mDotRadius * 2 + mDotSpacing); mPaint.setColor(mLeftColor); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.FILL); Log.e(TAG, " aaaa " + mAlphaChangeRate); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //測(cè)量寬高 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; Log.e(TAG, "onMeasure MeasureSpec.EXACTLY widthSize=" + widthSize); } else { //指定最小寬度所有圓點(diǎn)加上間距的寬度, 以最小半徑加上間距算總和再加上最左邊和最右邊變大后的距離 width = (mDotRadius * 2) * 2 + mDotSpacing; Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY widthSize=" + widthSize + " width=" + width); if (widthMode == MeasureSpec.AT_MOST) { width = Math.min(width, widthSize); Log.e(TAG, "onMeasure MeasureSpec.AT_MOST width=" + width); } } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; Log.e(TAG, "onMeasure MeasureSpec.EXACTLY heightSize=" + heightSize); } else { height = mDotRadius * 2; Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY heightSize=" + heightSize + " height=" + height); if (heightMode == MeasureSpec.AT_MOST) { height = Math.min(height, heightSize); Log.e(TAG, "onMeasure MeasureSpec.AT_MOST height=" + height); } } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { //左邊圓點(diǎn)起點(diǎn)x軸 int startPointX = getWidth() / 2 - (2 * mDotRadius * 2 + mDotSpacing) / 2 + mDotRadius; //左邊圓點(diǎn)起點(diǎn)y軸 int startPointY = getHeight() / 2; //向右移 位移要增加對(duì)應(yīng)透明度變化量也需要增加 反之都需要減小 if (mDotChangeStatus == DOT_STATUS_RIGHT) { mMoveDistance += mMoveRate; mAlphaChange += mAlphaChangeRate; } else { mAlphaChange -= mAlphaChangeRate; mMoveDistance -= mMoveRate; } Log.e(TAG, "mAlphaChange " + mAlphaChange); //當(dāng)移動(dòng)到最右 那么需要改變方向 反過(guò)來(lái) if (mMoveDistance >= mDotRadius * 2 + mDotSpacing && mDotChangeStatus == DOT_STATUS_RIGHT) { mDotChangeStatus = DOT_STATUS_LEFT; mMoveDistance = mDotRadius * 2 + mDotSpacing; mAlphaChange = mAlphaChangeTotal; } else if (mMoveDistance <= 0 && mDotChangeStatus == DOT_STATUS_LEFT) { //當(dāng)移動(dòng)到最座 那么需要改變方向 反過(guò)來(lái) mDotChangeStatus = DOT_STATUS_RIGHT; mMoveDistance = 0f; mAlphaChange = 0f; } //因?yàn)閮蓚€(gè)圓點(diǎn)可能會(huì)給定不同的顏色來(lái)顯示 所以提供兩種顏色設(shè)置mLeftColor和mRightColor mPaint.setColor(mLeftColor); mPaint.setAlpha((int) (255 - mAlphaChange)); canvas.drawCircle(startPointX + mMoveDistance, startPointY, mDotRadius, mPaint); mPaint.setColor(mRightColor); mPaint.setAlpha((int) (255 - mAlphaChange)); canvas.drawCircle(startPointX + mDotRadius * 2 - mMoveDistance + mDotSpacing, startPointY, mDotRadius, mPaint); invalidate(); } }
要是不容易理解的話,下載源碼運(yùn)行再對(duì)著源碼看會(huì)容易理解
源碼下載github:Android移動(dòng)加載進(jìn)度
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)圖片加載進(jìn)度提示
- Android 進(jìn)度條 ProgressBar的實(shí)現(xiàn)代碼(隱藏、出現(xiàn)、加載進(jìn)度)
- Android實(shí)現(xiàn)圓形漸變加載進(jìn)度條
- Android仿微信公眾號(hào)文章頁(yè)面加載進(jìn)度條
- Android自定義View實(shí)現(xiàn)加載進(jìn)度條效果
- Android自定義View仿華為圓形加載進(jìn)度條
- Android基于Glide v4.x的圖片加載進(jìn)度監(jiān)聽(tīng)
- Android Material加載進(jìn)度條制作代碼
- Android自定義View基礎(chǔ)開(kāi)發(fā)之圖片加載進(jìn)度條
- Android Webview添加網(wǎng)頁(yè)加載進(jìn)度條實(shí)例詳解
相關(guān)文章
Android中Intent傳遞對(duì)象的3種方式詳解
這篇文章給大家介紹了Android中Intent傳遞對(duì)象的3種方式,分別是Serializable 方式、Parcelable 方式以及JSON 方式,有需要的朋友們可以一起參考借鑒,下面來(lái)一起看看吧。2016-09-09Android編程實(shí)現(xiàn)的短信編輯器功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)的短信編輯器功能,涉及Android權(quán)限控制、界面布局及短信功能相關(guān)操作技巧,需要的朋友可以參考下2017-08-08android開(kāi)發(fā)框架afinal使用方法小結(jié)
這篇文章主要為大家詳細(xì)總結(jié)了android開(kāi)發(fā)框架afinal使用方法,注解功能、文件上傳下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android編程創(chuàng)建桌面快捷方式的常用方法小結(jié)【2種方法】
這篇文章主要介紹了Android編程創(chuàng)建桌面快捷方式的常用方法,結(jié)合實(shí)例形式總結(jié)分析了2種常見(jiàn)的實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02Android開(kāi)發(fā)中Widget的生命周期實(shí)例分析
這篇文章主要介紹了Android開(kāi)發(fā)中Widget的生命周期,結(jié)合實(shí)例形式分析了Android開(kāi)發(fā)中Widget生命周期所涉及的常用方法與使用技巧,代碼備有詳盡的注釋便于理解,需要的朋友可以參考下2016-02-02Android仿QQ分組實(shí)現(xiàn)二級(jí)菜單展示
這篇文章主要為大家詳細(xì)介紹了Android仿QQ分組實(shí)現(xiàn)二級(jí)菜單展示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android自定義流式布局實(shí)現(xiàn)淘寶搜索記錄
這篇文章主要為大家詳細(xì)介紹了Android自定義流式布局實(shí)現(xiàn)淘寶搜索記錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10