glide加载圆角和自定义圆角view_自定义View,带你撸一个带加载功能的按钮

67ab9078a312959f1f8d08e24eb3fabc.png

本文来自没有昵称投稿文章地址:https://www.jianshu.com/p/68044f728c46

介绍一个带加载功能的按钮控件的实现原理,加载动画来自于CircularProgressDrawable

效果图(最终效果图在最后面)

c4e3caede401df218697f0779e3f48cb.gif74e3c0d9abcb3449a6f5d7884bc48214.gif

实现原理

加载圆环就是用setCompoundDrawables放到TextViewdrawablewStart中,文字将的Gravity设置Center

public class DrawableText extends AppCompatTextView {
..... 省略


private void init(){
mProgressDrawable = new CircularProgressDrawable(getContext());
mProgressDrawable.setColorSchemeColors(getTextColors().getDefaultColor());
mProgressDrawable.setBounds(0, 0, 80, 80);
setCompoundDrawables(mProgressDrawable, null, null, null);
mProgressDrawable.setStrokeWidth(10);
}

public void start(){
mProgressDrawable.start();
}

public void stop(){
mProgressDrawable.stop();
}
}

结果效果是这个样子的:

f20cc8abb381d6ba532af8e0b4476bc0.png

看来实际的效果与我们想象中的不太一样,原来Drawable在一开始我们并没有设置它的位置

drawable.setBounds(0, 0, 80, 80)

那么我们应该如何将绘制居中显示文字的旁边?

用一张草图表示大概是这个样子的:

b05f912c695fff08616efe15eec3a397.png

中间那部分就是我们想要的位移,通过下面的计算就可以得到所要的位移,而getWidth()这些参数需要在布局之后才可以得到,所以我们干脆在onDraw中对drawable进行位移。

  //计算需要的位移
private float calcOffset() {
//getCompoundPaddingStart() = paddingStart + drawableWidth + drawablePadding
return (getWidth() - (getCompoundPaddingStart() + getTextWidth())) / 2;

}

//计算文字的长度
private float getTextWidth() {
//在draw时不断计算TextWidth似乎是不合理的,当然目前只是演示用法
//再者若是多行文字,则测量结果会偏大,但此处不再讨论,有兴趣可以直接去看源码
return getPaint().measureText(getText().toString());
}

private void init(){
mProgressDrawable = new CircularProgressDrawable(getContext());
mProgressDrawable.setColorSchemeColors(getTextColors().getDefaultColor());
mProgressDrawable.setBounds(0, 0, 80, 80);
//先保存Bounds
bounds = mProgressDrawable.copyBounds();
setCompoundDrawables(mProgressDrawable, null, null, null);
mProgressDrawable.setStrokeWidth(10);
}

@Override
protected void onDraw(Canvas canvas) {
final int offsetX = (int) calcOffsetX();
mProgressDrawable.setBounds(offsetX, bounds.top, bounds.right + offsetX, bounds.bottom);
//我们并不能通过offset来直接位移mProgressDrawable,这样为导致动画每次绘制时都会在原来位移过后的基础上再不断向右位移
//mProgressDrawable.getBounds().offset(offsetX,0);
super.onDraw(canvas);
}

经过位移的效果
cf05c4e6c7dae660ee3721bf5f49d9de.png

似乎看起来还是有一点点别扭,效果从上看出文字状语从句:drawable的英文一起居中的,一下看了TextView的源码发现setCompoundDrawables后会先划分出TextView左侧及右侧drawable需要的空间,然后再按照剩余的空间来居中显示,所以得到求最后通过位移得到的效果的英文文字状语从句:drawable一起居中显示的。

为了让文字在整个布局的中间,我们可以通过平移画布来实现文字的居中效果。

 @Override
protected void onDraw(Canvas canvas) {
final int offsetX = (int) calcOffsetX();
mProgressDrawable.setBounds(offsetX, bounds.top, bounds.right + offsetX, bounds.bottom);
//我们并不能通过offset来直接位移mProgressDrawable,这样为导致动画每次绘制时都会不断向右位移
//mProgressDrawable.getBounds().offset(offsetX,0);

//计算画布向左平移的距离
final int tranX = (bounds.width() + getCompoundDrawablePadding()) / 2;
canvas.translate(-tranX, 0);

super.onDraw(canvas);
}

我们可以看到,文字也居中了:

d4db6218809197c0f71636d92774a4e0.png
最后再说一下收缩效果的实现方式

主要也是通过getLayoutParams().widthgetLayoutParams().height来改变布局的尺寸,在开始收缩时先将文本设置为空drawablePadding字符0,设为,然后再开始收缩动画,具体的方式可以自行尝试。

        mShrinkAnimator = ValueAnimator.ofFloat(0, 1f);
mShrinkAnimator.setDuration(mShrinkDuration);
mShrinkAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// mRootViewSizeSaved是预先保存原先的尺寸,getShrinkSize() 是缩放后的尺寸
// b = getRootViewSize()
// k = getRootViewSize() - getLoadingSize
getLayoutParams().width = (int) ((getShrinkSize() - mRootViewSizeSaved[0]) * (float) animation.getAnimatedValue() + mRootViewSizeSaved[0]);
getLayoutParams().height = (int) ((getShrinkSize() - mRootViewSizeSaved[1]) * (float) animation.getAnimatedValue() + mRootViewSizeSaved[1]);
requestLayout();
}
});

最终效果图:

9c7815c4966806ebbf4f200f29d53e00.gif

b0c91c12e8694a10d3dd609b91b80745.gif

结语

本文介绍了带加载效果的按钮实现整体思路,然鹅如果想要真正使用并没有文中介绍的那么简单,还需要考虑各种细节和因素。(头发又变少了呢〜)

最后可以看下完整实现的效果,已经上传到github上了(LoadingButton),加了一些功能(本来只是想简单实现一个按钮旁边有一个Loading,结果功能越写越多就变成这样,苦笑〜)

有兴趣朋友可以给个明星,提提问题喝喝茶,我是新来的第一次写这种文章请多多包涵呀。

---end---

推荐阅读:

自定义Layout,让子View支持圆角属性

牛逼了,轻松实现RecyclerView 拖动多选功能

Android 实现滴滴出行App功能

1af8cf00a166e104c61897865f4c2f8e.png 每一个“在看”,我都当成真的喜欢
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值