1. 程式人生 > >【學習筆記】Android-打造炫酷進度條(條形)

【學習筆記】Android-打造炫酷進度條(條形)

本文是我在慕課網上學習《Android-打造炫酷進度條》整理的原始碼,和視訊中的原始碼主體一致,僅修改了部分引數。

效果圖如下所示(實際進度條是連續的)。


原始檔

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="progress_unreach_color" format="color"></attr>
    <attr name="progress_unreach_height" format="dimension"></attr>
    <attr name="progress_reach_color" format="color"></attr>
    <attr name="progress_reach_height" format="dimension"></attr>
    <attr name="progress_text_color" format="color"></attr>
    <attr name="progress_text_size" format="dimension"></attr>
    <attr name="progress_text_offset" format="dimension"></attr>

    <declare-styleable name="HorizontalProgressbar">
        <attr name="progress_unreach_color"></attr>
        <attr name="progress_unreach_height"></attr>
        <attr name="progress_reach_color"></attr>
        <attr name="progress_reach_height"></attr>
        <attr name="progress_text_color"></attr>
        <attr name="progress_text_size"></attr>
        <attr name="progress_text_offset"></attr>
    </declare-styleable>
</resources>
HorizontalProgressbar

package com.androidk.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.ProgressBar;

import com.androidk.myprogressbar.R;

/**
 * Created by Administrator on 16-7-23.
 */
public class HorizontalProgressbar extends ProgressBar {

    String TAG = "HorizontalProgressbar";
    //定義預設值
    private static final int DEFAULT_TEXT_SIZE = 10;//sp
    private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
    private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;
    private static final int DEFAULT_HEIGHT_UNREACH = 3;//dp
    private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
    private static final int DEFAULT_HEIGHT_REACH = 3;//dp
    private static final int DEFAULT_TEXT_OFFSET = 10;//dp
    //定義變數
    private int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
    private int mTextColor = DEFAULT_TEXT_COLOR;
    private int mUnReachColor = DEFAULT_COLOR_UNREACH;
    private int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
    private int mReachColor = DEFAULT_COLOR_REACH;
    private int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
    private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);

    //畫筆
    private Paint mPaint = new Paint();
    private int mRealWidth;


    public HorizontalProgressbar(Context context) {
        this(context,null);
        Log.i(TAG,"一個引數構造方法");
    }

    public HorizontalProgressbar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
        Log.i(TAG,"兩個引數構造方法");
    }

    public HorizontalProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.i(TAG,"三個引數構造方法");
        obtainStyledAttrs(attrs);
        
    }
    /*
    * 獲取自定義屬性
    * */
    private void obtainStyledAttrs(AttributeSet attrs) {

        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressbar);

        mTextSize = (int)ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_text_size,
                        mTextSize);

        mTextColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_text_color,
                        mTextColor);

        mTextOffset = (int) ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_text_offset,
                        mTextOffset);
        mUnReachColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_unreach_color,
                        mUnReachColor);
        mUnReachHeight = (int)ta.
                getDimension(R.styleable.HorizontalProgressbar_progress_unreach_height,
                        mUnReachHeight);

        mReachColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_reach_color,
                        mReachColor);
        mReachHeight = (int)ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_reach_height,
                        mReachHeight);
        mPaint.setTextSize(mTextSize);
        ta.recycle();
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //開始時進入兩次
        //int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthVal = MeasureSpec.getSize(widthMeasureSpec);

        int height =  measureHeight(heightMeasureSpec);

        setMeasuredDimension(widthVal,height);

        mRealWidth = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
        Log.i(TAG,"mRealWidth = "+mRealWidth);
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {

        canvas.save();
        canvas.translate(getPaddingLeft(),getHeight()/2);

        boolean noNeedUnReach = false;
        //draw reach bar
        String text = getProgress()+"%";
        int textWidth = (int)mPaint.measureText(text);
        float radio = getProgress()*1.0f/getMax();
        float progressX = radio * mRealWidth;

        if(progressX + textWidth >mRealWidth){
            progressX = mRealWidth - textWidth;
            noNeedUnReach = true;//不需要繪製後半段
        }

        float endX = radio*mRealWidth - mTextOffset/2;
        if(endX >0 ){
            mPaint.setColor(mReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(0,0,progressX,0,mPaint);
        }
        //draw text
        mPaint.setColor(mTextColor);
        int y = (int)(-(mPaint.descent()+mPaint.ascent())/2);
        canvas.drawText(text,progressX+ mTextOffset/2 ,y,mPaint);
        //draw unreach bar
        if(!noNeedUnReach){
            float start = progressX + mTextOffset/2 + textWidth;
            mPaint.setColor(mUnReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(start + mTextOffset/2,0,mRealWidth,0,mPaint);
        }

        canvas.restore();


    }

    private int measureHeight(int heightMeasureSpec) {
        int result = 0;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        Log.i(TAG,"mode = "+mode);
        if(mode == MeasureSpec.EXACTLY){
            result = size;
        }else{
            int textHeight = (int) (mPaint.descent()-mPaint.ascent());
            result = getPaddingTop()
                    +getPaddingBottom()
                    +Math.max(Math.max(mReachHeight,mUnReachHeight),
                    Math.abs(textHeight));
            if(mode == MeasureSpec.AT_MOST){
                result  = Math.min(result,size);
            }
        }
        Log.i(TAG,"result = "+result);
        return result;
    }

    private int dp2px(int dpVal){
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal,
                getResources().getDisplayMetrics());
    }
    private int sp2px(int spVal){
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal,
                getResources().getDisplayMetrics());
    }

}
HorizontalProgressbar.java
package com.androidk.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.widget.ProgressBar;

