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)度條,類(lèi)似的實(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();
}
}
要是不容易理解的話(huà),下載源碼運(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)文章
6步輕松實(shí)現(xiàn)兩個(gè)listView聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了教大家通過(guò)6步輕松實(shí)現(xiàn)兩個(gè)listView聯(lián)動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Android 10 啟動(dòng)Init進(jìn)程解析
這篇文章主要為大家介紹了Android 10 啟動(dòng)Init進(jìn)程解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Android Activity與Intent詳解及示例代碼
本文主要講解Android Activity與Intent的知識(shí),這里整理了相關(guān)資料并附有示例代碼,有興趣的小伙伴可以參考下2016-08-08
Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法
下面小編就為大家分享一篇Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android從觸碰屏幕開(kāi)始的事件采集解析及分發(fā)
這篇文章主要為大家介紹了Android從觸碰屏幕開(kāi)始的事件采集解析及分發(fā),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Flutter 包管理器和資源管理使用學(xué)習(xí)
這篇文章主要為大家介紹了Flutter 包管理器和資源管理使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android編程實(shí)現(xiàn)獲取所有傳感器數(shù)據(jù)的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)獲取所有傳感器數(shù)據(jù)的方法,涉及Android針對(duì)傳感器Sensor相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Android實(shí)現(xiàn)調(diào)用攝像頭拍照與視頻功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)調(diào)用攝像頭拍照與視頻功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Android StatusBar 透明化方法(不同的版本適配)
本篇文章主要介紹了Android StatusBar 透明化方法(不同的版本適配),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01

