中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android如何使用圖文居中顯示控件

發布時間:2020-11-04 17:35:47 來源:億速云 閱讀:234 作者:Leah 欄目:開發技術

Android如何使用圖文居中顯示控件?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

最近項目中用到了文字圖標的按鈕,需要居中顯示,如果用TextView實現的方式,必須同時設置padding和drawablePadding。如下:

<androidx.appcompat.widget.AppCompatTextView
  android:layout_width="200dp"
  android:layout_height="wrap_content"
  android:drawableLeft="@drawable/ic_xxx"
  android:drawablePadding="-60dp"
  android:minHeight="48dp"
  android:gravity="center"
  android:padding="80dp" />

這種方式需要自己做精確計算。比較麻煩。另外還有一種方式就是用線性布局包裹ImageView和TextView,但這樣會增加布局層級。于是自己封裝了一個控件DrawableCenterTextView。

attrs.xml文件中定義屬性:

<declare-styleable name="DrawableCenterTextView">
  <attr name="android:text" />
  <attr name="android:textColor" />
  <attr name="android:textSize" />
  <attr name="android:textStyle" />
  <attr name="android:drawablePadding" />
  <attr name="android:drawableLeft" />
  <attr name="android:drawableTop" />
  <attr name="android:drawableRight" />
  <attr name="android:drawableBottom" />
</declare-styleable>

對應的Java代碼如下:

public class DrawableCenterTextView extends View {

 static final int LEFT = 0;
 static final int TOP = 1;
 static final int RIGHT = 2;
 static final int BOTTOM = 3;

 private CharSequence mText;
 private ColorStateList mTextColor;
 private float mTextSize;
 private int mTextStyle;
 private int mDrawablePadding;
 private Drawable[] mCompoundDrawables;

 private Rect mTextBounds;
 private Rect mDrawableLeftBounds;
 private Rect mDrawableTopBounds;
 private Rect mDrawableRightBounds;
 private Rect mDrawableBottomBounds;

 private TextPaint mTextPaint;

 public DrawableCenterTextView(Context context) {
  this(context, null);
 }

