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

Android 自定義view和屬性動(dòng)畫實(shí)現(xiàn)充電進(jìn)度條效果

 更新時(shí)間:2016年12月08日 09:25:11   作者:seeyou_boy  
近期項(xiàng)目中需要使用到一種類似手機(jī)電池充電進(jìn)度的動(dòng)畫效果,以前沒學(xué)屬性動(dòng)畫的時(shí)候,是用圖片+定時(shí)器的方式來完成的,下面給大家分享android自定義view和屬性動(dòng)畫實(shí)現(xiàn)充電進(jìn)度條

近期項(xiàng)目中需要使用到一種類似手機(jī)電池充電進(jìn)度的動(dòng)畫效果,以前沒學(xué)屬性動(dòng)畫的時(shí)候,是用圖片+定時(shí)器的方式來完成的,最近一直在學(xué)習(xí)動(dòng)畫這一塊,再加上復(fù)習(xí)一下自定義view的相關(guān)知識(shí)點(diǎn),所以打算用屬性動(dòng)畫和自定義view的方式來完成這個(gè)功能,將它開源出來,供有需要的人了解一下相關(guān)的內(nèi)容。

本次實(shí)現(xiàn)的功能類似下面的效果:

充電效果

接下來便詳細(xì)解析一下如何完成這個(gè)功能,了解其中的原理,這樣就能舉一反三,實(shí)現(xiàn)其他類似的動(dòng)畫效果了。

詳細(xì)代碼請(qǐng)看大屏幕

https://github.com/crazyandcoder/ChargeProgress

圖形解析

一般,我們自定義view時(shí),是將該view進(jìn)行化解,分成一個(gè)一個(gè)小部分,然后在重疊起來進(jìn)行繪制,對(duì)于這個(gè)項(xiàng)目,也是按照相同的步驟進(jìn)行。我們用Word來簡(jiǎn)單解析一下該動(dòng)畫所包含的基本結(jié)構(gòu)。

對(duì)于這個(gè)充電進(jìn)度view,我將它分成了ABCD四個(gè)部分,下面來詳細(xì)說明各個(gè)部分的組成。

A部分

對(duì)于A而言,它是位于整個(gè)view的頂部,居中顯示,是一個(gè)圓角矩形。

B部分

對(duì)于B而言,它是整個(gè)view的重要組成部分,包含C和D兩部分,其中B主要屬性就是背景色的設(shè)置。

C部分

對(duì)于C而言,C就是每一個(gè)進(jìn)度的樣式,顯示的是未完成的進(jìn)度條樣式。

D部分

對(duì)于D而言,它跟C是一樣的,只不過是已經(jīng)完成的進(jìn)度樣式,區(qū)別在于顏色的不一樣。

其實(shí),這個(gè)進(jìn)度view圖形結(jié)構(gòu)還是比較簡(jiǎn)單的,只是一些簡(jiǎn)單的矩形,組合而成,因此對(duì)于以上的分析,我們輕易的得出一些重要的屬性。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="charging_progress">
<!--item個(gè)數(shù)-->
<attr name="cgv_item_count" format="integer" />
<!--邊界寬度-->
<attr name="cgv_border_width" format="dimension" />
<!--邊界顏色-->
<attr name="cgv_border_color" format="color" />
<!--圓角半徑-->
<attr name="cgv_border_cornor_radius" format="dimension" />
<!--充電內(nèi)每個(gè)進(jìn)度item模塊的寬度-->
<attr name="cgv_item_width" format="dimension" />
<!--充電內(nèi)每個(gè)進(jìn)度item模塊的高度-->
<attr name="cgv_item_height" format="dimension" />
<!--充電內(nèi)每個(gè)進(jìn)度item模塊的前景色,充電中的顏色-->
<attr name="cgv_item_charging_src" format="color" />
<!--充電內(nèi)每個(gè)進(jìn)度item模塊的背景色,未充電的顏色-->
<attr name="cgv_item_charging_background" format="color" />
<!--view 的背景-->
<attr name="cgv_background" format="color" />
</declare-styleable>
</resources>

對(duì)于以上屬性,我們?cè)谧远xview的時(shí)候需要在xml文件中進(jìn)行設(shè)置,如果沒有設(shè)置的話,我們給出一個(gè)默認(rèn)。然后我們?cè)诖a中進(jìn)行獲取這些屬性值。

