Awesome
CountDownTimerProject
仿京东首页倒计时控件 前言
这几天翻看之前写的一些代码,感觉整体的代码设计上有点缺陷,为此买了本《设计模式之禅》,随说之前也研究过设计模式,但长时间不用忘了差不多,买本书补充下知识。
今天给大家带来的是自定义倒计时控件,为什么要写这个,是因为今天在京东首页看到了这个全场秒杀的倒计时控件,感觉挺不错的,于是乎写给大家看看,也算是一个思路吧,当然实现这种样式的控件方法有很多,大家可以按照自己的思路来写,那我这个倒计时有什么特点呢?可定制,颜色,背景,四周角度,文字大小都可定制。
先来看看效果吧:
http://img.blog.csdn.net/20160329124233862
倒计时控件
如何使用
下载项目后将里面相关代码复制过去,创建一个继承BaseCountDownTimerView的类。
如以下:
package com.example.countdowntimerproject.view;
import android.content.Context; import android.util.AttributeSet;
import com.example.countdowntimerproject.view.base.BaseCountDownTimerView;
public class MainDownTimerView extends BaseCountDownTimerView{
public MainDownTimerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MainDownTimerView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MainDownTimerView(Context context) {
this(context,null);
}
@Override
protected String getStrokeColor() {
return "333333";
}
@Override
protected String getTextColor() {
return "000033";
}
@Override
protected int getCornerRadius() {
return 1;
}
@Override
protected int getTextSize() {
return 15;
}
@Override
protected String getBackgroundColor() {
return null;
}
}
创建继承自BaseCountDownTimerView的类时会重写几个方法,这几个方法含义如下:
/** * 获取边框颜色 * * @return */ protected abstract String getStrokeColor();
/**
* 设置背景色
*
* @return
*/
protected abstract String getBackgroundColor();
/**
* 获取文字颜色
*
* @return
*/
protected abstract String getTextColor();
/**
* 获取边框圆角
*
* @return
*/
protected abstract int getCornerRadius();
/**
* 获取标签文字大小
*
* @return
*/
protected abstract int getTextSize();
创建完毕后,创建我们的xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" >
<com.example.countdowntimerproject.view.MainDownTimerView
android:id="@+id/count_down_timer_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
</com.example.countdowntimerproject.view.MainDownTimerView>
</RelativeLayout>
接着在Activity中使用:
package com.example.countdowntimerproject;
import android.app.Activity; import android.os.Bundle;
import com.example.countdowntimerproject.view.MainDownTimerView;
public class MainActivity extends Activity {
private MainDownTimerView mMainDownTimerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initEvent();
startDownTimer();
}
private void initViews() {
mMainDownTimerView = (MainDownTimerView) findViewById(R.id.count_down_timer_view);
mMainDownTimerView.setDownTime(16000000);
}
private void initEvent() {
mMainDownTimerView.setDownTimerListener(new OnCountDownTimerListener() {
@Override
public void onFinish() {
Toast.makeText(MainActivity.this, "倒计时结束", Toast.LENGTH_SHORT)
.show();
}
});
}
private void startDownTimer() {
mMainDownTimerView.startDownTimer();
}
}
setDownTime方法传入的是总的毫秒数,最后通过startDownTimer方法开启倒计时,cancelDownTimer方法是取消倒计时。
自定义倒计时控件原理
整个控件的容器是LinearLayout,因此创建继承自LinearLayout的抽象类BaseCountDownTimerView,控件内的自控件是水平排列:
public abstract class BaseCountDownTimerView extends LinearLayout {
public BaseCountDownTimerView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
init();
}
public BaseCountDownTimerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseCountDownTimerView(Context context) {
this(context, null);
}
private void init() {
this.setOrientation(HORIZONTAL);// 设置布局排列方式
createView();// 创造三个标签
addLabelView();// 添加标签到容器中
}
标签的创建请查看《自定义瀑布流式的标签列表》这篇文章,创建完标签后,将标签添加到容器中去:
/**
* 创建时、分、秒的标签
*/
private void createView() {
mHourTextView = createLabel();
mMinTextView = createLabel();
mSecondTextView = createLabel();
}
/**
* 添加标签到容器中
*/
private void addLabelView() {
removeAllViews();
this.addView(mHourTextView);
this.addView(createColon());
this.addView(mMinTextView);
this.addView(createColon());
this.addView(mSecondTextView);
}
/**
* 创建冒号
*
* @return
*/
private TextView createColon() {
TextView textView = new TextView(mContext);
textView.setTextColor(Color.BLACK);
textView.setText(":");
return textView;
}
/**
* 创建标签
*
* @return
*/
private TextView createLabel() {
TextView textView = new GradientTextView(mContext)
.setTextColor(getTextColor()).setStrokeColor(getStrokeColor())
.setBackgroundColor(getBackgroundColor())
.setTextSize(getTextSize()).setStrokeRadius(getCornerRadius())
.build();
return textView;
}
整体样式已经创建完毕,这里的倒计时是使用CountDownTimer来实现,通过CountDownTimer构造器创建对象时,传入两个值:
public CountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; }
millisInFuture:是总的毫秒数 countDownInterval:间隔毫秒数执行onTick方法
创建CountDownTimer实例时重写以下两个方法:
@Override
public void onTick(long millisUntilFinished) {
setSecond(millisUntilFinished);
}
@Override
public void onFinish() {
OnCountDownTimerListener.onFinish();
}
每间隔countDownInterval毫秒执行onTick方法,当倒计时结束后执行onFinish方法。
时、分、秒的计算比较简单,通过除以1000得到总的秒数,将总秒数求余60得到当前的秒;将总秒除以60得到总分,总分求余60的当前的分;总分除以60得总小时,总小时求余24得当前的时,具体公式代码如下:
/**
* 设置秒
*
* @param millis
*/
private void setSecond(long millis) {
long totalSeconds = millis / 1000;
String second = (int) (totalSeconds % 60) + "";// 秒
long totalMinutes = totalSeconds / 60;
String minute = (int) (totalMinutes % 60) + "";// 分
long totalHours = totalMinutes / 60;
String hour = (int) (totalHours % 24) + "";// 时
Log.i("TAG", "hour:" + hour);
Log.i("TAG", "minute:" + minute);
Log.i("TAG", "second:" + second);
if (hour.length() == 1) {
hour = "0" + hour;
}
if (minute.length() == 1) {
minute = "0" + minute;
}
if (second.length() == 1) {
second = "0" + second;
}
mHourTextView.setText(hour);
mMinTextView.setText(minute);
mSecondTextView.setText(second);
}
以下是完整的BaseCountDownTimerView类的源码:
package com.example.countdowntimerproject.view.base;
import android.content.Context; import android.graphics.Color; import android.os.CountDownTimer; import android.util.AttributeSet; import android.util.Log; import android.widget.LinearLayout; import android.widget.TextView;
public abstract class BaseCountDownTimerView extends LinearLayout {
private Context mContext;
/**
* 倒计时控制器
*/
private CountDownTimer mCountDownTimer;
private OnCountDownTimerListener OnCountDownTimerListener;
private int mMillis;
/**
* 时
*/
private TextView mHourTextView;
/**
* 分
*/
private TextView mMinTextView;
/**
* 秒
*/
private TextView mSecondTextView;
/**
* 获取边框颜色
*
* @return
*/
protected abstract String getStrokeColor();
/**
* 设置背景色
*
* @return
*/
protected abstract String getBackgroundColor();
/**
* 获取文字颜色
*
* @return
*/
protected abstract String getTextColor();
/**
* 获取边框圆角
*
* @return
*/
protected abstract int getCornerRadius();
/**
* 获取标签文字大小
*
* @return
*/
protected abstract int getTextSize();
public BaseCountDownTimerView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
init();
}
public BaseCountDownTimerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseCountDownTimerView(Context context) {
this(context, null);
}
private void init() {
this.setOrientation(HORIZONTAL);// 设置布局排列方式
createView();// 创造三个标签
addLabelView();// 添加标签到容器中
}
/**
* 创建时、分、秒的标签
*/
private void createView() {
mHourTextView = createLabel();
mMinTextView = createLabel();
mSecondTextView = createLabel();
}
/**
* 添加标签到容器中
*/
private void addLabelView() {
removeAllViews();
this.addView(mHourTextView);
this.addView(createColon());
this.addView(mMinTextView);
this.addView(createColon());
this.addView(mSecondTextView);
}
/**
* 创建冒号
*
* @return
*/
private TextView createColon() {
TextView textView = new TextView(mContext);
textView.setTextColor(Color.BLACK);
textView.setText(":");
return textView;
}
/**
* 创建标签
*
* @return
*/
private TextView createLabel() {
TextView textView = new GradientTextView(mContext)
.setTextColor(getTextColor()).setStrokeColor(getStrokeColor())
.setBackgroundColor(getBackgroundColor())
.setTextSize(getTextSize()).setStrokeRadius(getCornerRadius())
.build();
return textView;
}
/**
* 创建倒计时
*/
private void createCountDownTimer() {
mCountDownTimer = new CountDownTimer(mMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
setSecond(millisUntilFinished);
}
@Override
public void onFinish() {
OnCountDownTimerListener.onFinish();
}
};
}
/**
* 设置秒
*
* @param millis
*/
private void setSecond(long millis) {
long totalSeconds = millis / 1000;
String second = (int) (totalSeconds % 60) + "";// 秒
long totalMinutes = totalSeconds / 60;
String minute = (int) (totalMinutes % 60) + "";// 分
long totalHours = totalMinutes / 60;
String hour = (int) (totalHours % 24) + "";// 时
Log.i("TAG", "hour:" + hour);
Log.i("TAG", "minute:" + minute);
Log.i("TAG", "second:" + second);
if (hour.length() == 1) {
hour = "0" + hour;
}
if (minute.length() == 1) {
minute = "0" + minute;
}
if (second.length() == 1) {
second = "0" + second;
}
mHourTextView.setText(hour);
mMinTextView.setText(minute);
mSecondTextView.setText(second);
}
/**
* 设置监听事件
*
* @param listener
*/
public void setDownTimerListener(OnCountDownTimerListener listener) {
this.OnCountDownTimerListener = listener;
}
/**
* 设置时间值
*
* @param millis
*/
public void setDownTime(int millis) {
this.mMillis = millis;
}
/**
* 开始倒计时
*/
public void startDownTimer() {
createCountDownTimer();// 创建倒计时
mCountDownTimer.start();
}
public void cancelDownTimer() {
mCountDownTimer.cancel();
}