├── .gitignore ├── GIF.gif ├── src ├── main │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── styles.xml │ │ │ └── attrs.xml │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ └── layout │ │ │ └── activity_main.xml │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── xinzhen │ │ └── customprogressbar2 │ │ ├── MainActivity.java │ │ └── customview │ │ ├── MyRoundProgressBar.java │ │ ├── MyRoundProgressBar2.java │ │ ├── MyHoriztalProgressBar.java │ │ └── MyHoriztalProgressBar2.java ├── test │ └── java │ │ └── com │ │ └── xinzhen │ │ └── customprogressbar2 │ │ └── ExampleUnitTest.java └── androidTest │ └── java │ └── com │ └── xinzhen │ └── customprogressbar2 │ └── ApplicationTest.java ├── README.md ├── proguard-rules.pro └── customprogressbar.iml /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /GIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/GIF.gif -------------------------------------------------------------------------------- /src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CustomProgressBar2 3 | 4 | -------------------------------------------------------------------------------- /src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kjt666/CustomProgressBar/HEAD/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /src/test/java/com/xinzhen/customprogressbar2/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/androidTest/java/com/xinzhen/customprogressbar2/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CustomProgressBar 2 | 3 | ## 09.27 4 | 5 | 另建分支,支持一键依赖 6 | https://github.com/kjt666/BeautyProgressBar 7 | 8 | ----- 9 | 自定义带进度文字的progressBar、圆形带进度的progressBar、仿ios应用商定的圆形下载进度条、两端和完成进度右端为半圆的进度条 10 | 11 | 仿ios应用商店下载应用时的进度条 12 | 13 | 2016.06.16日更新两端为半圆形的进度条,看起来比较柔和,用户体验更好。有三个属性。进度条完成和未完成的颜色,进度条的高度。 14 | 15 | 16 | 圆形进度条和带文字的条形进度条的通用属性 17 | 18 | progressbar_reach_color 已完成进度条的颜色 19 | 20 | progressbar_unreach_color 未完成进度条的颜色 21 | 22 | progressbar_reach_height 已完成进度条的高度 23 | 24 | progressbar_unreach_height 未完成进度条的高度 25 | 26 | progressbar_text_color 文字的颜色 27 | 28 | progressbar_text_offset 与进度条两侧的间距(水平进度条设置用) 29 | 30 | progressbar_radius 圆形进度条的半径 31 | 32 | 效果图 33 | 34 | ![image](https://github.com/kjt666/CustomProgressBar/blob/master/GIF.gif ) 35 | -------------------------------------------------------------------------------- /proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\androidstudiosdk\adt-bundle-windows-x64\android-sdk-windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/xinzhen/customprogressbar2/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.xinzhen.customprogressbar2.customview.MyHoriztalProgressBar; 7 | import com.xinzhen.customprogressbar2.customview.MyHoriztalProgressBar2; 8 | import com.xinzhen.customprogressbar2.customview.MyRoundProgressBar; 9 | import com.xinzhen.customprogressbar2.customview.MyRoundProgressBar2; 10 | 11 | import java.util.Timer; 12 | import java.util.TimerTask; 13 | 14 | public class MainActivity extends AppCompatActivity { 15 | 16 | private MyHoriztalProgressBar progressBar1, progressBar2, progressBar3; 17 | private MyRoundProgressBar progressBar4, progressBar5; 18 | private MyRoundProgressBar2 progressBar6; 19 | private MyHoriztalProgressBar2 progressBar7; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | progressBar1 = (MyHoriztalProgressBar) findViewById(R.id.progressbar1); 26 | progressBar2 = (MyHoriztalProgressBar) findViewById(R.id.progressbar2); 27 | progressBar3 = (MyHoriztalProgressBar) findViewById(R.id.progressbar3); 28 | progressBar4 = (MyRoundProgressBar) findViewById(R.id.progressbar4); 29 | progressBar5 = (MyRoundProgressBar) findViewById(R.id.progressbar5); 30 | progressBar6 = (MyRoundProgressBar2) findViewById(R.id.progressbar6); 31 | progressBar7 = (MyHoriztalProgressBar2) findViewById(R.id.progressbar7); 32 | new Timer().schedule(new TimerTask() { 33 | int i = 0; 34 | 35 | @Override 36 | public void run() { 37 | progressBar1.setProgress(++i); 38 | } 39 | }, 0, 150); 40 | new Timer().schedule(new TimerTask() { 41 | int i = 0; 42 | 43 | @Override 44 | public void run() { 45 | progressBar2.setProgress(++i); 46 | } 47 | }, 100, 180); 48 | new Timer().schedule(new TimerTask() { 49 | int i = 0; 50 | 51 | @Override 52 | public void run() { 53 | progressBar3.setProgress(++i); 54 | } 55 | }, 0, 250); 56 | new Timer().schedule(new TimerTask() { 57 | int i = 0; 58 | 59 | @Override 60 | public void run() { 61 | progressBar4.setProgress(++i); 62 | } 63 | }, 0, 150); 64 | new Timer().schedule(new TimerTask() { 65 | int i = 0; 66 | 67 | @Override 68 | public void run() { 69 | progressBar5.setProgress(++i); 70 | } 71 | }, 0, 200); 72 | new Timer().schedule(new TimerTask() { 73 | int i = 0; 74 | 75 | @Override 76 | public void run() { 77 | progressBar6.setProgress(++i); 78 | } 79 | }, 200, 200); 80 | new Timer().schedule(new TimerTask() { 81 | int i = 0; 82 | 83 | @Override 84 | public void run() { 85 | progressBar7.setProgress(++i); 86 | } 87 | },200,100); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/xinzhen/customprogressbar2/customview/MyRoundProgressBar.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.util.AttributeSet; 9 | 10 | import com.xinzhen.customprogressbar2.R; 11 | 12 | /** 13 | * Created by C058 on 2016/5/26. 14 | */ 15 | public class MyRoundProgressBar extends MyHoriztalProgressBar { 16 | 17 | private static final int DEFAULT_PROGRESS_RADIUS = 30; 18 | private int mMaxPaintWidth; 19 | private int mRadius = dp2px(DEFAULT_PROGRESS_RADIUS); 20 | private RectF mRectf; 21 | 22 | public MyRoundProgressBar(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public MyRoundProgressBar(Context context, AttributeSet attrs) { 27 | this(context, attrs, 0); 28 | } 29 | 30 | public MyRoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { 31 | super(context, attrs, defStyleAttr); 32 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyRoundProgressBar); 33 | mRadius = (int) ta.getDimension(R.styleable.MyRoundProgressBar_progressbar_radius, mRadius); 34 | ta.recycle(); 35 | 36 | mReachHeight = mUnReachHeight * 2; 37 | mMaxPaintWidth = mReachHeight; 38 | mPaint.setAntiAlias(true); 39 | mPaint.setDither(true); 40 | mPaint.setStrokeCap(Paint.Cap.ROUND); 41 | } 42 | 43 | @Override 44 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 45 | 46 | int diameter = mRadius * 2 + getPaddingLeft() + getPaddingRight() + mMaxPaintWidth; //控件宽度 默认四个padding一致 47 | int width = resolveSize(diameter, widthMeasureSpec); 48 | int height = resolveSize(diameter, heightMeasureSpec); 49 | 50 | int realWidth = Math.min(width, height);//当宽高设置不一致,取小的那个 51 | mRadius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWidth) / 2; 52 | mRectf = new RectF(0, 0, mRadius * 2, mRadius * 2); 53 | setMeasuredDimension(realWidth, realWidth); 54 | } 55 | 56 | @Override 57 | protected synchronized void onDraw(Canvas canvas) { 58 | 59 | canvas.save(); 60 | // mMaxPaintWidth / 加上这个只是为了能让已完成的bar完整显示出来 61 | canvas.translate(getPaddingLeft() + mMaxPaintWidth / 2, getPaddingTop() + mMaxPaintWidth / 2); 62 | //draw unreachbar 63 | mPaint.setStyle(Paint.Style.STROKE); 64 | mPaint.setColor(mUnReachColor); 65 | mPaint.setStrokeWidth(mUnReachHeight); 66 | //从圆点开始画圆 67 | canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); 68 | //draw reachbar 69 | mPaint.setStyle(Paint.Style.STROKE); 70 | mPaint.setColor(mReachColor); 71 | mPaint.setStrokeWidth(mReachHeight); 72 | float sweepAngle = getProgress() * 1.0f / getMax() * 360; 73 | canvas.drawArc(mRectf, 0, sweepAngle, false, mPaint); 74 | //draw text 75 | String text = getProgress() + "%"; 76 | int textWidth = (int) mPaint.measureText(text); 77 | int textHeight = (int) ((mPaint.descent() + mPaint.ascent()) / 2); 78 | mPaint.setStyle(Paint.Style.FILL); 79 | mPaint.setColor(mTextColor); 80 | canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight, mPaint); 81 | canvas.restore(); 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/xinzhen/customprogressbar2/customview/MyRoundProgressBar2.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.util.AttributeSet; 9 | 10 | import com.xinzhen.customprogressbar2.R; 11 | 12 | /** 13 | * Created by C058 on 2016/5/26. 14 | * 模仿ios app store应用下载圆形进图条 15 | */ 16 | public class MyRoundProgressBar2 extends MyHoriztalProgressBar { 17 | 18 | private static final int DEFAULT_PROGRESS_RADIUS = 30; 19 | private int mRadius = dp2px(DEFAULT_PROGRESS_RADIUS); 20 | private int mInRadius; 21 | private RectF mRectf, mInRectf; 22 | 23 | public MyRoundProgressBar2(Context context) { 24 | this(context, null); 25 | } 26 | 27 | public MyRoundProgressBar2(Context context, AttributeSet attrs) { 28 | this(context, attrs, 0); 29 | } 30 | 31 | public MyRoundProgressBar2(Context context, AttributeSet attrs, int defStyleAttr) { 32 | super(context, attrs, defStyleAttr); 33 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyRoundProgressBar); 34 | mRadius = (int) ta.getDimension(R.styleable.MyRoundProgressBar_progressbar_radius, mRadius); 35 | ta.recycle(); 36 | 37 | mReachHeight = mUnReachHeight * 2; 38 | mPaint.setAntiAlias(true);//抗锯齿 39 | mPaint.setDither(true); //防抖动模式 40 | mPaint.setStyle(Paint.Style.STROKE);//画笔风格设置为空心 41 | mPaint.setStrokeCap(Paint.Cap.ROUND); 42 | } 43 | 44 | @Override 45 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 46 | 47 | int diameter = mRadius * 2 + getPaddingLeft() + getPaddingRight() + mUnReachHeight * 2; //控件宽度 默认四个padding一致 48 | int width = resolveSize(diameter, widthMeasureSpec); 49 | int height = resolveSize(diameter, heightMeasureSpec); 50 | int realWidth = Math.min(width, height);//当宽高设置不一致,取小的那个 51 | //外圆的半径 52 | mRadius = (realWidth - getPaddingLeft() - getPaddingRight() - mUnReachHeight) / 2; 53 | mRectf = new RectF(0, 0, mRadius * 2, mRadius * 2); 54 | //内圆的半径 55 | mInRadius = mRadius - mUnReachHeight; 56 | mInRectf = new RectF(0, 0, mInRadius * 2, mInRadius * 2); 57 | setMeasuredDimension(realWidth, realWidth); 58 | } 59 | 60 | @Override 61 | protected synchronized void onDraw(Canvas canvas) { 62 | 63 | canvas.save(); 64 | canvas.translate(getPaddingLeft(), getPaddingTop()); 65 | //draw unreachbar 66 | mPaint.setColor(mUnReachColor); 67 | mPaint.setStrokeWidth(mUnReachHeight); 68 | //从圆点开始画圆 69 | canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); 70 | //draw reachbar 71 | //将画布移动到画内圆的位置 72 | canvas.translate(mUnReachHeight, mUnReachHeight); 73 | mPaint.setColor(mReachColor); 74 | mPaint.setStrokeWidth(mReachHeight); 75 | float sweepAngle = getProgress() * 1.0f / getMax() * 360; 76 | canvas.drawArc(mInRectf, 0, sweepAngle, false, mPaint); 77 | // //draw text 78 | // String text = getProgress() + "%"; 79 | // int textWidth = (int) mPaint.measureText(text); 80 | // int textHeight = (int) ((mPaint.descent() + mPaint.ascent()) / 2); 81 | // mPaint.setColor(mTextColor); 82 | // canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight, mPaint); 83 | canvas.restore(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 21 | 22 | 33 | 34 | 45 | 46 | 54 | 55 | 65 | 66 | 75 | 76 | 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/com/xinzhen/customprogressbar2/customview/MyHoriztalProgressBar.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.util.AttributeSet; 8 | import android.util.TypedValue; 9 | import android.widget.ProgressBar; 10 | 11 | import com.xinzhen.customprogressbar2.R; 12 | 13 | /** 14 | * Created by C058 on 2016/5/25. 15 | */ 16 | public class MyHoriztalProgressBar extends ProgressBar { 17 | 18 | private static final int DEFAULT_REACH_COLOR = 0xff24F569; 19 | private static final int DEFAULT_UNREACH_COLOR = 0xffC0C0C0; 20 | private static final int DEFAULT_REACH_HEIGHT = 2; 21 | private static final int DEFAULT_UNREACH_HEIGHT = 2; 22 | private static final int DEFAULT_TEXT_COLOR = DEFAULT_REACH_COLOR; 23 | private static final int DEFAULT_TEXT_SIZE = 12; 24 | private static final int DEFAULT_TEXT_OFFSET = 5; 25 | 26 | protected int mReachColor = DEFAULT_REACH_COLOR; 27 | protected int mUnReachColor = DEFAULT_UNREACH_COLOR; 28 | protected int mReachHeight = dp2px(DEFAULT_REACH_HEIGHT); 29 | protected int mUnReachHeight = dp2px(DEFAULT_UNREACH_HEIGHT); 30 | protected int mTextColor = DEFAULT_TEXT_COLOR; 31 | protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE); 32 | protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET); 33 | 34 | protected Paint mPaint = new Paint(); 35 | private int mRealWidth; 36 | 37 | public MyHoriztalProgressBar(Context context) { 38 | this(context, null); 39 | } 40 | 41 | public MyHoriztalProgressBar(Context context, AttributeSet attrs) { 42 | this(context, attrs, 0); 43 | } 44 | 45 | public MyHoriztalProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { 46 | super(context, attrs, defStyleAttr); 47 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyHoriztalProgressBar); 48 | mReachColor = ta.getColor(R.styleable.MyHoriztalProgressBar_progressbar_reach_color, mReachColor); 49 | mUnReachColor = ta.getColor(R.styleable.MyHoriztalProgressBar_progressbar_unreach_color, mUnReachColor); 50 | mReachHeight = (int) ta.getDimension(R.styleable.MyHoriztalProgressBar_progressbar_reach_height, mReachHeight); 51 | mUnReachHeight = (int) ta.getDimension(R.styleable.MyHoriztalProgressBar_progressbar_unreach_height, mUnReachHeight); 52 | mTextColor = ta.getColor(R.styleable.MyHoriztalProgressBar_progressbar_text_color, mTextColor); 53 | mTextSize = (int) ta.getDimension(R.styleable.MyHoriztalProgressBar_progressbar_text_size, mTextSize); 54 | mTextOffset = (int) ta.getDimension(R.styleable.MyHoriztalProgressBar_progressbar_text_offset, mTextOffset); 55 | ta.recycle(); 56 | mPaint.setTextSize(mTextSize); 57 | } 58 | 59 | @Override 60 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 61 | int widthVal = MeasureSpec.getSize(widthMeasureSpec); 62 | int heightVal = measureHeight(heightMeasureSpec); 63 | 64 | setMeasuredDimension(widthVal, heightVal); 65 | mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); 66 | } 67 | 68 | @Override 69 | protected synchronized void onDraw(Canvas canvas) { 70 | //draw reachBar 71 | String text = getProgress() + "%"; 72 | int textWidth = (int) mPaint.measureText(text); 73 | boolean noNeedUnrechBar = false; 74 | 75 | canvas.save(); 76 | canvas.translate(getPaddingLeft(), getMeasuredHeight() / 2); 77 | float radio = getProgress() * 1.0f / getMax(); 78 | float progressX = mRealWidth * radio; 79 | if (progressX + textWidth > mRealWidth) { 80 | progressX = mRealWidth - textWidth; 81 | noNeedUnrechBar = true; 82 | } 83 | //draw reachbar 84 | mPaint.setColor(mReachColor); 85 | mPaint.setStrokeWidth(mReachHeight); 86 | float endX = progressX - mTextOffset / 2; 87 | canvas.drawLine(0, 0, endX, 0, mPaint); 88 | //draw text 89 | mPaint.setColor(mTextColor); 90 | float y = -(mPaint.descent() + mPaint.ascent())/2; 91 | canvas.drawText(text, progressX,y, mPaint); 92 | //draw unreachbar 93 | if (!noNeedUnrechBar) { 94 | mPaint.setColor(mUnReachColor); 95 | mPaint.setStrokeWidth(mUnReachHeight); 96 | float startX = progressX + textWidth + mTextOffset / 2; 97 | canvas.drawLine(startX, 0, mRealWidth, 0, mPaint); 98 | } 99 | canvas.restore(); 100 | } 101 | 102 | private int measureHeight(int heightMeasureSpec) { 103 | int mode = MeasureSpec.getMode(heightMeasureSpec); 104 | int height = MeasureSpec.getSize(heightMeasureSpec); 105 | int result = 0; 106 | if (mode == MeasureSpec.EXACTLY||mode == MeasureSpec.UNSPECIFIED) { 107 | result = height; 108 | } else if (mode == MeasureSpec.AT_MOST) { 109 | int textHeight = (int) (mPaint.descent() - mPaint.ascent()); 110 | result = getPaddingTop() + getPaddingBottom() + Math.max(Math.max(mReachHeight, mUnReachHeight), textHeight); 111 | // { 112 | // result = Math.min(result, height); 113 | // } 114 | } 115 | return result; 116 | } 117 | 118 | protected int dp2px(int dp) { 119 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); 120 | } 121 | 122 | protected int sp2px(int sp) { 123 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics()); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/xinzhen/customprogressbar2/customview/MyHoriztalProgressBar2.java: -------------------------------------------------------------------------------- 1 | package com.xinzhen.customprogressbar2.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Bitmap; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.PorterDuffXfermode; 10 | import android.util.AttributeSet; 11 | import android.util.TypedValue; 12 | import android.widget.ProgressBar; 13 | 14 | import com.xinzhen.customprogressbar2.R; 15 | 16 | 17 | /** 18 | * Created by C058 on 2016/7/1. 19 | */ 20 | public class MyHoriztalProgressBar2 extends ProgressBar { 21 | 22 | private final int PROGRESSBAR_DEFAULT_HEIGHT = dp2px(10);//px 23 | private final int PROGRESSBAR_DEFAULT_REACH_COLOR = 0xfff456c5; 24 | private final int PROGRESSBAR_DEFAULT_UNREACH_COLOR = 0xFFCECECE; 25 | 26 | private int mProgressbarHeight; 27 | private int mReachColor; 28 | private int mUnReachColor; 29 | private int mRealWidth; 30 | private Paint mPaint; 31 | 32 | private Bitmap mDstBmp, mSrcBmp; 33 | private Canvas mSrcCanvas; 34 | float progressX; 35 | 36 | public MyHoriztalProgressBar2(Context context) { 37 | this(context, null); 38 | } 39 | 40 | public MyHoriztalProgressBar2(Context context, AttributeSet attrs) { 41 | this(context, attrs, 0); 42 | } 43 | 44 | public MyHoriztalProgressBar2(Context context, AttributeSet attrs, int defStyleAttr) { 45 | super(context, attrs, defStyleAttr); 46 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyHoriztalProgressBar2); 47 | mProgressbarHeight = (int) ta.getDimension(R.styleable.MyHoriztalProgressBar2_progressbar_height, PROGRESSBAR_DEFAULT_HEIGHT); 48 | mReachColor = ta.getColor(R.styleable.MyHoriztalProgressBar2_reach_color, PROGRESSBAR_DEFAULT_REACH_COLOR); 49 | mUnReachColor = ta.getColor(R.styleable.MyHoriztalProgressBar2_unreach_color, PROGRESSBAR_DEFAULT_UNREACH_COLOR); 50 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 51 | mPaint.setStrokeWidth(mProgressbarHeight); 52 | mPaint.setStrokeCap(Paint.Cap.ROUND); 53 | } 54 | 55 | @Override 56 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 57 | int widthVal = MeasureSpec.getSize(widthMeasureSpec); 58 | int heightVal = measureHeight(heightMeasureSpec); 59 | 60 | setMeasuredDimension(widthVal, heightVal); 61 | mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); 62 | mDstBmp = getDstPic();//完成测量后再创建图片\ 63 | mSrcBmp = Bitmap.createBitmap(getMeasuredWidth(), mProgressbarHeight, Bitmap.Config.ARGB_8888); 64 | } 65 | 66 | @Override 67 | protected synchronized void onDraw(Canvas canvas) { 68 | super.onDraw(canvas); 69 | 70 | progressX = mRealWidth * getProgress() / 100; 71 | mSrcBmp = getSrcPic(progressX); 72 | int layer = canvas.saveLayer(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint, Canvas.ALL_SAVE_FLAG); 73 | canvas.translate(getPaddingLeft(), (getMeasuredHeight() - mProgressbarHeight) / 2); //这个高度上的位移让我想了很久。画图和普通的画线不一样。画图是从图片的(0,0)点开始画的,画线是从(0,线高度的一半)开始画的。 74 | canvas.drawBitmap(mDstBmp, 0, 0, mPaint); 75 | mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); 76 | canvas.drawBitmap(mSrcBmp, 0, 0, mPaint); 77 | mPaint.setXfermode(null); 78 | canvas.restoreToCount(layer); 79 | } 80 | 81 | /** 82 | * 测量控件高度 83 | * 84 | * @param heightMeasureSpec 85 | * @return 86 | */ 87 | private int measureHeight(int heightMeasureSpec) { 88 | int height = MeasureSpec.getSize(heightMeasureSpec); 89 | int mode = MeasureSpec.getMode(heightMeasureSpec); 90 | int result = 0; 91 | if (mode == MeasureSpec.EXACTLY) { 92 | result = height; 93 | } else if (mode == MeasureSpec.AT_MOST) { 94 | result = getPaddingTop() + getPaddingBottom() + mProgressbarHeight * 2; 95 | } 96 | return result; 97 | } 98 | 99 | /** 100 | * 获取源图像,因为使用次数较多,所以将一些资源抽了出来,避免频繁gc操作,耗费内存 101 | * 102 | * @param progress 103 | * @return 104 | */ 105 | private Bitmap getSrcPic(float progress) { 106 | mSrcCanvas = new Canvas(mSrcBmp); 107 | mPaint.setColor(mReachColor); 108 | //canvas.drawLine(mProgressbarHeight, mProgressbarHeight / 2, progress - mProgressbarHeight, mProgressbarHeight / 2, paint); 109 | if (getProgress() <= 50) { 110 | mSrcCanvas.drawLine(0, mProgressbarHeight / 2, progress, mProgressbarHeight / 2, mPaint); 111 | } else { 112 | mSrcCanvas.drawLine(0, mProgressbarHeight / 2, progress - mProgressbarHeight / 2, mProgressbarHeight / 2, mPaint); 113 | } 114 | return mSrcBmp; 115 | } 116 | 117 | /** 118 | * 获取目标图层图像,初始一次就行了。用临时变量 119 | * 120 | * @return 121 | */ 122 | private Bitmap getDstPic() { 123 | //创建画布,不用mRealWidth的原因是加入给控件设定10dp宽度,在设定10dp的pading,那么这个mReaalWidth则为负数,创建bitmap会报错,同理,高度我们也是限定了的 124 | Bitmap bitmap = Bitmap.createBitmap(getMeasuredWidth(), mProgressbarHeight, Bitmap.Config.ARGB_8888); 125 | Canvas canvas = new Canvas(bitmap); 126 | mPaint.setColor(mUnReachColor); 127 | //因为线帽是线段两头的样式,是多出来的一部分,如果不设置线帽从0开始就可以,线帽长度一半为线的高度。 128 | canvas.drawLine(mProgressbarHeight, mProgressbarHeight / 2, mRealWidth - mProgressbarHeight, mProgressbarHeight / 2, mPaint); 129 | return bitmap; 130 | } 131 | 132 | /** 133 | * dp转px 134 | * 135 | * @param dp 136 | * @return 137 | */ 138 | private int dp2px(int dp) { 139 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /customprogressbar.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | --------------------------------------------------------------------------------