IT技術互動交流平台(tai)

lol外围官网

來(lai)源︰IT165收(shou)集  發布日期︰2020-02-24 13:02:40

 在上篇文章《Android Span 架構介紹》,我們講述了Android Span的基本概念和用法,這篇文章我們就來(lai)擴展一下我們對(dui)Android Span的了解,這一定會使你感到驚奇的,驚嘆Android Span竟然還能完(wan)成這些的效果(guo),讓你在Android自定義(yi)View和動畫方面(mian)有(you)更加深刻的理解,可能會幫助你你想出更加簡潔的實現方式。
 本篇文章主要講述一下兩(liang)個方面(mian)的內容:

自定義(yi)Android Span 使用Android Span實現動畫

 先貼(tie)一下本篇文章實現的自定義(yi)Span和動畫的效果(guo)圖
demo

demo

自定義(yi)Span

 我們都知(zhi)道,自定義(yi)View有(you)兩(liang)種方式,一種是繼承(cheng)特定的視圖類,比(bi)如你希望修改TextView的行(xing)為,所(suo)以繼承(cheng)了TextView;另一種就是直接繼承(cheng)View或(huo)者ViewGroup,這樣可以實現全新的視圖和行(xing)為。如同自定義(yi)View一樣,你有(you)兩(liang)種自定義(yi)Span的方法,一種直接繼承(cheng)特定類型的Span類,比(bi)如ForegroundColorSpan等,這樣你可以在這些類的基礎上進行(xing)修改;另一種就是繼承(cheng)ReplaceSpan這樣的抽象類或(huo)者實現LetterLineBackgroundSpan這樣的接口(kou),你只要實現它(ta)給出的接口(kou),就可以實現zhong)碌男?guo)。
 我們先來(lai)講bu)獾諞恢址絞健V苯蛹壇cheng)現有(you)的Span。文章開頭(tou)時展示(shi)的ActionBar動畫就是通過繼承(cheng)ForegroundSpan來(lai)實現的。
 我們主要重(zhong)載了updateDrawsState和getForegroundColor,這樣就可以通過改變setAlpha函數來(lai)改變顏色(se),讓字體從透明(alpha為0)到某個特定顏色(se)。

public class MutableForegroundColorSpan extends ForegroundColorSpan { private int mAlpha = 255; private int mForegroundColor; public MutableForegroundColorSpan(int alpha,int color) { super(color); mAlpha = alpha; mForegroundColor = color; } @Override public void updateDrawState(TextPaint ds) { ds.setColor(getForegroundColor()); } public void setAlpha(int alpha) { mAlpha = alpha; } public void setForegroundColor(int foregroundColor) { mForegroundColor = foregroundColor; } public float getAlpha() { return mAlpha; } @Override public int getForegroundColor() { return Color.argb(mAlpha,Color.red(mForegroundColor),Color.green(mForegroundColor),Color.blue(mForegroundColor)); }}

 第二種方法是繼承(cheng)Span架構中(zhong)的抽象類或(huo)者是實現特定接口(kou)。需(xu)要注意(yi)的是,在上一篇文章中(zhong)說的CharacterStyle,ParagraphStyle.UpdateAppearance和UpdateLayout都是沒(mei)有(you)函數的,所(suo)以,我們無(wu)法直接繼承(cheng)或(huo)者實現它(ta)們。除了第一篇文章中(zhong)所(suo)介紹的那些Span可以使用第一種方法進行(xing)繼承(cheng)。我們qie)話(hua)愣技壇cheng)或(huo)者實現MetricAffectingSpan,ReplacementSpan或(huo)者LineBackgroundSpan。
 比(bi)如我們想給每個字都添加一個不同顏色(se)的背景,我們就可以繼承(cheng)ReplacementSpan

demo

public class BubbleSpan extends ReplacementSpan { private Paint mPaint; static Random random = new Random(); private int mWidth = -1; private RectF mRectF = new RectF(); private int[] mColors = new int[20]; public BubbleSpan() { initPaint(); initColors(); } private void initPaint() { mPaint = new Paint(); mPaint.setColor(Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255))); mPaint.setAntiAlias(true); } private void initColors() { for(int index = 0 ; index < mColors.length ; index++) {  mColors[index] = Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255)); } } @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { //return text with relative to the Paint mWidth = (int) paint.measureText(text, start, end); return mWidth; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { float charx = x; for(int i = start ; i<end; i++) {  String charAt = extractText(text, i, i + 1);  float charWidth = paint.measureText(charAt);  mRectF.set(charx, top, charx += charWidth, bottom);  mPaint.setColor(mColors[i % mColors.length]);  //根據(ju)每個字的位置mei)嬤票塵 canvas.drawOval(mRectF, mPaint); } //繪制字體,如果(guo)不掉用這個函數,就不會顯示(shi)字體啦。 canvas.drawText(text, start, end, x, y, paint); } private String extractText(CharSequence text, int start, int end) { return text.subSequence(start, end).toString(); }}

 我們可以看到,我們qie) 迪至liang)個函數:getSize和draw。getSize是獲得(de)字體的長度(du)的,所(suo)以一hua)愣際侵苯郵褂aint.measureText,然後draw中(zhong)進行(xing)繪制,你可以在這里把(ba)每個字的背景繪制出來(lai),而且(qie)你必須也要把(ba)字體給繪制出來(lai)。如果(guo)你只想繪制背景,不想涉及(ji)字體的繪制,那麼就可以直接實現LineBackgroundSpan接口(kou)。