import com.androidk.myprogressbar.R;

/**
 * Created by Administrator on 16-7-23.
 */
public class HorizontalProgressbar extends ProgressBar {

    String TAG = "HorizontalProgressbar";
    //定義預設值
    private static final int DEFAULT_TEXT_SIZE = 10;//sp
    private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
    private static final int DEFAULT_COLOR_UNREACH = 0xFFD3D6DA;
    private static final int DEFAULT_HEIGHT_UNREACH = 3;//dp
    private static final int DEFAULT_COLOR_REACH = DEFAULT_TEXT_COLOR;
    private static final int DEFAULT_HEIGHT_REACH = 3;//dp
    private static final int DEFAULT_TEXT_OFFSET = 10;//dp
    //定義變數
    private int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
    private int mTextColor = DEFAULT_TEXT_COLOR;
    private int mUnReachColor = DEFAULT_COLOR_UNREACH;
    private int mUnReachHeight = dp2px(DEFAULT_HEIGHT_UNREACH);
    private int mReachColor = DEFAULT_COLOR_REACH;
    private int mReachHeight = dp2px(DEFAULT_HEIGHT_REACH);
    private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);

    //畫筆
    private Paint mPaint = new Paint();
    private int mRealWidth;


    public HorizontalProgressbar(Context context) {
        this(context,null);
        Log.i(TAG,"一個引數構造方法");
    }

    public HorizontalProgressbar(Context context, AttributeSet attrs) {
        this(context, attrs,0);
        Log.i(TAG,"兩個引數構造方法");
    }

    public HorizontalProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.i(TAG,"三個引數構造方法");
        obtainStyledAttrs(attrs);
        
    }
    /*
    * 獲取自定義屬性
    * */
    private void obtainStyledAttrs(AttributeSet attrs) {

        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressbar);

        mTextSize = (int)ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_text_size,
                        mTextSize);

        mTextColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_text_color,
                        mTextColor);

        mTextOffset = (int) ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_text_offset,
                        mTextOffset);
        mUnReachColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_unreach_color,
                        mUnReachColor);
        mUnReachHeight = (int)ta.
                getDimension(R.styleable.HorizontalProgressbar_progress_unreach_height,
                        mUnReachHeight);

        mReachColor = ta.
                getColor(
                        R.styleable.HorizontalProgressbar_progress_reach_color,
                        mReachColor);
        mReachHeight = (int)ta.
                getDimension(
                        R.styleable.HorizontalProgressbar_progress_reach_height,
                        mReachHeight);
        mPaint.setTextSize(mTextSize);
        ta.recycle();
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //開始時進入兩次
        //int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthVal = MeasureSpec.getSize(widthMeasureSpec);

        int height =  measureHeight(heightMeasureSpec);

        setMeasuredDimension(widthVal,height);

        mRealWidth = getMeasuredWidth()-getPaddingLeft()-getPaddingRight();
        Log.i(TAG,"mRealWidth = "+mRealWidth);
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {

        canvas.save();
        canvas.translate(getPaddingLeft(),getHeight()/2);

        boolean noNeedUnReach = false;
        //draw reach bar
        String text = getProgress()+"%";
        int textWidth = (int)mPaint.measureText(text);
        float radio = getProgress()*1.0f/getMax();
        float progressX = radio * mRealWidth;

        if(progressX + textWidth >mRealWidth){
            progressX = mRealWidth - textWidth;
            noNeedUnReach = true;//不需要繪製後半段
        }

        float endX = radio*mRealWidth - mTextOffset/2;
        if(endX >0 ){
            mPaint.setColor(mReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(0,0,progressX,0,mPaint);
        }
        //draw text
        mPaint.setColor(mTextColor);
        int y = (int)(-(mPaint.descent()+mPaint.ascent())/2);
        canvas.drawText(text,progressX+ mTextOffset/2 ,y,mPaint);
        //draw unreach bar
        if(!noNeedUnReach){
            float start = progressX + mTextOffset/2 + textWidth;
            mPaint.setColor(mUnReachColor);
            mPaint.setStrokeWidth(mReachHeight);
            canvas.drawLine(start + mTextOffset/2,0,mRealWidth,0,mPaint);
        }

        canvas.restore();


    }

    private int measureHeight(int heightMeasureSpec) {
        int result = 0;
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        Log.i(TAG,"mode = "+mode);
        if(mode == MeasureSpec.EXACTLY){
            result = size;
        }else{
            int textHeight = (int) (mPaint.descent()-mPaint.ascent());
            result = getPaddingTop()
                    +getPaddingBottom()
                    +Math.max(Math.max(mReachHeight,mUnReachHeight),
                    Math.abs(textHeight));
            if(mode == MeasureSpec.AT_MOST){
                result  = Math.min(result,size);
            }
        }
        Log.i(TAG,"result = "+result);
        return result;
    }

    private int dp2px(int dpVal){
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal,
                getResources().getDisplayMetrics());
    }
    private int sp2px(int spVal){
        return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal,
                getResources().getDisplayMetrics());
    }

}
MainActivity.java
package com.androidk.myprogressbar;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.androidk.view.HorizontalProgressbar;

