今天给大家带来的是仅仅使用一个TextView实现一个高仿京东、淘宝、唯品会等各种电商APP的活动倒计时。最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习。为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了。不知道从何处开始优化。然后我就查看京东,饿了么,唯品会等各个APP的倒计时,并在开发者中打开层级界面显示,发现他们都有一个共同的特点就是一个View,没有使用多个TextView来拼接。相信大家都知道仅仅使用一个TextView比使用多个TextView拼接去实现的优势吧,下面不妨来看看几个界面就知道了。
看到这个,大家心里自然就想到了自定义View来实现吧。对,自定义View确实可以实现这样的效果。但是今天我们不采用自定义View来做。而是使用一个TextView来实现。
由于项目经理要求此次优化的代码具有可扩展性。所以此次代码的设计加了一些面向对象的知识。有一些自己的设计和架构的思路。
此次demo的设计思路:
1、编写一个倒计时的基类作为实现最普通和最基本的倒计时的功能,没有任何样式,让这个基类去继承CountDownTimer类,并且在该基类中
保存一个TextView的对象,并且把每次倒计时的数据,显示在TextView中,然后公布一个getmDateTv()方法返回一个TextView对象即可。然后只要拿到这个TextView对象显示界面的布局中即可。非常方便。
2、然后不同样式的倒计时,只需要编写不同的子类去继承最普通的倒计时基类即可,然后重写其中的设置数据和设置样式的两个方法即可,然后就能给最普通的倒计时添加不同的样式。下次如果需要扩展新的倒计时样式,不需要改变其他类的代码,只需编写一个普通倒计时的派生类重写两个方法即可,使得可扩展性更灵活。
3、然后通过一个TimerUtils管理类,去集中承担子类和父类压力,让子类和父类所需实现功能分担到TimerUtils类中,并且该TimerUtils管理类是与客户端唯一打交道的类,比如获得倒计时对象以及获得倒计时的TextView对象都通过这个管理类分配,避免客户端直接与倒计时的基类和子类打交道。从而使得类的封装性和隐藏性得到体现。
下面可以看下这个Demo设计的简单的UML类图:
通过以上思路分析下面我们就看看此次Demo的实现需要用到哪些知识点.
1、CountDownTimer类的用法。
2、SpannableString的用法。
3、MikyouCountDownTimer的封装。
4、自定义MikyouBackgroundSpan的实现。
一、通过以上的分析我们首先得复习一下有关CountDownTimer的知识,CountDownTimer是一个很简单的类我们可以看下的它的源码,它的用法自然就知道了。
CountDownTimer是一个抽象类。
-
-
-
-
-
- package android.os;
-
- public abstract class CountDownTimer {
- public CountDownTimer(long millisInFuture, long countDownInterval) {
- throw new RuntimeException("Stub!");
- }
-
- public final synchronized void cancel() {
- throw new RuntimeException("Stub!");
- }
-
- public final synchronized CountDownTimer start() {
- throw new RuntimeException("Stub!");
- }
-
- public abstract void onTick(long var1);
-
- public abstract void onFinish();
- }
可以看到倒计时的总时长就是millisFuture,和countDownInterVal间隔步长默认是1000ms,所以数据都是通过其构造器进行初始化,然后需要去重写一个回调方法onTick,
里面的一个参数就是每隔相应的步长后剩余的时间毫秒数。然后我们只需要在onTick方法中将每隔1000ms时间毫秒数进行时间格式化即可得到相应时间格式的倒计时这就是实现了最基本倒计时样式。格式化倒计时格式采用的是apache中的common的lang包中DurationFormatUtils类中的formatDuration,通过传入一个时间格式就会自动将倒计时转换成相应的mTimePattern的样式(HH:mm:ss或dd天HH时mm分ss秒).
二、复习一下有关SpannableString的用法。
在Android中EditText用于编辑文本,TextView用于显示文本,但是有时候我们需要对其中的文本进行样式等方面的设置。Android为我们提供了SpannableString类来对指定文本进行处理。
1) ForegroundColorSpan 文本颜色
private void setForegroundColorSpan() {
SpannableString spanString = new SpannableString("前景色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
2) BackgroundColorSpan 文本背景色
private void setBackgroundColorSpan() {
SpannableString spanString = new SpannableString("背景色");
BackgroundColorSpan span = new BackgroundColorSpan(Color.YELLOW);
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
3) StyleSpan 字体样式:粗体、斜体等
private void setStyleSpan() {
SpannableString spanString = new SpannableString("粗体斜体");
StyleSpan span = new StyleSpan(Typeface.BOLD_ITALIC);
spanString.setSpan(span, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
4) RelativeSizeSpan 相对大小
private void setRelativeFontSpan() {
SpannableString spanString = new SpannableString("字体相对大小");
spanString.setSpan(new RelativeSizeSpan(2.5f), 0, 6,Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
5) TypefaceSpan 文本字体
private void setTypefaceSpan() {
SpannableString spanString = new SpannableString("文本字体");
spanString.setSpan(new TypefaceSpan("monospace"), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanText);
}
6) URLSpan 文本超链接
private void addUrlSpan() {
SpannableString spanString = new SpannableString("超链接");
URLSpan span = new URLSpan("http://www.baidu.com");
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
7) ImageSpan 图片
private void addImageSpan() {
SpannableString spanString = new SpannableString(" ");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
8) ClickableSpan 文本有点击事件
private TextView textView;
textView = (TextView)this.findViewById(R.id.textView);
String text = "显示Activity";
SpannableString spannableString = new SpannableString(text);
spannableString.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Intent intent = new Intent(Main.this,OtherActivity.class);
startActivity(intent);
}
// 表示点击整个text的长度都有效触发这个事件
}, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString);
textView.setMovementMethod(LinkMovementMethod.getInstance());
9) UnderlineSpan 下划线
private void addUnderLineSpan() {
SpannableString spanString = new SpannableString("下划线");
UnderlineSpan span = new UnderlineSpan();
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
10) StrikethroughSpan
删除线
private void addStrikeSpan() {
SpannableString spanString = new SpannableString("删除线");
StrikethroughSpan span = new StrikethroughSpan();
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
11) SuggestionSpan
相当于占位符
12) MaskFilterSpan
修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
13) RasterizerSpan
光栅效果
14) AbsoluteSizeSpan
绝对大小(文本字体)
private void setAbsoluteFontSpan() {
SpannableString spannableString = new SpannableString("40号字体");
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(40);
spannableString.setSpan(absoluteSizeSpan, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.append(spannableString);
}
15) DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
16) TextAppearanceSpan
文本外貌(包括字体、大小、样式和颜色)
private void setTextAppearanceSpan() {
SpannableString spanString = new SpannableString("文本外貌");
TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(this, android.R.style.TextAppearance_Medium);
spanString.setSpan(textAppearanceSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
好了,通过以上的复习知识点,现在我们就可以来真正开始demo的实现,然后我们一起来一步一步封装我们的倒计时。
一、编写一个MikyouCountDownTimer基类,让它去继承CountDownTimer类,并且公布出initSpanData和setBackgroundSpan方法用于其他样式倒计时的子类使用,它可以实现最基本倒计时的功能。
- package com.mikyou.countdowntimer.bean;
- import android.content.Context;
- import android.os.CountDownTimer;
- import android.text.style.ForegroundColorSpan;
- import android.widget.TextView;
- import com.mikyou.countdowntimer.myview.MikyouBackgroundSpan;
- import com.mikyou.countdowntimer.utils.TimerUtils;
- import org.apache.commons.lang.time.DurationFormatUtils;
- import java.util.ArrayList;
- import java.util.List;
-
-
-
- public class MikyouCountDownTimer extends CountDownTimer{
- private Context mContext;
- protected TextView mDateTv;
- private long mGapTime;
- private long mCount = 1000;
- private String mTimePattern = "HH:mm:ss";
- private String mTimeStr;
- protected List<MikyouBackgroundSpan> mBackSpanList;
- protected List<ForegroundColorSpan> mTextColorSpanList;
- private int mDrawableId;
- private boolean flag = false;
-
- protected String[] numbers;
- protected char[] nonNumbers;
-
- private int mSpanPaddingLeft,mSpanPaddingRight,mSpanPaddingTop,mSpanPaddingBottom;
- private int mSpanTextSize;
- private int mSpanTextColor;
- protected int mGapSpanColor;
- public MikyouCountDownTimer(Context mContext, long mGapTime, String mTimePattern,int mDrawableId) {
- this(mContext,mGapTime,1000,mTimePattern,mDrawableId);
- }
- public MikyouCountDownTimer(Context mContext, long mGapTime, int mCount, String mTimePattern,int mDrawableId) {
- super(mGapTime,mCount);
- this.mContext = mContext;
- this.mGapTime = mGapTime;
- this.mCount = mCount;
- this.mDrawableId= mDrawableId;
- this.mTimePattern = mTimePattern;
- mBackSpanList = new ArrayList<>();
- mTextColorSpanList = new ArrayList<>();
- mDateTv = new TextView(mContext,null);
- }
-
- public MikyouCountDownTimer setTimerTextSize(int textSize){
- this.mSpanTextSize = textSize;
- return this;
- }
- public MikyouCountDownTimer setTimerPadding(int left,int top,int right,int bottom){
- this.mSpanPaddingLeft = left;
- this.mSpanPaddingBottom = bottom;
- this.mSpanPaddingRight = right;
- this.mSpanPaddingTop = top;
- return this;
- }
- public MikyouCountDownTimer setTimerTextColor(int color){
- this.mSpanTextColor = color;
- return this;
- }
- public MikyouCountDownTimer setTimerGapColor(int color){
- this.mGapSpanColor = color;
- return this;
- }
-
- public void setBackgroundSpan(String timeStr) {
- if (!flag){
- initSpanData(timeStr);
- flag = true;
- }
- mDateTv.setText(timeStr);
- }
-
- public void initSpanData(String timeStr) {
- numbers = TimerUtils.getNumInTimerStr(timeStr);
- nonNumbers = TimerUtils.getNonNumInTimerStr(timeStr);
- }
-
- protected void initBackSpanStyle(MikyouBackgroundSpan mBackSpan) {
- mBackSpan.setTimerPadding(mSpanPaddingLeft,mSpanPaddingTop,mSpanPaddingRight,mSpanPaddingBottom);
- mBackSpan.setTimerTextColor(mSpanTextColor);
- mBackSpan.setTimerTextSize(mSpanTextSize);
- }
-
- @Override
- public void onTick(long l) {
- if (l > 0) {
- mTimeStr = DurationFormatUtils.formatDuration(l, mTimePattern);
-
-
- setBackgroundSpan(mTimeStr);
- }
- }
-
- @Override
- public void onFinish() {
- mDateTv.setText("倒计时结束");
- }
-
- public TextView getmDateTv() {
- startTimer();
- return mDateTv;
- }
- public void cancelTimer(){
- this.cancel();
- }
- public void startTimer(){
- this.start();
- }
-
- public String getmTimeStr() {
- return mTimeStr;
- }
- }
TimerUtils类用于保存不同倒计时的格式,例如HH:mm:ss、HH时mm分ss秒、dd天HH时mm分ss秒等。现在我们可以来看下简单的基本样式。
二、自定义MikyouBackgroundSpan去继承ImageSpan,这个类非常重要是用于给倒计时的TextView加样式,为什么可以使用一个TextView来实现呢
别忘了还有个很强悍的类就是SpannableString类,这个类就是可以设置一段字符串中的每个字符的样式,很多样式。最后通过TextView中有个setSpan方法即可传入
一个SpannableString对象完成设置。但是为什么需要自定义一个Span呢?这是因为很奇怪为什么android中的那么多Span样式中没有一个可以直接设置一个drawable对象文件呢,所以上网找了很多都没有找到,最后在stackOverFlow上找到了一个外国人给了一个解决办法,就是重写ImageSpan最后就可以实现了设置drawable文件即可
- package com.mikyou.countdowntimer.myview;
-
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.graphics.drawable.Drawable;
- import android.text.style.ImageSpan;
-
-
-
-
- public class MikyouBackgroundSpan extends ImageSpan {
- private Rect mTextBound;
- private int maxHeight = 0;
- private int maxWidth = 0;
- private int mPaddingLeft = 20;
- private int mPaddingRight = 20;
- private int mPaddingTop = 20;
- private int mPaddingBottom = 20;
- private int mTextColor = Color.GREEN;
- private int mTextSize = 50;
- public MikyouBackgroundSpan(Drawable d, int verticalAlignment) {
- super(d, verticalAlignment);
- mTextBound = new Rect();
- }
-
- public MikyouBackgroundSpan setTimerTextColor(int mTextColor) {
- this.mTextColor = mTextColor;
- return this;
- }
- public MikyouBackgroundSpan setTimerTextSize(int textSize){
- this.mTextSize = textSize;
- return this;
- }
- public MikyouBackgroundSpan setTimerPadding(int left,int top,int right,int bottom){
- this.mPaddingLeft = left;
- this.mPaddingRight = right;
- this.mPaddingBottom = bottom;
- this.mPaddingTop = top;
- return this;
- }
- @Override
- public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
-
- paint.setTextSize(mTextSize);
-
- paint.getTextBounds(text.toString(), start, end, mTextBound);
-
- maxWidth = maxWidth < mTextBound.width() ? mTextBound.width() : maxWidth;
- maxHeight = maxHeight < mTextBound.height() ? mTextBound.height() : maxHeight;
-
-
- getDrawable().setBounds(0,0, maxWidth+mPaddingLeft+mPaddingRight,mPaddingTop+mPaddingBottom+maxHeight);
-
- super.draw(canvas, text, start, end, x, top, y, bottom, paint);
-
- paint.setColor(mTextColor);
-
- paint.setTextSize(mTextSize);
- int mGapX = (getDrawable().getBounds().width() - maxWidth)/2;
- int mGapY= (getDrawable().getBounds().height() - maxHeight)/2;
-
- canvas.drawText(text.subSequence(start, end).toString(), x + mGapX , y - mGapY + maxHeight/3, paint); }
- }
三、样式一的倒计时实现,样式一指的是例如:12时36分27秒或者12:36:27就是将数值和时、分、秒或者":"分隔开,然后去自定义每块数值(12 36 27)和间隔(时 分 秒 或 :)的样式,包括给数值块加背景和边框。在MikyouCountDownTimer中的number数组中保存着[12 36 27]而nonumer数组中保存着[时 分 秒 ]或[ : :]d的间隔字符。
- package com.mikyou.countdowntimer.bean;
-
- import android.content.Context;
- import android.text.SpannableString;
- import android.text.method.LinkMovementMethod;
- import android.text.style.ForegroundColorSpan;
- import android.text.style.ImageSpan;
-
- import com.mikyou.countdowntimer.myview.MikyouBackgroundSpan;
- import com.mikyou.countdowntimer.utils.TimerUtils;
-
-
-
-
- public class JDCountDownTimer extends MikyouCountDownTimer {
- private SpannableString mSpan;
- private Context mContext;
- private int mDrawableId;
- public JDCountDownTimer(Context mContext, long mGapTime, String mTimePattern,int mDrawableId) {
- super(mContext, mGapTime, mTimePattern,mDrawableId);
- this.mContext = mContext;
- this.mDrawableId = mDrawableId;
- }
-
-
-
-
-
-
-
-
-
- @Override
- public void initSpanData(String timeStr) {
- super.initSpanData(timeStr);
- for (int i = 0; i<numbers.length;i++){
- MikyouBackgroundSpan mBackSpan = new MikyouBackgroundSpan(mContext.getDrawable(mDrawableId), ImageSpan.ALIGN_BOTTOM);
- initBackSpanStyle(mBackSpan);
- mBackSpanList.add(mBackSpan);
- }
- for (int i= 0; i<nonNumbers.length;i++){
- ForegroundColorSpan mGapSpan = new ForegroundColorSpan(mGapSpanColor);
- mTextColorSpanList.add(mGapSpan);
- }
- }
-
-
-
-
-
-
-
-
-
-
- @Override
- public void setBackgroundSpan(String timeStr) {
- super.setBackgroundSpan(timeStr);
- int mGapLen = 1;
- mSpan = new SpannableString(timeStr);
- for (int i = 0;i<mBackSpanList.size();i++){
- int start = i*numbers[i].length() + i*mGapLen;
- int end = start + numbers[i].length();
- TimerUtils.setContentSpan(mSpan,mBackSpanList.get(i),start,end);
-
- if (i < mTextColorSpanList.size()){
- TimerUtils.setContentSpan(mSpan,mTextColorSpanList.get(i),end,end + mGapLen);
- }
- }
- mDateTv.setMovementMethod(LinkMovementMethod.getInstance());
- mDateTv.setText(mSpan);
- }
-
- }
四、样式二的倒计时实现,样式二不同于样式一的是例如:12时36分27秒或者12:36:27就是将每个数值和时、分、秒或者":"分隔开,然后去自定义每块数值(1 2 3 6 2 7)和间隔(时 分 秒 或 :)的样式,包括给数值块加背景和边框。在MikyouCountDownTimer中的vipNumber数组中保存着[1 2 3 6 2 7]而vipnonNumer数组中保存着[时 分 秒 ]或[ : :]d的间隔字符。
- package com.mikyou.countdowntimer.bean;
-
- import android.content.Context;
- import android.text.SpannableString;
- import android.text.method.LinkMovementMethod;
- import android.text.style.ForegroundColorSpan;
- import android.text.style.ImageSpan;
-
- import com.mikyou.countdowntimer.myview.MikyouBackgroundSpan;
- import com.mikyou.countdowntimer.utils.TimerUtils;
-
- import java.util.ArrayList;
- import java.util.List;
-
-
-
-
- public class VIPCountDownTimer extends MikyouCountDownTimer {
- private SpannableString mSpan;
- private Context mContext;
- private int mDrawableId;
- private List<MikyouBackgroundSpan> mSpanList;
- private String[] vipNumbers;
- private char[] vipNonNumbers;
- public VIPCountDownTimer(Context mContext, long mGapTime, String mTimePattern,int mDrawableId) {
- super(mContext, mGapTime, mTimePattern,mDrawableId);
- this.mContext = mContext;
- this.mDrawableId = mDrawableId;
- mSpanList = new ArrayList<>();
- }
-
-
-
-
-
-
-
-
-
- @Override
- public void setBackgroundSpan(String timeStr) {
- int mGapLen = 1;
- mSpan = new SpannableString(timeStr);
- initSpanData(timeStr);
- int start = 0 ;
- int count =0;
- for (int i=0;i<vipNumbers.length;i++){
-
- for (int j=start;j<start + vipNumbers[i].toCharArray().length;j++,count++){
- TimerUtils.setContentSpan(mSpan,mSpanList.get(count),j,j+mGapLen);
- }
-
- start = start + vipNumbers[i].toCharArray().length;
- if (i < nonNumbers.length){
- TimerUtils.setContentSpan(mSpan,mTextColorSpanList.get(i),start,start+mGapLen);
- start = start +mGapLen;
- }
-
- }
- mDateTv.setMovementMethod(LinkMovementMethod.getInstance());
- mDateTv.setText(mSpan);
- }
-
-
-
-
-
-
-
-
-
- @Override
- public void initSpanData(String timeStr) {
- super.initSpanData(timeStr);
- vipNumbers = TimerUtils.getNumInTimerStr(timeStr);
- vipNonNumbers = TimerUtils.getNonNumInTimerStr(timeStr);
- for (int i=0;i<vipNumbers.length;i++){
- for (int j=0;j<vipNumbers[i].toCharArray().length;j++){
- MikyouBackgroundSpan mSpan = new MikyouBackgroundSpan(mContext.getDrawable(mDrawableId), ImageSpan.ALIGN_BOTTOM);
- initBackSpanStyle(mSpan);
- mSpanList.add(mSpan);
- }
- }
- for (int i= 0; i<vipNonNumbers.length;i++){
- ForegroundColorSpan mGapSpan = new ForegroundColorSpan(mGapSpanColor);
- mTextColorSpanList.add(mGapSpan);
- }
- }
- }
四、TimerUtils管理类,主要是提供不同样式的倒计时的对象给客户端,所以这个类直接与客户端建立关系,从而实现倒计时子类和基类对外界的隐藏体现了封装性。
- package com.mikyou.countdowntimer.utils;
-
- import android.content.Context;
- import android.graphics.Color;
- import android.text.SpannableString;
- import android.text.Spanned;
- import android.text.style.ForegroundColorSpan;
-
- import com.mikyou.countdowntimer.bean.JDCountDownTimer;
- import com.mikyou.countdowntimer.bean.MikyouCountDownTimer;
- import com.mikyou.countdowntimer.bean.VIPCountDownTimer;
-
-
-
-
- public class TimerUtils {
- public static final int JD_STYLE = 0;
- public static final int VIP_STYLE = 1;
- public static final int DEFAULT_STYLE = 3;
-
- public static final String TIME_STYLE_ONE = "HH:mm:ss";
- public static final String TIME_STYLE_TWO = "HH时mm分ss秒";
- public static final String TIME_STYLE_THREE = "dd天HH时mm分ss秒";
- public static final String TIME_STYLE_FOUR = "dd天HH时mm分";
-
- public static MikyouCountDownTimer getTimer(int style,Context mContext, long mGapTime, String mTimePattern, int mDrawableId){
- MikyouCountDownTimer mCountDownTimer = null;
- switch (style){
- case JD_STYLE:
- mCountDownTimer = new JDCountDownTimer(mContext,mGapTime,mTimePattern,mDrawableId);
- break;
- case VIP_STYLE:
- mCountDownTimer = new VIPCountDownTimer(mContext,mGapTime,mTimePattern,mDrawableId);
- break;
- case DEFAULT_STYLE:
- mCountDownTimer = new MikyouCountDownTimer(mContext,mGapTime,mTimePattern,mDrawableId);
- break;
- }
- return mCountDownTimer;
- }
-
- public static String[] getNumInTimerStr(String mTimerStr){
- return mTimerStr.split("[^\\d]");
- }
-
- public static char[] getNonNumInTimerStr(String mTimerStr){
- return mTimerStr.replaceAll("\\d","").toCharArray();
- }
-
- public static ForegroundColorSpan getTextColorSpan(String color){
- ForegroundColorSpan mSpan = null;
- if (mSpan == null){
- mSpan = new ForegroundColorSpan(Color.parseColor(color));
- }
- return mSpan;
- }
-
- public static void setContentSpan(SpannableString mSpan, Object span, int start,
- int end) {
- mSpan.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- }
现在我们就来测试下我们使用一个TextView实现的倒计时。
使用该倒计时非常简单非常方便只需要一行代码就能实现一个高仿京东和各种电商的APP的倒计时样式。
- package com.mikyou.countdowntimer;
-
- import android.graphics.Color;
- import android.os.Bundle;
- import android.support.v7.app.AppCompatActivity;
- import android.view.Gravity;
- import android.widget.LinearLayout;
- import android.widget.TextView;
-
- import com.mikyou.countdowntimer.utils.TimerUtils;
-
- public class MainActivity extends AppCompatActivity {
- private LinearLayout parent;
- private int padding =10;
- private int textSize = 40;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- parent = (LinearLayout) findViewById(R.id.parent);
-
-
-
-
- TextView tv = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_ONE,0)
- .getmDateTv();
- parent.addView(tv);
- setmLayoutParams(tv);
-
-
-
- TextView tv1 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_TWO,0)
- .getmDateTv();
- parent.addView(tv1);
- setmLayoutParams(tv1);
-
-
-
- TextView tv2 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_THREE,0)
- .getmDateTv();
- parent.addView(tv2);
- setmLayoutParams(tv2);
-
-
-
- TextView tv3 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_FOUR,0)
- .getmDateTv();
- parent.addView(tv3);
- setmLayoutParams(tv3);
-
-
-
-
- TextView tv4= TimerUtils.getTimer(TimerUtils.JD_STYLE,this,120000000,TimerUtils.TIME_STYLE_ONE,R.drawable.timer_shape)
- .setTimerPadding(10,10,10,10)
- .setTimerTextColor(Color.BLACK)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv4);
- setmLayoutParams(tv4);
-
-
-
- TextView tv5= TimerUtils.getTimer(TimerUtils.JD_STYLE,this,120000000,TimerUtils.TIME_STYLE_TWO,R.drawable.timer_shape2)
- .setTimerPadding(10,10,10,10)
- .setTimerTextColor(Color.WHITE)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv5);
- setmLayoutParams(tv5);
-
-
-
- TextView tv6= TimerUtils.getTimer(TimerUtils.JD_STYLE,this,120000000,TimerUtils.TIME_STYLE_THREE,R.drawable.timer_shape2)
- .setTimerPadding(10,10,10,10)
- .setTimerTextColor(Color.YELLOW)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv6);
- setmLayoutParams(tv6);
-
-
-
- TextView tv7= TimerUtils.getTimer(TimerUtils.JD_STYLE,this,120000000,TimerUtils.TIME_STYLE_FOUR,R.drawable.timer_shape2)
- .setTimerPadding(15,15,15,15)
- .setTimerTextColor(Color.BLUE)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv7);
- setmLayoutParams(tv7);
-
-
-
-
-
-
- TextView tv8= TimerUtils.getTimer(TimerUtils.VIP_STYLE,this,120000000,TimerUtils.TIME_STYLE_ONE,R.drawable.timer_shape)
- .setTimerPadding(15,15,15,15)
- .setTimerTextColor(Color.BLACK)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv8);
- setmLayoutParams(tv8);
-
-
-
-
- TextView tv9= TimerUtils.getTimer(TimerUtils.VIP_STYLE,this,120000000,TimerUtils.TIME_STYLE_TWO,R.drawable.timer_shape2)
- .setTimerPadding(15,15,15,15)
- .setTimerTextColor(Color.WHITE)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv9);
- setmLayoutParams(tv9);
-
-
-
- TextView tv10= TimerUtils.getTimer(TimerUtils.VIP_STYLE,this,120000000,TimerUtils.TIME_STYLE_THREE,R.drawable.timer_shape2)
- .setTimerPadding(15,15,15,15)
- .setTimerTextColor(Color.YELLOW)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv10);
- setmLayoutParams(tv10);
-
-
-
- TextView tv11= TimerUtils.getTimer(TimerUtils.VIP_STYLE,this,120000000,TimerUtils.TIME_STYLE_FOUR,R.drawable.timer_shape2)
- .setTimerPadding(15,15,15,15)
- .setTimerTextColor(Color.BLUE)
- .setTimerTextSize(40)
- .setTimerGapColor(Color.BLACK)
- .getmDateTv();
- parent.addView(tv11);
- setmLayoutParams(tv11);
- }
-
- private void setmLayoutParams(TextView tv) {
- tv.setGravity(Gravity.CENTER_HORIZONTAL);
- LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
- params.setMargins(20,20,20,20);
- tv.setLayoutParams(params);
- }
- }
两个drawable文件:
带边框样式
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- >
- <corners android:radius="5px"/>
- <stroke android:color="#88000000" android:width="1dp"/>
- </shape>
带背景和边框样式
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- >
- <corners android:radius="10px"/>
- <solid android:color="#000000"/>
- </shape>
现在就看看我们运行的成果吧。
看看运行结果还不错吧,其实它的样式还可以定义很多种主要看自己的创意和想法了,这个倒计时封装如果还有什么不足之处,请多多提出建议。但是现在使用还是蛮方便和简单的,一行代码就能就能解决。这个倒计时用到的地方还是蛮多的,大家有需要的话可以直接引入到自己的项目中。
PS:有人反应说Demo放入工程跑起来有问题,但是我自己是没问题的,然后我索性将这个打成了一个aar包,只需要将这个aar包放入工程中,即可在Activity中如博客上所写一样通过一行代码即可实现倒计时。注意:aar包只适用于AndroidStudio
引入说明:
新建一个Module,将aar包放入libs目录,然后在build.gradle中添加:
repositories {
flatDir {
dirs 'libs'
}
}
repositories放入android{}内部
compile(name:'mikyoutimerlib',ext:'aar')
compile放入dependencies {}内部,name-->aar包名
aar包下载
DEMO下载