 public DrawableCenterTextView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public DrawableCenterTextView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);

  Drawable drawableLeft = null, drawableTop = null, drawableRight = null, drawableBottom = null;
  TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DrawableCenterTextView, defStyleAttr, 0);
  mText = ta.getText(R.styleable.DrawableCenterTextView_android_text);
  mTextColor = ta.getColorStateList(R.styleable.DrawableCenterTextView_android_textColor);
  mTextSize = ta.getDimensionPixelSize(R.styleable.DrawableCenterTextView_android_textSize, 15);
  mTextStyle = ta.getInt(R.styleable.DrawableCenterTextView_android_textStyle, 0);

  drawableLeft = ta.getDrawable(R.styleable.DrawableCenterTextView_android_drawableLeft);
  drawableTop = ta.getDrawable(R.styleable.DrawableCenterTextView_android_drawableTop);
  drawableRight = ta.getDrawable(R.styleable.DrawableCenterTextView_android_drawableRight);
  drawableBottom = ta.getDrawable(R.styleable.DrawableCenterTextView_android_drawableBottom);

  mDrawablePadding = ta.getDimensionPixelSize(R.styleable.DrawableCenterTextView_android_drawablePadding, 0);
  ta.recycle();

  if (mTextColor == null) {
   mTextColor = ColorStateList.valueOf(0xFF000000);
  }

  mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
  mTextPaint.density = getResources().getDisplayMetrics().density;
  mTextPaint.setTextSize(mTextSize);
  setTypeface(Typeface.create(Typeface.DEFAULT, mTextStyle));

  setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int heightSize = MeasureSpec.getSize(heightMeasureSpec);

  int width;
  int height;

  //計算文本范圍
  calcTextBounds();

  if (widthMode == MeasureSpec.EXACTLY) {
   width = widthSize;
  } else {
   width = mTextBounds.width();

   if (mCompoundDrawables != null) {
    if (mCompoundDrawables[TOP] != null) {
     width = Math.max(width, mDrawableTopBounds.width());
    }

    if (mCompoundDrawables[BOTTOM] != null) {
     width = Math.max(width, mDrawableBottomBounds.width());
    }

    //加上左右內邊距及drawable寬度和drawable間距
    width += getCompoundPaddingLeft() + getCompoundPaddingRight();

    width = Math.max(width, getSuggestedMinimumWidth());

    if (widthMode == MeasureSpec.AT_MOST) {
     width = Math.min(widthSize, width);
    }
   }
  }

  if (heightMode == MeasureSpec.EXACTLY) {
   height = heightSize;
  } else {
   height = mTextBounds.height();

   if (mCompoundDrawables != null) {
    if (mCompoundDrawables[LEFT] != null) {
     height = Math.max(height, mDrawableLeftBounds.height());
    }

    if (mCompoundDrawables[RIGHT] != null) {
     height = Math.max(height, mDrawableRightBounds.height());
    }

    //加上上下內邊距及drawable高度和drawable間距
    height += getCompoundPaddingTop() + getCompoundPaddingBottom();

    height = Math.max(height, getSuggestedMinimumHeight());

    if (heightMode == MeasureSpec.AT_MOST) {
     height = Math.min(heightSize, height);
    }
   }
  }

  setMeasuredDimension(width, height);
 }

 public int getCompoundPaddingTop() {
  if (mCompoundDrawables == null || mCompoundDrawables[TOP] == null) {
   return getPaddingTop();
  } else {
   Rect rect = new Rect();
   mCompoundDrawables[TOP].copyBounds(rect);
   return getPaddingTop() + mDrawablePadding + rect.height();
  }
 }

 public int getCompoundPaddingBottom() {
  if (mCompoundDrawables == null || mCompoundDrawables[BOTTOM] == null) {
   return getPaddingBottom();
  } else {
   Rect rect = new Rect();
   mCompoundDrawables[BOTTOM].copyBounds(rect);
   return getPaddingBottom() + mDrawablePadding + rect.height();
  }
 }

 public int getCompoundPaddingLeft() {
  if (mCompoundDrawables == null || mCompoundDrawables[LEFT] == null) {
   return getPaddingLeft();
  } else {
   Rect rect = new Rect();
   mCompoundDrawables[LEFT].copyBounds(rect);
   return getPaddingLeft() + mDrawablePadding + rect.width();
  }
 }

 public int getCompoundPaddingRight() {
  if (mCompoundDrawables == null || mCompoundDrawables[RIGHT] == null) {
   return getPaddingRight();
  } else {
   Rect rect = new Rect();
   mCompoundDrawables[RIGHT].copyBounds(rect);
   return getPaddingRight() + mDrawablePadding + rect.width();
  }
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);

  int vspace = getBottom() - getTop() - getCompoundPaddingBottom() - getCompoundPaddingTop(); //剩余垂直可繪制文本空間大小
  int hspace = getRight() - getLeft() - getCompoundPaddingRight() - getCompoundPaddingLeft(); //剩余水平可繪制文本空間大小

  if (mCompoundDrawables != null) {
   if (mCompoundDrawables[LEFT] != null) {
    canvas.save();
    canvas.translate((hspace - mTextBounds.width()) / 2.0f + getPaddingLeft(),
      getCompoundPaddingTop() + (vspace - mDrawableLeftBounds.height()) / 2.0f);
    mCompoundDrawables[LEFT].draw(canvas);
    canvas.restore();
   }

   if (mCompoundDrawables[RIGHT] != null) {
    canvas.save();
    canvas.translate(getRight() - getLeft() - getPaddingRight() - (hspace - mTextBounds.width()) / 2.0f - mDrawableRightBounds.width(),
      getCompoundPaddingTop() + (vspace - mDrawableRightBounds.height()) / 2.0f);
    mCompoundDrawables[RIGHT].draw(canvas);
    canvas.restore();
   }

   if (mCompoundDrawables[TOP] != null) {
    canvas.save();
    canvas.translate(getCompoundPaddingLeft()
      + (hspace - mDrawableTopBounds.width()) / 2.0f, (vspace - mTextBounds.height()) / 2.0f + getPaddingTop());
    mCompoundDrawables[TOP].draw(canvas);
    canvas.restore();
   }

   if (mCompoundDrawables[BOTTOM] != null) {
    canvas.save();
    canvas.translate(getCompoundPaddingLeft()
        + (hspace - mDrawableBottomBounds.width()) / 2.0f,
      getBottom() - getTop() - getPaddingBottom() - (vspace - mTextBounds.height()) / 2.0f - mDrawableBottomBounds.height());
    mCompoundDrawables[BOTTOM].draw(canvas);
    canvas.restore();
   }
  }

  if (!TextUtils.isEmpty(mText)) {
   float startX = (hspace - mTextBounds.width()) / 2.0f + getCompoundPaddingLeft();
   //因為drawText以baseline為基準,因此需要向下移ascent
   float startY = (vspace - mTextBounds.height()) / 2.0f + getCompoundPaddingTop() - mTextPaint.getFontMetrics().ascent;
   mTextPaint.setColor(mTextColor.getColorForState(getDrawableState(), 0));
   canvas.drawText(mText, 0, mText.length(), startX, startY, mTextPaint);
  }
 }

 @Override
 protected void drawableStateChanged() {
  super.drawableStateChanged();

  if (mTextColor != null && mTextColor.isStateful()) {
   mTextPaint.setColor(mTextColor.getColorForState(getDrawableState(), 0));
  }

  if (mCompoundDrawables != null) {
   final int[] state = getDrawableState();
   for (Drawable dr : mCompoundDrawables) {
    if (dr != null && dr.isStateful() && dr.setState(state)) {
     invalidateDrawable(dr);
    }
   }
  }
 }

 public void setCompoundDrawablesWithIntrinsicBounds(@Nullable Drawable left,
              @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom) {
  if (left != null) {
   left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
  }
  if (right != null) {
   right.setBounds(0, 0, right.getIntrinsicWidth(), right.getIntrinsicHeight());
  }
  if (top != null) {
   top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
  }
  if (bottom != null) {
   bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
  }
  setCompoundDrawables(left, top, right, bottom);
 }

 public void setCompoundDrawables(@Nullable Drawable left, @Nullable Drawable top,
          @Nullable Drawable right, @Nullable Drawable bottom) {

  if (mCompoundDrawables == null) {
   mCompoundDrawables = new Drawable[4];
  } else {
   if (mCompoundDrawables[LEFT] != null && mCompoundDrawables[LEFT] != left) {
    mCompoundDrawables[LEFT].setCallback(null);
   }

   if (mCompoundDrawables[TOP] != null && mCompoundDrawables[TOP] != top) {
    mCompoundDrawables[TOP].setCallback(null);
   }

   if (mCompoundDrawables[RIGHT] != null && mCompoundDrawables[RIGHT] != right) {
    mCompoundDrawables[RIGHT].setCallback(null);
   }

   if (mCompoundDrawables[BOTTOM] != null && mCompoundDrawables[BOTTOM] != bottom) {
    mCompoundDrawables[BOTTOM].setCallback(null);
   }
  }

  if (left != null) {
   mDrawableLeftBounds = new Rect();
   left.copyBounds(mDrawableLeftBounds);
   left.setCallback(this);
   mCompoundDrawables[LEFT] = left;
  } else {
   mCompoundDrawables[LEFT] = null;
  }

  if (top != null) {
   mDrawableTopBounds = new Rect();
   top.copyBounds(mDrawableTopBounds);
   top.setCallback(this);
   mCompoundDrawables[TOP] = top;
  } else {
   mCompoundDrawables[TOP] = null;
  }

  if (right != null) {
   mDrawableRightBounds = new Rect();
   right.copyBounds(mDrawableRightBounds);
   right.setCallback(this);
   mCompoundDrawables[RIGHT] = right;
  } else {
   mCompoundDrawables[RIGHT] = null;
  }

  if (bottom != null) {
   mDrawableBottomBounds = new Rect();
   bottom.copyBounds(mDrawableBottomBounds);
   bottom.setCallback(this);
   mCompoundDrawables[BOTTOM] = bottom;
  } else {
   mCompoundDrawables[BOTTOM] = null;
  }

  invalidate();
  requestLayout();
 }

 public void setText(CharSequence text) {
  this.mText = text;

  invalidate();
  requestLayout();
 }

 public void setTextSize(float textSize) {
  this.mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, textSize, getResources().getDisplayMetrics());

  invalidate();
  requestLayout();
 }

 public void setTextColor(@ColorInt int textColor) {
  this.mTextColor = ColorStateList.valueOf(textColor);

  invalidate();
 }

 public void setTypeface(@Nullable Typeface tf) {
  if (mTextPaint.getTypeface() != tf) {
   mTextPaint.setTypeface(tf);

   requestLayout();
   invalidate();
  }
 }

 private void calcTextBounds() {
  mTextBounds = new Rect();

  if (TextUtils.isEmpty(mText)) return;

  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
   mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
  } else {
   int width = (int) Math.ceil(mTextPaint.measureText(mText.toString()));
   Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
   int height = (int) Math.ceil(fontMetrics.descent - fontMetrics.ascent);
   mTextBounds.set(0, 0, width, height);
  }
 }
}

看完上述內容,你們掌握Android如何使用圖文居中顯示控件的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

达州市| 唐河县| 丽江市| 卢氏县| 成安县| 融水| 留坝县| 县级市| 阳西县| 海城市| 延安市| 嫩江县| 沙雅县| 丰镇市| 蓬莱市| 丹凤县| 阿拉善右旗| 榆林市| 曲周县| 湘乡市| 赤水市| 新龙县| 华宁县| 雅安市| 巴南区| 武胜县| 阳信县| 宝山区| 读书| 石阡县| 陆川县| 凤台县| 沈阳市| 青海省| 常山县| 巴林左旗| 马公市| 万宁市| 山阴县| 平江县| 永吉县|