Skip to content

Commit 0264d37

Browse files
committed
# Conflicts: # app/build/outputs/apk/debug/app-debug.apk
2 parents 3991e66 + dd414c4 commit 0264d37

File tree

5 files changed

+185
-15
lines changed

5 files changed

+185
-15
lines changed

Loadingbutton/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ android {
88
minSdkVersion 17
99
targetSdkVersion 28
1010
versionCode 100
11-
versionName "1.0.0-alpha1"
11+
versionName "1.0.0-alpha5"
1212

1313
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1414

Loadingbutton/src/main/java/com/flod/loadingbutton/DrawableTextView.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* 2、设置Drawable的大小 √
2828
* 3、文字居中,图片靠边居中 √
2929
* 4、多次setCompoundDrawablesRelative,图片会发生偏移 √
30-
* 5、寻找一个合适的测量文字大小的时机,避免多次测量消耗性能
30+
* 5、寻找一个合适的测量文字大小的时机,避免多次测量
3131
* 6、在draw时,避免用取出旧的drawable的bounds绘制,需要预先取出并存储起来,还需要注意在存储bounds时是不是有平移过 √
3232
* 7、foreground会受平移影响 √
3333
* 8、如果是只有hint没有Text需要也需要测量出文字大小√
@@ -52,7 +52,8 @@ public class DrawableTextView extends AppCompatTextView {
5252
private float mTextHeight;
5353

5454
private boolean firstLayout;
55-
private boolean isCenter; //Gravity是否是居中
55+
private boolean isCenterHorizontal; //Gravity是否水平居中
56+
private boolean isCenterVertical; //Gravity是否垂直居中
5657
private boolean enableCenterDrawables; //drawable跟随文本居中
5758
private boolean enableTextInCenter; //默认情况下文字与图片共同居中,开启后文字在最中间,图片紧挨
5859

@@ -109,8 +110,8 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
109110
super.onLayout(changed, left, top, right, bottom);
110111
if (enableCenterDrawables) {
111112
final int absoluteGravity = Gravity.getAbsoluteGravity(getGravity(), getLayoutDirection());
112-
isCenter = (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL
113-
|| (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL;
113+
isCenterHorizontal = (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL;
114+
isCenterVertical = (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL;
114115
}
115116

116117
if (!firstLayout) {
@@ -131,7 +132,7 @@ protected void onFirstLayout(int left, int top, int right, int bottom) {
131132
@Override
132133
protected void onDraw(Canvas canvas) {
133134

134-
if (enableCenterDrawables && isCenter) {
135+
if (enableCenterDrawables && (isCenterHorizontal | isCenterVertical)) {
135136

136137
//画布的偏移量
137138
int transX = 0, transY = 0;
@@ -141,7 +142,9 @@ protected void onDraw(Canvas canvas) {
141142
int offset = (int) calcOffset(POSITION.START);
142143
mDrawables[POSITION.START].setBounds(bounds.left + offset, bounds.top,
143144
bounds.right + offset, bounds.bottom);
144-
transX -= (mDrawablesBounds[POSITION.START].width() + getCompoundDrawablePadding()) >> 1;
145+
146+
if (isCenterHorizontal)
147+
transX -= (mDrawablesBounds[POSITION.START].width() + getCompoundDrawablePadding()) >> 1;
145148
}
146149

147150
if (mDrawables[POSITION.TOP] != null) {
@@ -151,7 +154,8 @@ protected void onDraw(Canvas canvas) {
151154
mDrawables[POSITION.TOP].setBounds(bounds.left, bounds.top + offset,
152155
bounds.right, bounds.bottom + offset);
153156

154-
transY -= (mDrawablesBounds[POSITION.TOP].height() + getCompoundDrawablePadding()) >> 1;
157+
if (isCenterVertical)
158+
transY -= (mDrawablesBounds[POSITION.TOP].height() + getCompoundDrawablePadding()) >> 1;
155159
}
156160

157161
if (mDrawables[POSITION.END] != null) {
@@ -160,7 +164,8 @@ protected void onDraw(Canvas canvas) {
160164
mDrawables[POSITION.END].setBounds(bounds.left + offset, bounds.top,
161165
bounds.right + offset, bounds.bottom);
162166

163-
transX += (mDrawablesBounds[POSITION.END].width() + getCompoundDrawablePadding()) >> 1;
167+
if (isCenterHorizontal)
168+
transX += (mDrawablesBounds[POSITION.END].width() + getCompoundDrawablePadding()) >> 1;
164169
}
165170

166171
if (mDrawables[POSITION.BOTTOM] != null) {
@@ -169,7 +174,8 @@ protected void onDraw(Canvas canvas) {
169174
mDrawables[POSITION.BOTTOM].setBounds(bounds.left, bounds.top + offset,
170175
bounds.right, bounds.bottom + offset);
171176

172-
transY += (mDrawablesBounds[POSITION.BOTTOM].height() + getCompoundDrawablePadding()) >> 1;
177+
if (isCenterVertical)
178+
transY += (mDrawablesBounds[POSITION.BOTTOM].height() + getCompoundDrawablePadding()) >> 1;
173179
}
174180

175181
if (enableTextInCenter) {

Loadingbutton/src/main/java/com/flod/loadingbutton/LoadingButton.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ private void init(Context context, AttributeSet attrs) {
9898

9999
//getConfig
100100
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingButton);
101-
enableShrink = array.getBoolean(R.styleable.LoadingButton_enableShrink, false);
102-
disableClickOnLoading = array.getBoolean(R.styleable.LoadingButton_disableClickOnLoading, false);
101+
enableShrink = array.getBoolean(R.styleable.LoadingButton_enableShrink, true);
102+
disableClickOnLoading = array.getBoolean(R.styleable.LoadingButton_disableClickOnLoading, true);
103103
mShrinkDuration = array.getInt(R.styleable.LoadingButton_shrinkDuration, 450);
104104
int loadingDrawableSize = array.getDimensionPixelSize(R.styleable.LoadingButton_loadingEndDrawableSize, (int) (enableShrink ? getTextSize() * 2 : getTextSize()));
105105
int loadingDrawableColor = array.getColor(R.styleable.LoadingButton_loadingDrawableColor, getTextColors().getDefaultColor());

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LoadingButton [![LoadingButton](https://jitpack.io/v/FlodCoding/LoadingButton.svg)](https://jitpack.io/#FlodCoding/LoadingButton)
22

3-
一个小巧灵活的带加载功能的按钮控件,继承自[DrawableTextView](),加载动画来自于[CircularProgressDrawable](https://developer.android.google.cn/reference/android/support/v4/widget/CircularProgressDrawable?hl=en)
3+
一个小巧灵活的带加载功能的按钮控件,继承自[DrawableTextView](https://github.com/FlodCoding/LoadingButton/blob/master/DrawableText.md),加载动画来自于[CircularProgressDrawable](https://developer.android.google.cn/reference/android/support/v4/widget/CircularProgressDrawable?hl=en)
44

55
## 特性
66
* 支持按钮收缩
@@ -23,10 +23,10 @@
2323

2424
dependencies {
2525
//Androidx
26-
implementation 'com.github.FlodCoding:LoadingButton:1.0.0-alpha3'
26+
implementation 'com.github.FlodCoding:LoadingButton:1.0.0-alpha5'
2727

2828
//Support-appcompat
29-
implementation 'com.github.FlodCoding:LoadingButton:1.0.0-alpha3-support'
29+
implementation 'com.github.FlodCoding:LoadingButton:1.0.0-alpha4-support'
3030
}
3131

3232

实现原理记录.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
## 简介
2+
---
3+
介绍一个带加载功能的按钮控件的实现原理,加载动画来自于[CircularProgressDrawable](https://developer.android.google.cn/reference/android/support/v4/widget/CircularProgressDrawable?hl=en)
4+
<br/>
5+
## 效果图(最终效果图在最后面)
6+
---
7+
![](https://upload-images.jianshu.io/upload_images/7565394-4d54f09ac73d0dd0.gif?imageMogr2/auto-orient/strip)
8+
![](https://upload-images.jianshu.io/upload_images/7565394-4f37c5e6d67508c1.gif?imageMogr2/auto-orient/strip)
9+
10+
<br/>
11+
12+
## 下面开始介绍实现的原理
13+
---
14+
15+
![](https://upload-images.jianshu.io/upload_images/7565394-0cd02c573f2a30e1.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
16+
17+
18+
#### 加载动画
19+
圆环加载就是用setCompoundDrawables放到TextView的drawablewStart中,将文字的Gravity设置Center
20+
```
21+
public class DrawableText extends AppCompatTextView {
22+
..... 省略
23+
24+
25+
private void init(){
26+
mProgressDrawable = new CircularProgressDrawable(getContext());
27+
mProgressDrawable.setColorSchemeColors(getTextColors().getDefaultColor());
28+
mProgressDrawable.setBounds(0, 0, 80, 80);
29+
setCompoundDrawables(mProgressDrawable, null, null, null);
30+
mProgressDrawable.setStrokeWidth(10);
31+
}
32+
33+
public void start(){
34+
mProgressDrawable.start();
35+
}
36+
37+
public void stop(){
38+
mProgressDrawable.stop();
39+
}
40+
}
41+
```
42+
43+
结果效果是这个亚子的:
44+
![](https://upload-images.jianshu.io/upload_images/7565394-fd9d213c563c27b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
45+
46+
![](https://upload-images.jianshu.io/upload_images/7565394-def8c86dd0542b09.gif?imageMogr2/auto-orient/strip)
47+
48+
看来实际的效果与我们想象中的不太一样,原来Drawable在一开始我们并没有设置它的位置
49+
```
50+
drawable.setBounds(0, 0, 80, 80)
51+
```
52+
<br/>
53+
<br/>
54+
55+
那么我们应该如何将drawable居中显示文字的旁边?
56+
用一张草图表示大概是这个样子的:
57+
![](https://upload-images.jianshu.io/upload_images/7565394-ac51865a03c7a389.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
58+
59+
中间那部分就是我们想要的位移,通过下面的计算就可以得到所要的位移,
60+
而getWidth()这些参数需要在Layout之后才可以得到,
61+
所以我们干脆在onDraw中对drawable进行位移
62+
```
63+
//计算需要的位移
64+
private float calcOffset() {
65+
//getCompoundPaddingStart() = paddingStart + drawableWidth + drawablePadding
66+
return (getWidth() - (getCompoundPaddingStart() + getTextWidth())) / 2;
67+
68+
}
69+
70+
//计算文字的长度
71+
private float getTextWidth() {
72+
//在draw时不断计算TextWidth似乎是不合理的,当然目前只是演示用法
73+
//再者若是多行文字,则测量结果会偏大,但此处不再讨论,有兴趣可以直接去看源码
74+
return getPaint().measureText(getText().toString());
75+
}
76+
```
77+
78+
79+
```
80+
81+
private void init(){
82+
mProgressDrawable = new CircularProgressDrawable(getContext());
83+
mProgressDrawable.setColorSchemeColors(getTextColors().getDefaultColor());
84+
mProgressDrawable.setBounds(0, 0, 80, 80);
85+
//先保存Bounds
86+
bounds = mProgressDrawable.copyBounds();
87+
setCompoundDrawables(mProgressDrawable, null, null, null);
88+
mProgressDrawable.setStrokeWidth(10);
89+
}
90+
91+
@Override
92+
protected void onDraw(Canvas canvas) {
93+
final int offsetX = (int) calcOffsetX();
94+
mProgressDrawable.setBounds(offsetX, bounds.top, bounds.right + offsetX, bounds.bottom);
95+
//我们并不能通过offset来直接位移mProgressDrawable,这样为导致动画每次绘制时都会在原来位移过后的基础上再不断向右位移
96+
//mProgressDrawable.getBounds().offset(offsetX,0);
97+
super.onDraw(canvas);
98+
}
99+
100+
```
101+
#### 经过位移的效果
102+
![](https://upload-images.jianshu.io/upload_images/7565394-187ca9d747d23fb1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
103+
104+
105+
似乎看起来还是有一点点别扭,从效果上看出文字和drawable是一起居中的,
106+
看了一下TextView的源码发现setCompoundDrawables后会先划分出TextView左侧及右侧drawable需要的空间,
107+
然后再按照剩余的空间来居中显示,
108+
所以最后得到通过位移得到的效果是文字和drawable一起居中显示的。
109+
110+
为了让文字在整个布局的中间,我们可以通过平移画布来实现文字的居中效果
111+
```
112+
113+
@Override
114+
protected void onDraw(Canvas canvas) {
115+
final int offsetX = (int) calcOffsetX();
116+
mProgressDrawable.setBounds(offsetX, bounds.top, bounds.right + offsetX, bounds.bottom);
117+
//我们并不能通过offset来直接位移mProgressDrawable,这样为导致动画每次绘制时都会不断向右位移
118+
//mProgressDrawable.getBounds().offset(offsetX,0);
119+
120+
//计算画布向左平移的距离
121+
final int tranX = (bounds.width() + getCompoundDrawablePadding()) / 2;
122+
canvas.translate(-tranX, 0);
123+
124+
super.onDraw(canvas);
125+
}
126+
127+
```
128+
#### 我们可以看到,文字也居中了
129+
![](https://upload-images.jianshu.io/upload_images/7565394-75cd27932e9cda81.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/150)
130+
131+
132+
#### 最后再说一下收缩效果的实现方式
133+
主要也是通过 getLayoutParams().width和 getLayoutParams().height来改变布局的尺寸,
134+
在开始收缩时先将文本设置为空字符、drawablePadding设为0,然后再开始收缩动画,具体的方式可以自行尝试
135+
```
136+
mShrinkAnimator = ValueAnimator.ofFloat(0, 1f);
137+
mShrinkAnimator.setDuration(mShrinkDuration);
138+
mShrinkAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
139+
@Override
140+
public void onAnimationUpdate(ValueAnimator animation) {
141+
// mRootViewSizeSaved是预先保存原先的尺寸,getShrinkSize() 是缩放后的尺寸
142+
// b = getRootViewSize()
143+
// k = getRootViewSize() - getLoadingSize
144+
getLayoutParams().width = (int) ((getShrinkSize() - mRootViewSizeSaved[0]) * (float) animation.getAnimatedValue() + mRootViewSizeSaved[0]);
145+
getLayoutParams().height = (int) ((getShrinkSize() - mRootViewSizeSaved[1]) * (float) animation.getAnimatedValue() + mRootViewSizeSaved[1]);
146+
requestLayout();
147+
}
148+
});
149+
```
150+
<br/><br/>
151+
152+
# 结语
153+
---
154+
本文介绍了带加载效果的按钮实现整体思路,然鹅如果想要真正使用并没有文中介绍的那么简单,还需要考虑各种细节和因素。(头发又变少了呢~)
155+
最后可以看下完整实现的效果,已经上传到github上了([LoadingButton](https://github.com/FlodCoding/LoadingButton)),加了一些功能(本来只是想简单实现一个按钮旁边有一个Loading,结果功能越写越多就变成这样,苦笑~
156+
有兴趣朋友可以给个星星,提提issue喝喝茶,我是新来的第一次写这种文章请多多包涵呀。
157+
158+
![](https://upload-images.jianshu.io/upload_images/7565394-3ae40e74968373b6.gif?imageMogr2/auto-orient/strip)
159+
![](https://upload-images.jianshu.io/upload_images/7565394-70294e35ea498122.gif?imageMogr2/auto-orient/strip)
160+
161+
162+
163+
164+

0 commit comments

Comments
 (0)