//邊界寬度
private float border_width;
//item個(gè)數(shù)
private int item_count;
//邊界寬度
private float item_width;
//邊界高度
private float item_height;
//view內(nèi)部的進(jìn)度前景色
private int item_charging_src;
//view內(nèi)部的進(jìn)度背景色
private int item_charging_background;
//view背景色
private int background;
//<!--邊界顏色-->
private int border_color;
//圓角半徑
private float border_cornor_radius;
//獲取xml中設(shè)定的屬性值
TypedArray array = mContext.obtainStyledAttributes(attrs, R.styleable.charging_progress);
border_width = array.getDimension(R.styleable.charging_progress_cgv_border_width, dp2px(2));
item_height = array.getDimension(R.styleable.charging_progress_cgv_item_height, dp2px(10));
item_width = array.getDimension(R.styleable.charging_progress_cgv_item_width, dp2px(20));
item_charging_src = array.getColor(R.styleable.charging_progress_cgv_item_charging_src, 0xffffea00);
item_charging_background = array.getColor(R.styleable.charging_progress_cgv_item_charging_background, 0xff544645);
background = array.getColor(R.styleable.charging_progress_cgv_background, 0xff463938);
border_color = array.getColor(R.styleable.charging_progress_cgv_border_color, 0xffb49d7c);
border_cornor_radius = array.getDimension(R.styleable.charging_progress_cgv_border_cornor_radius, dp2px(2));
item_count = array.getInt(R.styleable.charging_progress_cgv_item_count, 10);
array.recycle();

已經(jīng)獲取了自定義屬性的值,那么接下來,我們就來具體繪制這些組合圖形。

對(duì)于一個(gè)自定義view,首先要做的就是測(cè)量view的大小,而本項(xiàng)目中view的寬度和高度,寬度是好計(jì)算的,我們?cè)O(shè)置view的寬度等于item_widht 乘以2 。但是對(duì)于高度的話,因?yàn)槲覀冊(cè)O(shè)置了progress的級(jí)數(shù),也就是item_count,也設(shè)置了item的高度和寬度,所以對(duì)于高度,我們可以通過計(jì)算item_count 乘以 item_height,再加上間隔數(shù)和頂部矩形的就是整個(gè)view的高度。同時(shí),我們?cè)O(shè)定,頂部矩形的高度等于item_height,寬度等于item_widht的一半,中間間隔等于item_height 除以2

/**
* 測(cè)量view的寬和高,
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//總間隔數(shù)=(item_count+1) 乘以間隔高度(間隔高度等于item_height的一半)
//總數(shù)=item_count 乘以 item_height + 總間隔數(shù) + 頂部一個(gè)矩形(高度等于item的高度,寬度等于item的寬度的一半)
mHeight = (int) (item_count * item_height + (item_count + 1) * item_height / 2 + item_height);
mWidth = (int) (2 * item_width);
setMeasuredDimension(mWidth, mHeight);
}

有了上面的設(shè)置,接下來我們就可以按部就班的畫圖了。

對(duì)于坐標(biāo)中心點(diǎn)是設(shè)定在左上角,也就是(0,0)處。

畫頂部矩形

知道了坐標(biāo)系的原點(diǎn),那么頂部矩形的坐標(biāo)就可以計(jì)算了。

首先設(shè)置畫筆。

mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(border_width);
mPaint.setColor((border_color));

由于頂部矩形的width等于item_widht的一半,所以它的width等于整個(gè)view的width的1/6,

int left = mWidth * 3 / 8;
int top = 0;
int right = 5 * mWidth / 8;
int bottom = (int) item_height / 2;
//頂部的矩形
RectF topRect = new RectF(left, top, right, bottom);
canvas.drawRoundRect(topRect, border_cornor_radius, border_cornor_radius, mPaint);

接下來繪制底部的矩形,也就是包含進(jìn)度item的矩形

//總的進(jìn)度背景
RectF border = new RectF(0, bottom, mWidth, mHeight);
canvas.drawRoundRect(border, border_cornor_radius, border_cornor_radius, mPaint);

接下來繪制每個(gè)item的矩形,對(duì)于每個(gè)item的坐標(biāo),實(shí)際上是有規(guī)律可循的。

//繪制所有的進(jìn)度
for (int i = 1; i <= item_count; i++) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor((item_charging_background));
RectF backRect = new RectF(mWidth / 4,
(i + 1) * item_height / 2 + (i - 1) * item_height,
3 * mWidth / 4,
item_height / 2 + i * (3 * item_height / 2));
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
}

繪制動(dòng)畫

對(duì)于交流動(dòng)畫,就是從進(jìn)度0到100的動(dòng)畫顯示,依次顯示。其實(shí)也是對(duì)于坐標(biāo)的計(jì)算而已。接下來最終要的功能就是動(dòng)畫的使用了,我們使用的是屬性動(dòng)畫呢?因?yàn)?,常?guī)的動(dòng)畫它不支持啊,很簡(jiǎn)單。

對(duì)于Android屬性動(dòng)畫的學(xué)習(xí),可以查看這篇文章,稍微了解一下。《Android動(dòng)畫了解》

1、交流動(dòng)畫

/**
* 繪制交流動(dòng)畫
*
* @param canvas
*/
private void drawACAnimaiton(Canvas canvas) {
int j = getProgress() / item_count;
//已經(jīng)充好的進(jìn)度
for (int i = item_count; i >= (item_count - j); i--) {
RectF backRect = new RectF(mWidth / 4,
(i + 1) * item_height / 2 + (i - 1) * item_height,
3 * mWidth / 4,
item_height / 2 + i * (3 * item_height / 2));
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(item_charging_src);
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
}
}

