├── .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 | 
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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
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 |
--------------------------------------------------------------------------------