public class MainActivity extends AppCompatActivity {

    private HorizontalProgressbar mHProgressbar;
    private static final int MSG_UPDATE = 0x110;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            int progress = mHProgressbar.getProgress();
            mHProgressbar.setProgress(++progress);
            if(progress>=100){
                mHandler.removeMessages(MSG_UPDATE);
            }else{
                mHandler.sendEmptyMessageDelayed(MSG_UPDATE,100);
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHProgressbar = (HorizontalProgressbar)findViewById(R.id.id_progress01);
        mHandler.sendEmptyMessage(MSG_UPDATE);

    }
}

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <com.androidk.view.HorizontalProgressbar
            android:id="@+id/id_progress01"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:progress="50"
            android:padding="5dp"
            android:layout_marginTop="30dp"/>
    </LinearLayout>
</ScrollView>



相關推薦

學習筆記Android-打造進度條形

本文是我在慕課網上學習《Android-打造炫酷進度條》整理的原始碼,和視訊中的原始碼主體一致,僅修改了部分引數。 效果圖如下所示(實際進度條是連續的)。 原始檔 attrs.xml <?xml version="1.0" encoding="utf-8"?>

學習筆記Android Activity

本部分內容參考這裡。manifest宣告activities需要在manifest檔案中的<application> element中增加<activity> element。<activity>的屬性中,僅有android:name是必須

extjs6學習筆記0.1 準備:基礎概念02

json over cal 類的屬性 tab 常用事件 data 微軟 基於 Ext 類 Ext 是一個全局單例的對象,在 Sencha library 中它封裝了所有的類和許多實用的方法。許多常用的函數都定義在 Ext 對象裏。它還提供了像其他類中一些頻繁使用的方法

學習筆記SIFT尺度不變特征 配合UCF-CRCV課程視頻

rri cnblogs -o mask 畫出 blocks http ucf 產生 SIFT尺度不變特征 D. Lowe. Distinctive image features from scale-invariant key points, IJCV 2004 -Lect

學習筆記String進階:StringBuffer類線程安全和StringBuilder類

n) static this util double 字符串 對象 ice 單線程 一、除了使用String類存儲字符串之外,還可以使用StringBuffer類存儲字符串。而且它是比String類更高效的存儲字符串的一種引用數據類型。 優點:   對字符串進行連接操作時,

機器學習筆記自組織映射網絡SOM

非線性 每一個 可能 合作 空間 找到 節點 視覺 網格 什麽是自組織映射? 一個特別有趣的無監督系統是基於競爭性學習,其中輸出神經元之間競爭激活,結果是在任意時間只有一個神經元被激活。這個激活的神經元被稱為勝者神經元(winner-takes-all neuron)。這種

python筆記騰訊動漫爬取更新