我們首先獲取當(dāng)前的進(jìn)度,然后依次給它填充背景,這就是已完成的進(jìn)度表示。

然后使用動(dòng)畫即可,我們?cè)O(shè)置進(jìn)度為100,也就是充滿,然后設(shè)置動(dòng)畫時(shí)間是10秒鐘,對(duì)于下面的動(dòng)畫執(zhí)行原理是什么呢?其實(shí)很簡(jiǎn)單,獲取當(dāng)前的進(jìn)度,然后從0開始,依次繪制進(jìn)度,知道繪制的進(jìn)度為100就是總的進(jìn)度,最后再循環(huán)執(zhí)行動(dòng)畫即可。

/**
* 設(shè)置交流動(dòng)畫
*/
public void setACAnimation() {
chargeType = AC;
animAC = ObjectAnimator.ofInt(this, "progress", 100);
animAC.setDuration(10 * 1000);
animAC.setInterpolator(new LinearInterpolator());
animAC.setRepeatCount(ValueAnimator.INFINITE);
animAC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
});
animAC.start();
}

2、直流動(dòng)畫

對(duì)于直流動(dòng)畫就稍微比較復(fù)雜了。當(dāng)我們?cè)O(shè)置了進(jìn)度后,需要我們預(yù)先繪制已完成的進(jìn)度,然后在下一個(gè)進(jìn)度進(jìn)行閃爍表示動(dòng)畫,那么該如何完成呢?

首先看繪制代碼:

/**
* 直流動(dòng)畫
*
* @param canvas
*/
private void drawDCAniamtion(Canvas canvas) {
int j = getProgress() / item_count;
//已經(jīng)充好的進(jìn)度
for (int i = item_count; i > (item_count - j); i--) {
RectF backRect = new RectF(mWidth / 4,
(i + 1) * item_height / 2 + (i - 1) * item_height,
3 * mWidth / 4,
item_height / 2 + i * (3 * item_height / 2));
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(item_charging_src);
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
}
//下一個(gè)進(jìn)度,隱藏和顯示交替執(zhí)行動(dòng)畫
int i = item_count - j;
if (i > 0) {
RectF backRect = new RectF(mWidth / 4,
(i + 1) * item_height / 2 + (i - 1) * item_height,
3 * mWidth / 4,
item_height / 2 + i * (3 * item_height / 2));
mPaint.setStyle(Paint.Style.FILL);
if (show) {
mPaint.setColor((item_charging_src));
} else {
mPaint.setColor((item_charging_background));
}
canvas.drawRoundRect(backRect, border_cornor_radius, border_cornor_radius, mPaint);
}
}

首先繪制已完成的進(jìn)度,然后在繪制閃爍的部分。

