CountDownTimerProject
仿京东首页倒计时控件
Install / Use
/learn @LinhaiGu/CountDownTimerProjectREADME
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())
Related Skills
node-connect
347.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
347.2kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