目前騰訊動漫閱讀介面的滑動需要切換到指定視窗,即漫畫照片頁所在div 'var q=document.getElementById("mainView").scrollTop ='+str(i*3000) 才可以滑動 import requests import u

打造進度

如何自定義控制元件 1.自定義屬性的宣告與獲取 2.測量onMeasure 3.佈局onLayout(ViewGroup) 4.繪製onDraw 5.onTouchEvent 6.onInterceptTouchEvent(ViewGroup) 7.狀態的恢復與儲存 自定

Android學習筆記Android Studio簡單斷點調試

分享 遇到 跟著 相關 斷點調試 .com 完整 android學習 force 首先點擊斷點調試按鈕運行App 啟動之後,會彈出如下圖的提示框,不要管,幾秒之後這個彈框會自動消失,然後App會成功運行。 下面介紹一下斷點調試的相關操作按鈕對應的功能: 按鈕1的功能:

安卓學習筆記Android Studio第3課——EditText控制元件

EditText和TextView很相似,主要不同的是EditText是使用者可以在上面編輯本文的,而TextView只能用app本身去改變和顯示。做了一個簡單的登入介面:xml程式碼如下<?xml version="1.0" encoding="utf-8"?>

學習筆記65~百度看到的比較好的Android原始碼學習路徑

我幹了3年Android sdk開發,覺得到了瓶勁沒法更進一步,於是花了一年多點時間,大概摸到點門徑。根據前輩的經驗,Android底層完全入門需要兩年。    先說下我的入門過程:    第零步,下載原始碼,我下的4.2的,框架層原始碼10G,核心2G多,ctags給框架層建的標籤檔案都有600M,當時

學習筆記關於DOM4J:使用DOM4J解析XML文檔

文本 class 中產 獲取 ber exce int() logs hone 一、概述 DOM4J是一個易用的、開源的庫,用於XML、XPath和XSLT中。采用了Java集合框架並完全支持DOM、SAX、和JAXP。 DOM4J最大的特色是使用大量的接口,主要接口都在o

學習筆記Java中生成對象的5中方法

目標 獲得 cti com pre lan except 我們 highlight 概述:本文介紹以下java五種創建對象的方式: 1.用new語句創建對象,這是最常用的創建對象的方式。 2.使用Class類的newInstance方法 3.運用反射手段,調用java.la

學習筆記使用SQLyog連接MySQL數據庫

comm 丟失 school turn 復合主鍵 price not email pre 一、使用SQLyog創建數據庫用來管理學生信息 1 #創建數據庫student 2 DROP DATABASE IF EXISTS Myschool; 3 CREAT

學習筆記2017年7月18日MySQL測試:模擬QQ數據庫

關系 ref sts one database 等級 weight insert phone 模擬測試: QQ數據庫管理 一、創建數據庫並添加關系和測試數據 1 ##創建QQ數據庫,完成簡單的測試 2 3 #創建數據庫 4 DROP DATABASE IF EX

學習筆記C# 構造和析構

成員 int 學習 pri [] func 釋放內存 ring 銷毀 構造方法 構造方法是一個特殊的方法,負責初始化對象 構造方法名必須和類名一致 構造方法沒有返回值,但可以有參數,能夠重載 構造方法可以不寫,系統會自動為類添加一個無參的默認構造 如果將構造方法設置為P

學習筆記C# 靜態類

實例化 namespace [] line str 過程 ole test 數據 靜態修飾符 用static修飾的成員是靜態成員 靜態成員只能由類來調用 用static修飾的類是靜態類 靜態類不能實例化,只能包含靜態成員和const常量 在內存中一共有五個區域 1

學習筆記C# 接口

apple [] oat 訪問 names 使用 foo pub 修飾 使用interface關鍵字定義接口 接口定義一組成員但不直接實現它們 實現接口 實現接口的任何類都必須實現其所有的成員方法 接口不能直接實例化 接口可以包含方法和屬性聲明,不能包含字段 接口中所有

學習筆記C# ArrayList

tde 獲取 style demo key ren mov cnblogs content 集合 集合是種容器,在程序中,使用集體管理相關對象組 集合分為非泛型集合和泛型集合 非泛型集合 使用非泛型集合需要引入命名空間System.Collections Arra

學習筆記C# 字典

鍵值對 保存 包含 ear 是否 nod 對象 命名空間 不包含 字典 Dictionary是存儲鍵和值的集合 Dictionary是無序的,鍵Key是唯一的 使用時,首先要引入泛型集合命名空間 using System.Collections.Generic;