/**
* 直流動(dòng)畫
*
* @param progress
*/
public void setDCAnimation(final int progress) {
chargeType = DC;
animatorDC = ValueAnimator.ofFloat(0, 1);
animatorDC.setInterpolator(new LinearInterpolator());
animatorDC.setDuration(1000);
animatorDC.setRepeatCount(-1);
animatorDC.setRepeatMode(ValueAnimator.RESTART);
animatorDC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
if (value > 0.5) {
show = true;
} else {
show = false;
}
setProgress(progress);
}
});
animatorDC.start();
}

到這里,就很明了了。對(duì)于直流動(dòng)畫,我們使用屬性動(dòng)畫中這個(gè)ValueAnimator類,它的意思就是從0到1平滑的過渡,在設(shè)定的時(shí)間內(nèi)。我們的原理是當(dāng)達(dá)到0.5以上后就設(shè)定灰色進(jìn)度,當(dāng)小于0.5的話就設(shè)置亮色進(jìn)度,然后在刷新一下view即可。

以上所述是小編給大家介紹的Android 自定義view和屬性動(dòng)畫實(shí)現(xiàn)充電進(jìn)度條效果,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Android使用AIDL方式實(shí)現(xiàn)播放音樂案例

    Android使用AIDL方式實(shí)現(xiàn)播放音樂案例

    這篇文章主要介紹了Android使用AIDL方式實(shí)現(xiàn)播放音樂案例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Android實(shí)現(xiàn)在列表List中顯示半透明小窗體效果的控件用法詳解

    Android實(shí)現(xiàn)在列表List中顯示半透明小窗體效果的控件用法詳解

    這篇文章主要介紹了Android實(shí)現(xiàn)在列表List中顯示半透明小窗體效果的控件用法,結(jié)合實(shí)例形式分析了Android半透明提示框的實(shí)現(xiàn)與設(shè)置技巧,需要的朋友可以參考下
    2016-06-06
  • Android開發(fā)Jetpack組件LiveData使用講解

    Android開發(fā)Jetpack組件LiveData使用講解

    LiveData是Jetpack組件的一部分,更多的時(shí)候是搭配ViewModel來使用,相對(duì)于Observable,LiveData的最大優(yōu)勢(shì)是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動(dòng)生命周期狀態(tài)的時(shí)候才會(huì)更新數(shù)據(jù)
    2022-08-08
  • Android shape和selector 結(jié)合使用實(shí)例代碼

    Android shape和selector 結(jié)合使用實(shí)例代碼

    本篇文章主要介紹了Android shape和selector 的使用,這里提供了shape 和selector 的詳細(xì)介紹,并附有代碼實(shí)例,有興趣的朋友可以參考下
    2016-07-07
  • Android自定義帶圓角的ImageView

    Android自定義帶圓角的ImageView

    這篇文章主要為大家詳細(xì)介紹了Android自定義帶圓角的ImageView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • Android簡(jiǎn)單實(shí)現(xiàn)引導(dǎo)頁

    Android簡(jiǎn)單實(shí)現(xiàn)引導(dǎo)頁

    這篇文章主要為大家詳細(xì)介紹了Android簡(jiǎn)單實(shí)現(xiàn)引導(dǎo)頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Android MPAndroidChart開源庫圖表之折線圖的實(shí)例代碼

    Android MPAndroidChart開源庫圖表之折線圖的實(shí)例代碼

    這篇文章主要介紹了Android MPAndroidChart開源庫圖表之折線圖的實(shí)例代碼,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Android開發(fā)之StackView用法和遇到的坑分析

    Android開發(fā)之StackView用法和遇到的坑分析

    這篇文章主要介紹了Android開發(fā)之StackView用法和遇到的坑,結(jié)合實(shí)例形式分析了Android StackView圖片操作用法及常見問題解決方法,需要的朋友可以參考下
    2019-03-03
  • Android RecycleView實(shí)現(xiàn)Item拖拽效果

    Android RecycleView實(shí)現(xiàn)Item拖拽效果

    RecyclerView是Android一個(gè)更強(qiáng)大的控件,其不僅可以實(shí)現(xiàn)和ListView同樣的效果,還有優(yōu)化了ListView中的各種不足。本文將介紹通過RecyclerView實(shí)現(xiàn)Item拖拽效果以及拖拽位置保存,感興趣的可以參考一下
    2022-01-01
  • Android小程序?qū)崿F(xiàn)切換背景顏色

    Android小程序?qū)崿F(xiàn)切換背景顏色

    這篇文章主要介紹了Android小程序?qū)崿F(xiàn)切換背景顏色,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論