【學習筆記】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
HorizontalProgressbar.javapackage 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.javapackage 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()); } }
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;