最近比較火的幾個組件Android Design Support Library包含8個新的組件,最低支持Android2.1。使用TextInputLaypout這個控件可以非常方便的做出用戶登錄界面帳號密碼輸入框的效果。
一 TextInputLayout的使用
1.1
使用這些新的組件之前先引用庫,在 build.gradle
文件中加上這段代碼
compile 'com.android.support:design:25.0.1'
這裏使用TextInputLaout簡單寫了一個註冊信息,輸入姓名和密碼
佈局代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.textinputlayout.MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:errorEnabled="true"
android:id="@+id/textInputId"
>
<AutoCompleteTextView
android:id="@+id/nameId"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:hint="@string/tipName"
android:inputType="textEmailAddress"
android:maxLines="1"
android:singleLine="true"
>
</>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:errorEnabled="true"
>
<EditText
android:id="@+id/psdId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/tipPsd"
android:maxLines="1"
android:singleLine="true"
android:inputType="textPassword"
/>
</android.support.design.widget.TextInputLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subBt"
android:textSize="18sp"
android:layout_marginTop="10dp"
/>
</LinearLayout>
</ScrollView>
</LinearLayout>
在MainActivity中
package com.textinputlayout;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
/**
* @autor:liangyuanyuan
* @date:2016/12/21
* @des:textInputText demo學習
*/
public class MainActivity extends AppCompatActivity {
private TextInputLayout mTextInputLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextInputLayout= (TextInputLayout) findViewById(R.id.textInputId);
mTextInputLayout.getEditText().addTextChangedListener(new MinLengthWatch("輸入的文字長度最大6",mTextInputLayout));
//開啓計時器
mTextInputLayout.setCounterEnabled(true);
mTextInputLayout.setCounterMaxLength(10);
}
class MinLengthWatch implements TextWatcher{
private String errStr;
private TextInputLayout mTextInputLayout;
public MinLengthWatch(String errStr,TextInputLayout mTextInputLayout){
this.errStr=errStr;
this.mTextInputLayout=mTextInputLayout;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
//檢測輸入的文字的長度是否符合要求,長度低於6
if(mTextInputLayout.getEditText().getText().toString().length()<=6){
mTextInputLayout.setErrorEnabled(false);
}else{
mTextInputLayout.setErrorEnabled(true);
//設置錯誤的提示
mTextInputLayout.setError(errStr);
}
}
}
}
1.2 簡單說明一下這個控件的使用
使用TextInputLayout非常簡單,它是一個ViewGroup,裏面可以包裹EditText或者AutoCompleteTextView,以下幾個屬性和方法需要聲明一下:
app:hintAnimationEnabled="true"可以開啓動畫,這個爲true時,獲得焦點的時候hint提示問題會動畫地移動上去。
app:errorEnabled="true"時,開啓錯誤提示
textInputLayout.setCounterEnabled(true);用於 開啓計數
textInputLayout.setCounterMaxLength(10);設置最大輸入限制數
textInputLayout.setError(errorStr);設置錯誤提示的信息
textInputLayout.getEditText().addTextChangedListener()用於給textInputLayout包裹的EditText設置內容變化監聽,我們可以自己重寫一個監聽實現裏面的方法進行相關邏輯的處理
1.3 效果如下:
注意項:
TextInputLayout中至少嵌套一個EditText。
二
TextInputLayout源碼分析
TextInputLayout繼承自LinearLayout,說明它是一個ViewGroup
-
public class TextInputLayout extendsLinearLayout
先從構造函數開始看起
-
public TextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
-
-
super(context, attrs);
-
-
setOrientation(VERTICAL);
-
setWillNotDraw(false);
-
setAddStatesFromChildren(true);
這裏它自動設置了VERTICAL的Orientation,說明這個TextInputLayout是一個豎直的排列,那字數超過部分的提示,在哪裏添加的呢?說明在源碼中必定有添加這個提示的邏輯,這裏我們後面在討論,先繼續往下看
-
mCollapsingTextHelper.setTextSizeInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
-
mCollapsingTextHelper.setPositionInterpolator(new AccelerateInterpolator());
-
mCollapsingTextHelper.setCollapsedTextGravity(Gravity.TOP | GravityCompat.START);
-
-
final TypedArray a = context.obtainStyledAttributes(attrs,
-
R.styleable.TextInputLayout, defStyleAttr, R.style.Widget_Design_TextInputLayout);
-
mHint = a.getText(R.styleable.TextInputLayout_android_hint);
-
mHintAnimationEnabled = a.getBoolean(
-
R.styleable.TextInputLayout_hintAnimationEnabled, true);
這裏出現了一個mCollapsingTextHelper,通過它可以設置文字大小的加速動畫,FAST_OUT_SLOW_IN_INTERPOLATOR,快出慢進的效果,還有設置位置的加速器setPositionInterpolator,setCollapsedTextGravity設置摺疊文字的Gravity,看來這個mCollapsingTextHelper的作用還是很強大的,我們後面再看它的源碼,先繼續往下看
-
final TypedArray a = context.obtainStyledAttributes(attrs,
-
R.styleable.TextInputLayout, defStyleAttr, R.style.Widget_Design_TextInputLayout);
-
mHint = a.getText(R.styleable.TextInputLayout_android_hint);
-
mHintAnimationEnabled = a.getBoolean(
-
R.styleable.TextInputLayout_hintAnimationEnabled, true);
-
-
if (a.hasValue(R.styleable.TextInputLayout_android_textColorHint)) {
-
mDefaultTextColor = mFocusedTextColor =
-
a.getColorStateList(R.styleable.TextInputLayout_android_textColorHint);
-
}
-
-
final int hintAppearance = a.getResourceId(
-
R.styleable.TextInputLayout_hintTextAppearance, -1);
-
if (hintAppearance != -1) {
-
setHintTextAppearance(
-
a.getResourceId(R.styleable.TextInputLayout_hintTextAppearance, 0));
-
}
-
-
mErrorTextAppearance = a.getResourceId(R.styleable.TextInputLayout_errorTextAppearance, 0);
-
final boolean errorEnabled = a.getBoolean(R.styleable.TextInputLayout_errorEnabled, false);
-
a.recycle();
從TypedArray中取出一些用戶給TextInputLayout設置的屬性,比如給hint設置的文字,mHintAnimationEnabled,hint內文字的動畫是否可用,還有hintAppearance的值,mErrorTextAppearance是錯誤提示文字的樣式,errorEnabled是否開啓錯誤提示
-
setErrorEnabled(errorEnabled);
並通過setErrorEnabled把errorEnabled的值設置給TextInputLayout,TextInputLayout是一個ViewGroup,所以addView方法是必須的
-
public void addView(View child, int index, ViewGroup.LayoutParams params) {
-
if (child instanceof EditText) {
-
setEditText((EditText) child);
-
super.addView(child, 0, updateEditTextMargin(params));
-
} else {
-
-
super.addView(child, index, params);
-
}
-
}
只有當child 是 EditText的時候,會調用自身的setEditText方法,然後調用父類LinearLayout的addView方法,如果不是EditText,也調用父類的addView方法,查看setEditText方法 內部
-
private void setEditText(EditText editText) {
-
-
if (mEditText != null) {
-
throw new IllegalArgumentException("We already have an EditText, can only have one");
-
}
-
mEditText = editText;
-
-
-
mCollapsingTextHelper.setTypeface(mEditText.getTypeface());
-
mCollapsingTextHelper.setExpandedTextSize(mEditText.getTextSize());
-
mCollapsingTextHelper.setExpandedTextGravity(mEditText.getGravity());
如果TextInputLayout內已經有了一個EditText,再添加就會報錯,使用CollapsingTextHelper把傳進來的editText的相關屬性取出進行設置
-
mEditText.addTextChangedListener(new TextWatcher() {
-
@Override
-
public void afterTextChanged(Editable s) {
-
updateLabelVisibility(true)<pre name="code" class="java">
然後給EditText設置文本變化的監聽,在文本改變之前,正在改變的時候都可以做相應的邏輯處理,往下看有更改EditText的Margin的方法
-
private LayoutParams updateEditTextMargin(ViewGroup.LayoutParams lp) {
-
-
-
LayoutParams llp = lp instanceof LayoutParams ? (LayoutParams) lp : new LayoutParams(lp);
-
-
if (mTmpPaint == null) {
-
mTmpPaint = new Paint();
-
}
-
mTmpPaint.setTypeface(mCollapsingTextHelper.getTypeface());
-
mTmpPaint.setTextSize(mCollapsingTextHelper.getCollapsedTextSize());
-
llp.topMargin = (int) -mTmpPaint.ascent();
-
-
return llp;
-
}
設置提示文字的樣式
-
public void setHintTextAppearance(@StyleRes int resId) {
-
mCollapsingTextHelper.setCollapsedTextAppearance(resId);
-
mFocusedTextColor = ColorStateList.valueOf(mCollapsingTextHelper.getCollapsedTextColor());
-
-
if (mEditText != null) {
-
updateLabelVisibility(false);
-
-
-
LayoutParams lp = updateEditTextMargin(mEditText.getLayoutParams());
-
mEditText.setLayoutParams(lp);
-
mEditText.requestLayout();
-
}
-
}
設置錯誤提示開啓和關閉的方法
-
public void setErrorEnabled(boolean enabled) {
-
if (mErrorEnabled != enabled) {
-
if (mErrorView != null) {
-
ViewCompat.animate(mErrorView).cancel();
-
}
-
-
if (enabled) {
-
mErrorView = new TextView(getContext());
-
mErrorView.setTextAppearance(getContext(), mErrorTextAppearance);
-
mErrorView.setVisibility(INVISIBLE);
-
addView(mErrorView);
-
-
if (mEditText != null) {
-
-
ViewCompat.setPaddingRelative(mErrorView, ViewCompat.getPaddingStart(mEditText),
-
0, ViewCompat.getPaddingEnd(mEditText), mEditText.getPaddingBottom());
-
}
-
} else {
-
removeView(mErrorView);
-
mErrorView = null;
-
}
-
mErrorEnabled = enabled;
-
}
-
}
如果enabled爲true的時候,這裏會new一個TextView,給TextView設置文本信息和設爲可見,然後使用addView(mErrorView)方法,將其添加到TextInputLayout之中,還記得前面我們提過TextInputLayout之中肯定應該會有一個添加錯誤提示信息的方法,在這裏我們找到了,同時這裏的代碼也是值得我們進行學習的,只有當用戶設置錯誤提示爲真的時候,纔會new一個TextView,這樣是比較省性能的,接下來是setError方法,設置錯誤提示的文本信息,裏面是一些判斷和動畫的設置
-
public void setError(@Nullable CharSequence error) {
-
if (!mErrorEnabled) {
-
if (TextUtils.isEmpty(error)) {
-
-
return;
-
}
-
-
setErrorEnabled(true);
-
}
-
-
if (!TextUtils.isEmpty(error)) {
-
ViewCompat.setAlpha(mErrorView, 0f);
-
mErrorView.setText(error);
-
ViewCompat.animate(mErrorView)
-
.alpha(1f)
-
.setDuration(ANIMATION_DURATION)
-
.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
-
.setListener(new ViewPropertyAnimatorListenerAdapter() {
-
@Override
-
public void onAnimationStart(View view) {
-
view.setVisibility(VISIBLE);
-
}
-
})
-
.start();
-
-
-
ViewCompat.setBackgroundTintList(mEditText,
-
ColorStateList.valueOf(mErrorView.getCurrentTextColor()));
-
} else {
-
if (mErrorView.getVisibility() == VISIBLE) {
-
ViewCompat.animate(mErrorView)
-
.alpha(0f)
-
.setDuration(ANIMATION_DURATION)
-
.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
-
.setListener(new ViewPropertyAnimatorListenerAdapter() {
-
@Override
-
public void onAnimationEnd(View view) {
-
view.setVisibility(INVISIBLE);
-
}
-
}).start();
-
-
-
final TintManager tintManager = TintManager.get(getContext());
-
ViewCompat.setBackgroundTintList(mEditText,
-
tintManager.getTintList(R.drawable.abc_edit_text_material));
-
}
-
}
-
-
sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
-
}
接下來是draw方法,調用了mCollapsingTextHelper的draw方法,說明這個TextInputLayout是畫出來
-
<pre name="code" class="java">public void draw(Canvas canvas) {
-
super.draw(canvas);
-
mCollapsingTextHelper.draw(canvas);
-
}
onLayout方法,會拿到EditText的Left,Right等屬性,然後使用mCollapsingTextHelper 來setExpandedBounds,設置一個Bound區域
-
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-
super.onLayout(changed, left, top, right, bottom);
-
-
if (mEditText != null) {
-
final int l = mEditText.getLeft() + mEditText.getCompoundPaddingLeft();
-
final int r = mEditText.getRight() - mEditText.getCompoundPaddingRight();
-
-
mCollapsingTextHelper.setExpandedBounds(l,
-
mEditText.getTop() + mEditText.getCompoundPaddingTop(),
-
r, mEditText.getBottom() - mEditText.getCompoundPaddingBottom());
-
-
-
-
mCollapsingTextHelper.setCollapsedBounds(l, getPaddingTop(),
-
r, bottom - top - getPaddingBottom());
-
-
mCollapsingTextHelper.recalculate();
-
}
-
}
上面的有一句註釋還是很重要的:設置摺疊的bounds去匹配EditText可編輯區域的高,接下來我們查看CollapsingTextHelper這個非常重要的類的代碼
-
public CollapsingTextHelper(View view) {
-
mView = view;
-
-
mTextPaint = new TextPaint();
-
mTextPaint.setAntiAlias(true);
-
-
mCollapsedBounds = new Rect();
-
mExpandedBounds = new Rect();
-
mCurrentBounds = new RectF();
構造函數中會把view傳進來,而這個view就是TextInputLayout,同時new了一個TextPaint來進行文本的繪製,然後是new出來3個矩形區域,mCollapsedBounds:輸入框處於摺疊狀態下的矩形區域,mExpandedBounds:提示框獲得焦點,提示文字向上展開的矩形區域,mCurrentBounds:當前狀態下的矩形區域;往下是一大堆set方法,然後有一個setExpandedBounds方法
-
void setExpandedBounds(int left, int top, int right, int bottom) {
-
if (!rectEquals(mExpandedBounds, left, top, right, bottom)) {
-
mExpandedBounds.set(left, top, right, bottom);
-
mBoundsChanged = true;
-
onBoundsChanged();
-
}
-
}
setCollapsedBounds方法
-
void setCollapsedBounds(int left, int top, int right, int bottom) {
-
if (!rectEquals(mCollapsedBounds, left, top, right, bottom)) {
-
mCollapsedBounds.set(left, top, right, bottom);
-
mBoundsChanged = true;
-
onBoundsChanged();
-
}
-
}
其實也沒有什麼,就是設置left,top, right, bottom,然後調用onBoundsChanged方法進行更新,接下來有setCollapsedTextAppearance方法,設置摺疊時候文字的樣式
-
void setCollapsedTextAppearance(int resId) {
-
TypedArray a = mView.getContext().obtainStyledAttributes(resId, R.styleable.TextAppearance);
-
if (a.hasValue(R.styleable.TextAppearance_android_textColor)) {
-
mCollapsedTextColor = a.getColor(
-
R.styleable.TextAppearance_android_textColor, mCollapsedTextColor);
-
}
-
if (a.hasValue(R.styleable.TextAppearance_android_textSize)) {
-
mCollapsedTextSize = a.getDimensionPixelSize(
-
R.styleable.TextAppearance_android_textSize, (int) mCollapsedTextSize);
-
}
-
a.recycle();
-
-
recalculate();
-
}
setExpandedTextAppearance:設置展開狀態時文字的樣式
-
void setExpandedTextAppearance(int resId) {
-
TypedArray a = mView.getContext().obtainStyledAttributes(resId, R.styleable.TextAppearance);
-
if (a.hasValue(R.styleable.TextAppearance_android_textColor)) {
-
mExpandedTextColor = a.getColor(
-
R.styleable.TextAppearance_android_textColor, mExpandedTextColor);
-
}
-
if (a.hasValue(R.styleable.TextAppearance_android_textSize)) {
-
mExpandedTextSize = a.getDimensionPixelSize(
-
R.styleable.TextAppearance_android_textSize, (int) mExpandedTextSize);
-
}
-
a.recycle();
-
-
recalculate();
-
}
都是取出mView(傳進來的TextInputLayout)的屬性取出來進行設置,我們會發現各個方法裏都調用了recalculate()方法,也就是重新計算,我們查看一下這個方法
-
public void recalculate() {
-
if (mView.getHeight() > 0 && mView.getWidth() > 0) {
-
-
-
calculateBaseOffsets();
-
calculateCurrentOffsets();
-
}
-
}
判斷條件是當TextInputLayout的Height與Width都大於0的時候會調用calculateBaseOffsets()與calculateCurrentOffsets()方法,註釋的內容:如果TextInputLayout已經被laid out的時候,會去重新計算現在佈局的一切,否則就等待。calculateBaseOffsets()方法,用於計算基本的偏移量,注意註釋的內容:在計算摺疊狀態下的文字大小,也使用同樣的邏輯
-
final int collapsedAbsGravity = GravityCompat.getAbsoluteGravity(mCollapsedTextGravity,
-
mIsRtl ? ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR);
-
switch (collapsedAbsGravity & Gravity.VERTICAL_GRAVITY_MASK) {
-
case Gravity.BOTTOM:
-
mCollapsedDrawY = mCollapsedBounds.bottom;
-
break;
-
case Gravity.TOP:
-
mCollapsedDrawY = mCollapsedBounds.top - mTextPaint.ascent();
-
break;
-
case Gravity.CENTER_VERTICAL:
-
default:
-
float textHeight = mTextPaint.descent() - mTextPaint.ascent();
-
float textOffset = (textHeight / 2) - mTextPaint.descent();
-
mCollapsedDrawY = mCollapsedBounds.centerY() + textOffset;
-
break;
-
}
-
switch (collapsedAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-
case Gravity.CENTER_HORIZONTAL:
-
mCollapsedDrawX = mCollapsedBounds.centerX() - (width / 2);
-
break;
-
case Gravity.RIGHT:
-
mCollapsedDrawX = mCollapsedBounds.right - width;
-
break;
-
case Gravity.LEFT:
-
default:
-
mCollapsedDrawX = mCollapsedBounds.left;
-
break;
-
}
取出collapsedAbsGravity的值,然後和各種Gravity進行比較,然後確定mCollapsedDrawY 和mCollapsedDrawX的值
-
mTextPaint.setTextSize(mExpandedTextSize);
-
width = mTextToDraw != null
-
? mTextPaint.measureText(mTextToDraw, 0, mTextToDraw.length()) : 0;
-
final int expandedAbsGravity = GravityCompat.getAbsoluteGravity(mExpandedTextGravity,
-
mIsRtl ? ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR);
-
switch (expandedAbsGravity & Gravity.VERTICAL_GRAVITY_MASK) {
-
case Gravity.BOTTOM:
-
mExpandedDrawY = mExpandedBounds.bottom;
-
break;
-
case Gravity.TOP:
-
mExpandedDrawY = mExpandedBounds.top - mTextPaint.ascent();
-
break;
-
case Gravity.CENTER_VERTICAL:
-
default:
-
float textHeight = mTextPaint.descent() - mTextPaint.ascent();
-
float textOffset = (textHeight / 2) - mTextPaint.descent();
-
mExpandedDrawY = mExpandedBounds.centerY() + textOffset;
-
break;
-
}
-
switch (expandedAbsGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-
case Gravity.CENTER_HORIZONTAL:
-
mExpandedDrawX = mExpandedBounds.centerX() - (width / 2);
-
break;
-
case Gravity.RIGHT:
-
mExpandedDrawX = mExpandedBounds.right - width;
-
break;
-
case Gravity.LEFT:
-
default:
-
mExpandedDrawX = mExpandedBounds.left;
-
break;
-
}
取出expandedAbsGravity的值然後和各種Gravity進行比較,然後確定mCollapsedDrawY 和mCollapsedDrawX的值,最後調用clearTexture()方法清空texture(紋理的意思)
calculateCurrentOffsets方法,通過lerp方法獲取mCurrentDrawX與mCurrentDrawY的值,如果mCollapsedTextColor != mExpandedTextColor,給mTextPaint設置顏色,而這個顏色會通過blendColors方法將mCollapsedTextColor與mExpandedTextColor進行混合,然後採用ViewCompat.postInvalidateOnAnimation方法進行刷新
-
private void calculateCurrentOffsets() {
-
final float fraction = mExpandedFraction;
-
-
interpolateBounds(fraction);
-
mCurrentDrawX = lerp(mExpandedDrawX, mCollapsedDrawX, fraction,
-
mPositionInterpolator);
-
mCurrentDrawY = lerp(mExpandedDrawY, mCollapsedDrawY, fraction,
-
mPositionInterpolator);
-
-
setInterpolatedTextSize(lerp(mExpandedTextSize, mCollapsedTextSize,
-
fraction, mTextSizeInterpolator));
-
-
if (mCollapsedTextColor != mExpandedTextColor) {
-
-
-
mTextPaint.setColor(blendColors(mExpandedTextColor, mCollapsedTextColor, fraction));
-
} else {
-
mTextPaint.setColor(mCollapsedTextColor);
-
}
-
-
ViewCompat.postInvalidateOnAnimation(mView);
-
}
再看一下blendColors內部,也就是通過一個ratio對顏色進行計算,分別計算出ARGB
-
private static int blendColors(int color1, int color2, float ratio) {
-
final float inverseRatio = 1f - ratio;
-
float a = (Color.alpha(color1) * inverseRatio) + (Color.alpha(color2) * ratio);
-
float r = (Color.red(color1) * inverseRatio) + (Color.red(color2) * ratio);
-
float g = (Color.green(color1) * inverseRatio) + (Color.green(color2) * ratio);
-
float b = (Color.blue(color1) * inverseRatio) + (Color.blue(color2) * ratio);
-
return Color.argb((int) a, (int) r, (int) g, (int) b);
-
}
再看一下draw方法
-
public void draw(Canvas canvas) {
-
final int saveCount = canvas.save();
-
-
if (mTextToDraw != null && mDrawTitle) {
-
float x = mCurrentDrawX;
-
float y = mCurrentDrawY;
-
-
final boolean drawTexture = mUseTexture && mExpandedTitleTexture != null;
-
-
final float ascent;
-
final float descent;
-
-
-
mTextPaint.setTextSize(mCurrentTextSize);
-
-
if (drawTexture) {
-
ascent = mTextureAscent * mScale;
-
descent = mTextureDescent * mScale;
-
} else {
-
ascent = mTextPaint.ascent() * mScale;
-
descent = mTextPaint.descent() * mScale;
-
}
-
-
if (DEBUG_DRAW) {
-
-
canvas.drawRect(mCurrentBounds.left, y + ascent, mCurrentBounds.right, y + descent,
-
DEBUG_DRAW_PAINT);
-
}
-
-
if (drawTexture) {
-
y += ascent;
-
}
-
-
if (mScale != 1f) {
-
canvas.scale(mScale, mScale, x, y);
-
}
-
-
if (drawTexture) {
-
-
canvas.drawBitmap(mExpandedTitleTexture, x, y, mTexturePaint);
-
} else {
-
canvas.drawText(mTextToDraw, 0, mTextToDraw.length(), x, y, mTextPaint);
-
}
-
}
-
-
canvas.restoreToCount(saveCount);
-
}
給TextPaint設置當前文字的大小,並給X,Y賦值
-
float x = mCurrentDrawX;
-
float y = mCurrentDrawY;
-
-
final boolean drawTexture = mUseTexture && mExpandedTitleTexture != null;
-
-
final float ascent;
-
final float descent;
-
-
-
mTextPaint.setTextSize(mCurrentTextSize);
如果需要繪製紋理,則調用canvas的drawBitmap方法,否則canvas 的drawText方法,繪製文字
-
if (drawTexture) {
-
-
canvas.drawBitmap(mExpandedTitleTexture, x, y, mTexturePaint);
-
} else {
-
canvas.drawText(mTextToDraw, 0, mTextToDraw.length(), x, y, mTextPaint);
-
}
還有一個calculateIsRtl方法,從右向左計算,是專門給左撇子設計的
-
private boolean calculateIsRtl(CharSequence text) {
-
final boolean defaultIsRtl = ViewCompat.getLayoutDirection(mView)
-
== ViewCompat.LAYOUT_DIRECTION_RTL;
-
return (defaultIsRtl
-
? TextDirectionHeuristicsCompat.FIRSTSTRONG_RTL
-
: TextDirectionHeuristicsCompat.FIRSTSTRONG_LTR).isRtl(text, 0, text.length());
-
}
到此,源碼就基本分析完畢了。
轉自:http://blog.csdn.net/u012124438/article/details/51778845