这次带来一个个性化的按钮,再点击以后可以变成Loading,Loading完成以后又可以拉伸会按钮。会不多说,下面开始。
首先还是定义几个资源文件。
button_main_color_up.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="#45a8ca" />
<gradient
android:endColor="#45a8ca"
android:startColor="#6fd1e7" />
</shape>
button_main_color_down.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp" />
<solid android:color="#45a8aa" />
<gradient
android:endColor="#45a8aa"
android:startColor="#6fd1c7" />
</shape>
button_main_color_selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_main_color_up" android:state_pressed="false"></item>
<item android:drawable="@drawable/button_main_color_down" android:state_pressed="true"></item>
</selector>
circle_loading.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="18dp"
android:shape="ring"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="#45a8ca" />
<gradient
android:endColor="#45a8ca"
android:startColor="#0000"
android:type="sweep" />
</shape>
然后就可以上本体了:
LoadingButton.java:
public class LoadingButton extends Button {
private Context context;
// 开始Loading时的回调
private OnStartListener startListener;
// 结束Loading时的回调
private OnFinishListener finishListener;
// 开始和结束Loading时的回调
private OnLoadingListener listener;
// Loading动画旋转周期
private int rotateDuration = 1000;
// 按钮缩成Loading动画的时间
private int reduceDuration = 350;
// Loading旋转动画控制器
private Interpolator rotateInterpolator;
// 按钮缩成Loading动画的控制器
private Interpolator reduceInterpolator;
private int width;
private int height;
private String text;
// 是否在Loading中
private boolean isLoading = false;
public LoadingButton(Context context) {
this(context, null);
}
public LoadingButton(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public LoadingButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
this.context = context;
setGravity(Gravity.CENTER);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (width == 0) width = getMeasuredWidth();
if (height == 0) height = getMeasuredHeight();
}
/**
* 播放按钮缩成Loading的动画
*/
private void showStartLoadAnimation() {
ValueAnimator animator = new ValueAnimator().ofInt(width, height);
animator.setDuration(reduceDuration);
if (reduceInterpolator != null) animator.setInterpolator(reduceInterpolator);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
getLayoutParams().width = (int) animation.getAnimatedValue();
requestLayout();
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
setBackgroundDrawable(context.getResources().getDrawable(R.drawable.button_main_color_selector));
setEnabled(false);
text = getText().toString();
setText("");
}
@Override
public void onAnimationEnd(Animator animation) {
showLoadingAnimation();
}
});
animator.start();
}
/**
* 播放Loading动画
*/
private void showLoadingAnimation() {
RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(rotateDuration);
animation.setInterpolator(rotateInterpolator != null ? rotateInterpolator : new LinearInterpolator());
animation.setRepeatCount(-1);
setBackgroundDrawable(context.getResources().getDrawable(R.drawable.circle_loading));
if (startListener != null) {
startListener.onStart();
} else if (listener != null) {
listener.onStart();
}
startAnimation(animation);
isLoading = true;
}
/**
* 播放Loading拉伸成按钮的动画
*/
private void showFinishLoadAnimation() {
ValueAnimator animator = new ValueAnimator().ofInt(height, width);
animator.setDuration(reduceDuration);
if (reduceInterpolator != null) animator.setInterpolator(reduceInterpolator);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
getLayoutParams().width = (int) animation.getAnimatedValue();
requestLayout();
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
setBackgroundDrawable(context.getResources().getDrawable(R.drawable.button_main_color_selector));
setEnabled(false);
}
@Override
public void onAnimationEnd(Animator animation) {
setText(text);
setEnabled(true);
if (finishListener != null) {
finishListener.onFinish();
} else if (listener != null) {
listener.onFinish();
}
}
});
animator.start();
isLoading = false;
}
/**
* 开始Loading
*/
public void startLoading() {
if (!isLoading) {
clearAnimation();
showStartLoadAnimation();
}
}
/**
* 开始Loading
*
* @param listener Loading开始时的回调
*/
public void startLoading(OnStartListener listener) {
if (!isLoading) {
this.startListener = listener;
clearAnimation();
showStartLoadAnimation();
}
}
/**
* 结束Loading
*/
public void finishLoading() {
if (isLoading) {
clearAnimation();
showFinishLoadAnimation();
}
}
/**
* 结束Loading
*
* @param listener Loading结束时的回调
*/
public void finishLoading(OnFinishListener listener) {
if (isLoading) {
this.finishListener = listener;
clearAnimation();
showFinishLoadAnimation();
}
}
/**
* 设置Loading开始和结束时的回调接口
*
* @param listener
*/
public void setOnLoadingListener(OnLoadingListener listener) {
this.listener = listener;
}
/**
* 设置按钮缩成Loading动画的时间
*
* @param reduceDuration 时间,单位毫秒
*/
public void setReduceDuration(int reduceDuration) {
this.reduceDuration = reduceDuration;
}
/**
* 设置Loading动画旋转周期
*
* @param rotateDuration 旋转周期,单位毫秒
*/
public void setRotateDuration(int rotateDuration) {
this.rotateDuration = rotateDuration;
}
/**
* 获取是否正在Loading
*
* @return
*/
public boolean isLoading() {
return isLoading;
}
/**
* 设置Loading旋转动画控制器
*
* @param rotateInterpolator
*/
public void setRotateInterpolator(Interpolator rotateInterpolator) {
this.rotateInterpolator = rotateInterpolator;
}
/**
* 按钮缩成Loading动画的控制器
*
* @param reduceInterpolator
*/
public void setReduceInterpolator(Interpolator reduceInterpolator) {
this.reduceInterpolator = reduceInterpolator;
}
/**
* Loading开始时的回调接口
*/
public interface OnStartListener {
void onStart();
}
/**
* Loading结束时的回调接口
*/
public interface OnFinishListener {
void onFinish();
}
/**
* Loading开始和结束时的回调接口
*/
public interface OnLoadingListener {
void onStart();
void onFinish();
}
}
就一个文件,复制即可用,上MainActivity.java和activity_main.xml:
MainActivity.java:
public class MainActivity extends Activity {
private LoadingButton button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData() {
}
private void initView() {
button = (LoadingButton) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startLoading();
}
});
}
private void startLoading() {
button.startLoading(new LoadingButton.OnStartListener() {
@Override
public void onStart() {
Toast.makeText(MainActivity.this, "LOADING START", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finishLoading();
}
}, 5000);
}
});
}
private void finishLoading() {
button.finishLoading(new LoadingButton.OnFinishListener() {
@Override
public void onFinish() {
Toast.makeText(MainActivity.this, "LOADING FINISH", Toast.LENGTH_SHORT).show();
}
});
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.min.loadingbutton.LoadingButton
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:background="@drawable/button_main_color_selector"
android:text="CLICK"
android:textColor="#ffffff" />
</LinearLayout
用法很简单,startLoading()方法开始Loading,finishLoading方法结束Loading,开始和结束的回调可以在相应的接口里接收。
看一下效果:
控件支持的一些参数设置在源码注释里已经写的很清楚了,大家可以自己试一试。
最后附上源码地址:点击打开链接
这次的内容就到这里,我们下次再见。