public class RectSpan extends ReplacementSpan { private final Paint mPaint; private int mWidth; public RectSpan() { mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(Color.BLUE); mPaint.setAntiAlias(true); } @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { //return text with relative to the Paint mWidth = (int) paint.measureText(text, start, end); return mWidth; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { //只繪制了外圍矩形,沒(mei)有(you)繪制文字。 canvas.drawRect(x, top, x + mWidth, bottom, mPaint); }}

demo

通過Span實現動畫

 在上一節中(zhong),我們qie)丫 迪至utableForegroundColorSpan類,那麼如何使用它(ta)來(lai)實現動畫呢(ne)?這里我們就要使用到ObjectAnimator和Property<T1,T2>。我們首先定義(yi)MutableForegroundColorSpan使用的property。

private static final Property<MutableForegroundColorSpan, Integer> MUTABLE_FOREGROUND_COLOR_SPAN_PROPERTY = new Property<MutableForegroundColorSpan, Integer>(Integer.class, 'MUTABLE_FOREGROUND_COLOR_SPAN_FC_PROPERTY') { @Override  public void set(MutableForegroundColorSpan alphaForegroundColorSpanGroup, Integer value) {   alphaForegroundColorSpanGroup.setForegroundColor(value);  } @Override  public Integer get(MutableForegroundColorSpan span) {   return span.getForegroundColor();  }};

 然後我們就可以使用ObjectAnimator對(dui)MutableForegroundColorSpan實現屬(shu)性動畫了。

MutableForegroundColorSpan span = new MutableForegroundColorSpan(255, Color.BLUE);final SpannableString spannableString = new SpannableString(CONTENT);spannableString.setSpan(span, 0,4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);ObjectAnimator objectAnimator = ObjectAnimator.ofInt(span, MUTABLE_FOREGROUND_COLOR_SPAN_PROPERTY, Color.BLACK, Color.RED);objectAnimator.setEvaluator(new ArgbEvaluator());objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //refresh  mTvTextView.setText(spannableString); } });objectAnimator.setInterpolator(mSmoothInterpolator);objectAnimator.setDuration(600);objectAnimator.start();

 這里還只是單獨(du)一個Span實例的動畫效果(guo),你可以對(dui)多個Span實例進行(xing)屬(shu)性動畫,從而實現更加復雜的動畫效果(guo)。就比(bi)如文章開始時的文字逐漸顯示(shi)的動畫效果(guo)。
 我們可以給每個字都設置一個MutableForegroundColorSpan實例,並將這些實例都添加到一個對(dui)象中(zhong),然後在屬(shu)性動畫過程中(zhong),亂序設置每個實例的alpha的值,從而達到文字逐漸顯現的動畫。

public class FireWorkGroup { private final float mProgress; private final ArrayList<MutableForegroundColorSpan> mSpans; private final ArrayList<Integer> mSpanIndexes; public FireWorkGroup() { mProgress = 0; mSpans = new ArrayList<>(); mSpanIndexes = new ArrayList<>(); } public void addSpan(MutableForegroundColorSpan span) { span.setAlpha(0); mSpanIndexes.add(mSpans.size()); mSpans.add(span); } public void init() { Collections.shuffle(mSpans); } public void setProgress(float progress) { int size = mSpans.size(); float total = 1.0f * size * progress; for (int index = 0 ; index < size ; index++) {  MutableForegroundColorSpan span = mSpans.get(index);  if (total > 1.0f) {  span.setAlpha(255);  total -= 1.0f;  } else {  span.setAlpha((int)(total * 255));  total = 0.0f;  } } } public float getProgress() { return mProgress; } public static final Property<FireWorkGroup, Float> FIREWORKS_GROUP_PROGRESS_PROPERTY =  new Property<FireWorkGroup, Float>(Float.class, 'FIREWORKS_GROUP_PROGRESS_PROPERTY') {  @Override  public void set(FireWorkGroup spanGroup, Float value) {   spanGroup.setProgress(value);  }  @Override  public Float get(FireWorkGroup spanGroup) {   return spanGroup.getProgress();  }  };}

後記(ji)

 上述的這些動畫都是我在第一篇文章提到的那篇博文中(zhong)實現過的效果(guo),我在學習過程中(zhong)又發現了一個實現了很多TextView相(xiang)關動畫的開源項目HTextView。所(suo)以接下來(lai)的任(ren)務(wu)就是想使用Span機制去(qu)實現這個項目中(zhong)的一些動畫效果(guo)。希望大(da)家繼續支持我的文章,並積極指出文中(zhong)的錯誤。
 !!!源碼都在我的github里。

lol外围官网

    Tag標簽︰進階  
    • lol外围官网

    About IT165 - 廣告服務(wu) - 隱私聲明 - 版權(quan)申明 - 免責條款 - 網(wang)站地圖 - 網(wang)友投稿(gao) - 聯(lian)系方式
    本站內容來(lai)自于(yu)互聯(lian)網(wang),僅供(gong)用于(yu)網(wang)絡(luo)技術學習,學習中(zhong)請遵(zun)循(xun)相(xiang)關法律法規
    lol外围官网 | 下一页