Android 에 서 는 TextView 를 사용 하여 경 동 타 오 바 오의 각종 카운트다운 효 과 를 높 게 모방 합 니 다.
이 를 보고 자 연 스 럽 게 사용자 정의 뷰 가 떠 올 랐 다.네,사용자 정의 View 는 이러한 효 과 를 실현 할 수 있 습 니 다.하지만 오늘 은 사용자 정의 뷰 로 하지 않 습 니 다.하나의 TextView 로 이 루어 집 니 다.
프로젝트 매니저 가 이번 최적화 코드 에 확장 성 을 요구 하기 때문이다.그래서 이번 코드 의 디자인 은 대상 을 대상 으로 하 는 지식 을 더 했다.자신의 디자인 과 구조 에 대한 사고 가 있다.
이번 demo 의 디자인 방향:
1.카운트다운 의 기본 클래스 를 작성 하여 가장 일반적 이 고 기본 적 인 카운트다운 을 실현 하 는 기능 으로 스타일 이 없습니다.이 기본 클래스 가 Countdown Timer 클래스 를 계승 하고 이 기본 클래스 에서
TextView 의 대상 을 저장 하고 카운트다운 할 때마다 데 이 터 를 TextView 에 표시 한 다음 getmDateTv()방법 을 발표 하여 TextView 대상 을 되 돌려 주면 됩 니 다.그리고 이 TextView 대상 을 가 져 와 인터페이스의 레이아웃 을 표시 하면 됩 니 다.매우 편리 하 다.
2.그리고 서로 다른 스타일 의 카운트다운 은 서로 다른 하위 클래스 를 만들어 서 가장 일반적인 카운트다운 기 류 를 계승 하면 됩 니 다.그리고 그 중의 설정 데이터 와 스타일 을 설정 하 는 두 가지 방법 을 다시 쓰 면 됩 니 다.그리고 가장 일반적인 카운트다운 에 서로 다른 스타일 을 추가 할 수 있 습 니 다.다음 에 새로운 카운트다운 스타일 을 확장 하려 면 다른 종류의 코드 를 바 꿀 필요 가 없습니다.일반적인 카운트다운 파생 클래스 를 만들어 서 두 가지 방법 을 다시 쓰 면 확장 성 이 더욱 유연 해 집 니 다.
3.그 다음 에 하나의 TimerUtils 관리 류 를 통 해 부담 류 와 아버지 류 의 압력 을 집중 적 으로 받 고 서브 류 와 아버지 류 가 필요 로 하 는 기능 을 TimerUtils 류 에 분담 하도록 한다.또한 이 TimerUtils 관리 류 는 클 라 이언 트 와 유일 하 게 접촉 하 는 유형 이다.예 를 들 어 카운트다운 대상 을 얻 고 카운트다운 을 받 는 TextView 대상 은 모두 이런 관리 류 를 통 해 분배 된다.클 라 이언 트 가 카운트다운 의 기본 클래스 와 하위 클래스 와 직접 접촉 하 는 것 을 피한다.그래서 류 의 포장 성과 숨겨 진 성 을 나타 낸다.
다음은 이 데모 가 디자인 한 간단 한 UML 클래스 를 볼 수 있 습 니 다.
이상 의 사고방식 분석 을 통 해 이번 데모 의 실현 에 어떤 지식 이 필요 한 지 살 펴 보 겠 습 니 다.
1.Countdown Timer 류 의 용법.
2.SpannableString 의 용법.
3.MikyuCountdown Timer 의 패키지.
4.사용자 정의 MikyuBackgroundSpan 의 실현.
1.상기 분석 을 통 해 우 리 는 먼저 Countdown Timer 에 관 한 지식 을 복습 해 야 한다.Countdown Timer 는 우리 가 볼 수 있 는 간단 한 유형 으로 그 소스 코드 의 용법 을 자 연 스 럽 게 알 수 있다.
Countdown Timer 는 추상 적 인 유형 이다.
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
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 과 의 간격 은 기본적으로 1000 ms 이기 때문에 데 이 터 는 구조 기 를 통 해 초기 화 된 다음 에 리 셋 방법 인 onTick 을 다시 써 야 합 니 다.그 중의 한 매개 변 수 는 해당 하 는 걸음 마다 남 은 시간 밀리초 입 니 다.그리고 우 리 는 onTick 방법 에서 1000 ms 시간 밀리초 간격 으로 시간 을 포맷 하면 해당 시간 형식의 카운트다운 을 얻 을 수 있 습 니 다.이것 이 바로 가장 기본 적 인 카운트다운 스타일 입 니 다.포맷 초읽기 형식 은 apache 의 common lang 패키지 의 Duration Format Utils 클래스 의 format Duration 을 사용 합 니 다.시간 형식 을 입력 하면 자동 으로 초읽기 를 해당 하 는 mTimePattern 스타일 로 변환 합 니 다(HH:mm:ss 또는 dd 일 HH 시 mm 분 ss 초).2.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)배경 ColorSpan 텍스트 배경 색
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)스타일 스 판 글꼴 스타일:굵 은 몸,기울 임 꼴 등
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)상대 크기
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)Clickable Span 텍스트 에 클릭 이벤트 가 있 음
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)언 더 라인 스 판 밑줄
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);
}
자,이상 의 복습 지식 포 인 트 를 통 해 이제 우 리 는 데모 의 실현 을 진정 으로 시작 할 수 있 습 니 다.그리고 우 리 는 한 걸음 한 걸음 우리 의 카운트다운 을 포장 할 수 있 습 니 다.1.MikyuCountdown Timer 기본 클래스 를 작성 하여 Countdown Timer 클래스 를 계승 하고 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;
/**
* Created by mikyou on 16-10-22.
*/
public class MikyouCountDownTimer extends CountDownTimer{
private Context mContext;//
protected TextView mDateTv;// TextView
private long mGapTime;//
private long mCount = 1000;// 1000 1s
private String mTimePattern = "HH:mm:ss";//timePattern : HH:mm:ss HH mm ss dd HH mm ss
private String mTimeStr;
protected List<MikyouBackgroundSpan> mBackSpanList;
protected List<ForegroundColorSpan> mTextColorSpanList;
private int mDrawableId;
private boolean flag = false;// flag, Span
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;// , 1000
this.mDrawableId= mDrawableId;// drawable id
this.mTimePattern = mTimePattern;// : HH:mm:ss dd HH mm ss
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;
}
// Span ,
public void setBackgroundSpan(String timeStr) {
if (!flag){
initSpanData(timeStr);
flag = true;
}
mDateTv.setText(timeStr);
}
// Span ,
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);
// apache common lang DurationFormatUtils formatDuration,
// mTimePattern (HH:mm:ss dd HH mm ss )
setBackgroundSpan(mTimeStr);
}
}
@Override
public void onFinish() {
mDateTv.setText(" ");
}
// TextView
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 초 등 입 니 다.이제 간단 한 기본 스타일 을 살 펴 볼 수 있 습 니 다.2.MikyuBackgroundSpan 을 사용자 정의 하여 ImageSpan 을 계승 합 니 다.이 종 류 는 카운트다운 하 는 TextView 에 스타일 을 추가 하 는 것 이 매우 중요 합 니 다.왜 TextView 를 사용 하여 이 루어 질 수 있 습 니까?
또 하나의 강력 한 종 류 는 바로 SpannableString 류 라 는 것 을 잊 지 마 세 요.이 종 류 는 문자열 의 모든 문 자 를 설정 할 수 있 는 스타일 이 고 여러 가지 스타일 입 니 다.마지막 으로 TextView 에 setSpan 방법 이 있 으 면 들 어 갈 수 있 습 니 다.
SpannableString 대상 이 설정 을 마 쳤 습 니 다.그런데 왜 스 판 을 사용자 정의 해 야 합 니까?이것 은 왜 안 드 로 이 드 의 그렇게 많은 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;
/**
* Created by mikyou on 16-10-22.
*/
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);
// , mTextBound
paint.getTextBounds(text.toString(), start, end, mTextBound);
// , left,top,right,bottom
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); }
}
3.스타일 1 의 카운트다운 이 이 루어 집 니 다.스타일 은 예 를 들 어 12 시 36 분 27 초 또는 12 시 36 분 27 초 또는 12 시 36 분 27 초 는 수치 와 시,분,초 또는':'를 분리 한 다음 에 각 수치(12 36 27)와 간격(시 분 초 또는:)을 사용자 정의 하 는 스타일 입 니 다.이 는 수치 블록 에 배경 과 테 두 리 를 추가 하 는 것 을 포함 합 니 다.MikyuCountdown Timer 의 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;
/**
* Created by mikyou on 16-10-22.
*/
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;
}
/**
* initSpanData
* number MikyouBackgroundSpan
* MikyouBackgroundSpan , , ,
* nonNumber ForegroundColorSpan
* , ForegroundColorSpan
* ,setmGapSpanColor
* Span, 。
* */
@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);
}
}
/** setBackgroundSpan
* Span start,end
* start end
* mGapLen = 1, ,
* :12 36 27 " "," "," "
* Span , Span,
* Span start :start = i*numbers[i].length() + i*mGapLen;
* end = start + numbers[i].length();
* */
@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()){// 12:36:27 , 2 ,
TimerUtils.setContentSpan(mSpan,mTextColorSpanList.get(i),end,end + mGapLen);
}
}
mDateTv.setMovementMethod(LinkMovementMethod.getInstance());// ,
mDateTv.setText(mSpan);
}
}
4.스타일 2 의 카운트다운 이 이 루어 집 니 다.스타일 2 는 스타일 1 과 다 릅 니 다.예 를 들 어 12 시 36 분 27 초 또는 12:36:27 은 모든 수치 와 시,분,초 또는":"분리 한 다음 에 각 수치(1,2,3,6,27)와 간격(시 분 초 또는:)을 사용자 정의 하 는 스타일 입 니 다.이 는 수치 블록 에 배경 과 테 두 리 를 추가 하 는 것 을 포함 합 니 다.MikyuCountdown Timer 의 vipNumber 배열 에는[1,2,3,6,27]이 저장 되 어 있 고,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;
/**
* Created by mikyou on 16-10-22.
*/
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<>();
}
/** setBackgroundSpan
* Span start,end
* start end ,
* mGapLen = 1, ,
* :12 36 27 " "," "," "
* Span , Span,
* Span start :start = i*numbers[i].length() + i*mGapLen;
* end = start + numbers[i].length();
* */
@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 = start + vipNumbers[i].toCharArray().length;
if (i < nonNumbers.length){
TimerUtils.setContentSpan(mSpan,mTextColorSpanList.get(i),start,start+mGapLen);
start = start +mGapLen;// start
}
}
mDateTv.setMovementMethod(LinkMovementMethod.getInstance());
mDateTv.setText(mSpan);
}
/**
* initSpanData
* number MikyouBackgroundSpan
* MikyouBackgroundSpan , , ,
* nonNumber ForegroundColorSpan
* , ForegroundColorSpan
* ,setmGapSpanColor
* Span, 。
* */
@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);
}
}
}
4.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;
/**
* Created by mikyou on 16-10-22.
*/
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;
}
// Span
public static void setContentSpan(SpannableString mSpan, Object span, int start,
int end) {
mSpan.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
이제 TextView 로 이 루어 진 카운트다운 을 테스트 해 보 겠 습 니 다.이 카운트다운 을 사용 하 는 것 은 매우 간단 하고 매우 편리 하 며 코드 한 줄 만 있 으 면 경 동과 각종 전자상거래 의 앱 을 모방 하 는 카운트다운 스타일 을 실현 할 수 있다.
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);
//
/**
* + 1:DEFAULT_STYLE <--> TIME_STYLE_ONE = "HH:mm:ss"
* */
TextView tv = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_ONE,0)
.getmDateTv();
parent.addView(tv);
setmLayoutParams(tv);
/**
* + 2:DEFAULT_STYLE <--> TIME_STYLE_TWO = "HH mm ss "
* */
TextView tv1 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_TWO,0)
.getmDateTv();
parent.addView(tv1);
setmLayoutParams(tv1);
/**
* + 3:DEFAULT_STYLE <--> TIME_STYLE_THREE = "dd HH mm ss "
* */
TextView tv2 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_THREE,0)
.getmDateTv();
parent.addView(tv2);
setmLayoutParams(tv2);
/**
* + 4:DEFAULT_STYLE <--> TIME_STYLE_FOUR = "dd HH mm "
* */
TextView tv3 = TimerUtils.getTimer(TimerUtils.DEFAULT_STYLE,this,120000000,TimerUtils.TIME_STYLE_FOUR,0)
.getmDateTv();
parent.addView(tv3);
setmLayoutParams(tv3);
// , ,
/**
* + 1:JD_STYLE <--> TIME_STYLE_ONE = "HH:mm:ss"
* */
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();// TextView
parent.addView(tv4);
setmLayoutParams(tv4);
/**
* + 2:JD_STYLE <--> TIME_STYLE_TWO = "HH mm ss "
* */
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);
/**
* + 3:JD_STYLE <-->TIME_STYLE_THREE = "dd HH mm ss "
* */
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);
/**
* + 4:JD_STYLE <-->TIME_STYLE_FOUR = "dd HH mm "
* */
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);
/**
* + 1:VIP_STYLE <-->TIME_STYLE_ONE = "HH:mm:ss"
* */
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);
/**
* + 2:VIP_STYLE <-->TIME_STYLE_TWO = "HH mm ss "
* */
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);
/**
* + 3:VIP_STYLE <-->TIME_STYLE_THREE = "dd HH mm ss "
* */
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);
/**
* + 4:VIP_STYLE <-->TIME_STYLE_FOUR = "dd HH mm "
* */
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>
이제 우리 운행 의 성 과 를 보 자.운행 결 과 를 보면 괜 찮 은 것 같 습 니 다.사실 스타일 은 자신의 창의 와 아 이 디 어 를 많이 볼 수 있 습 니 다.이 카운트다운 패 키 징 이 부족 한 점 이 있다 면 많은 조언 을 해 주 십시오.하지만 지금 은 사용 이 편리 하고 간단 해서 코드 한 줄 로 해결 할 수 있 습 니 다.이 카운트다운 에 사용 되 는 곳 은 꽤 많 습 니 다.여러분 이 필요 하 다 면 자신의 프로젝트 에 직접 도입 할 수 있 습 니 다.
데모 다운로드
위 에서 말 한 것 은 편집장 님 께 서 소개 해 주신 안 드 로 이 드 에서 TextView 를 사용 하여 고 모 경 동 타 오 바 오의 각종 카운트다운 효 과 를 실현 하 는 것 입 니 다.여러분 께 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주세요.편집장 님 께 서 제때에 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.