Android图文居中显示控件使用方法详解
最近项目中用到了文字图标的按钮,需要居中显示,如果用TextView实现的方式,必须同时设置padding和drawablePadding。如下:
这种方式需要自己做精确计算。比较麻烦。另外还有一种方式就是用线性布局包裹ImageView和TextView,但这样会增加布局层级。于是自己封装了一个控件DrawableCenterTextView。
attrs.xml文件中定义属性:
对应的Java代码如下:
publicclassDrawableCenterTextViewextendsView{
staticfinalintLEFT=0;
staticfinalintTOP=1;
staticfinalintRIGHT=2;
staticfinalintBOTTOM=3;
privateCharSequencemText;
privateColorStateListmTextColor;
privatefloatmTextSize;
privateintmTextStyle;
privateintmDrawablePadding;
privateDrawable[]mCompoundDrawables;
privateRectmTextBounds;
privateRectmDrawableLeftBounds;
privateRectmDrawableTopBounds;
privateRectmDrawableRightBounds;
privateRectmDrawableBottomBounds;
privateTextPaintmTextPaint;
publicDrawableCenterTextView(Contextcontext){
this(context,null);
}
publicDrawableCenterTextView(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
publicDrawableCenterTextView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
DrawabledrawableLeft=null,drawableTop=null,drawableRight=null,drawableBottom=null;
TypedArrayta=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=newTextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density=getResources().getDisplayMetrics().density;
mTextPaint.setTextSize(mTextSize);
setTypeface(Typeface.create(Typeface.DEFAULT,mTextStyle));
setCompoundDrawablesWithIntrinsicBounds(drawableLeft,drawableTop,drawableRight,drawableBottom);
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
intwidthMode=MeasureSpec.getMode(widthMeasureSpec);
intheightMode=MeasureSpec.getMode(heightMeasureSpec);
intwidthSize=MeasureSpec.getSize(widthMeasureSpec);
intheightSize=MeasureSpec.getSize(heightMeasureSpec);
intwidth;
intheight;
//计算文本范围
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);
}
publicintgetCompoundPaddingTop(){
if(mCompoundDrawables==null||mCompoundDrawables[TOP]==null){
returngetPaddingTop();
}else{
Rectrect=newRect();
mCompoundDrawables[TOP].copyBounds(rect);
returngetPaddingTop()+mDrawablePadding+rect.height();
}
}
publicintgetCompoundPaddingBottom(){
if(mCompoundDrawables==null||mCompoundDrawables[BOTTOM]==null){
returngetPaddingBottom();
}else{
Rectrect=newRect();
mCompoundDrawables[BOTTOM].copyBounds(rect);
returngetPaddingBottom()+mDrawablePadding+rect.height();
}
}
publicintgetCompoundPaddingLeft(){
if(mCompoundDrawables==null||mCompoundDrawables[LEFT]==null){
returngetPaddingLeft();
}else{
Rectrect=newRect();
mCompoundDrawables[LEFT].copyBounds(rect);
returngetPaddingLeft()+mDrawablePadding+rect.width();
}
}
publicintgetCompoundPaddingRight(){
if(mCompoundDrawables==null||mCompoundDrawables[RIGHT]==null){
returngetPaddingRight();
}else{
Rectrect=newRect();
mCompoundDrawables[RIGHT].copyBounds(rect);
returngetPaddingRight()+mDrawablePadding+rect.width();
}
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
intvspace=getBottom()-getTop()-getCompoundPaddingBottom()-getCompoundPaddingTop();//剩余垂直可绘制文本空间大小
inthspace=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)){
floatstartX=(hspace-mTextBounds.width())/2.0f+getCompoundPaddingLeft();
//因为drawText以baseline为基准,因此需要向下移ascent
floatstartY=(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
protectedvoiddrawableStateChanged(){
super.drawableStateChanged();
if(mTextColor!=null&&mTextColor.isStateful()){
mTextPaint.setColor(mTextColor.getColorForState(getDrawableState(),0));
}
if(mCompoundDrawables!=null){
finalint[]state=getDrawableState();
for(Drawabledr:mCompoundDrawables){
if(dr!=null&&dr.isStateful()&&dr.setState(state)){
invalidateDrawable(dr);
}
}
}
}
publicvoidsetCompoundDrawablesWithIntrinsicBounds(@NullableDrawableleft,
@NullableDrawabletop,@NullableDrawableright,@NullableDrawablebottom){
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);
}
publicvoidsetCompoundDrawables(@NullableDrawableleft,@NullableDrawabletop,
@NullableDrawableright,@NullableDrawablebottom){
if(mCompoundDrawables==null){
mCompoundDrawables=newDrawable[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=newRect();
left.copyBounds(mDrawableLeftBounds);
left.setCallback(this);
mCompoundDrawables[LEFT]=left;
}else{
mCompoundDrawables[LEFT]=null;
}
if(top!=null){
mDrawableTopBounds=newRect();
top.copyBounds(mDrawableTopBounds);
top.setCallback(this);
mCompoundDrawables[TOP]=top;
}else{
mCompoundDrawables[TOP]=null;
}
if(right!=null){
mDrawableRightBounds=newRect();
right.copyBounds(mDrawableRightBounds);
right.setCallback(this);
mCompoundDrawables[RIGHT]=right;
}else{
mCompoundDrawables[RIGHT]=null;
}
if(bottom!=null){
mDrawableBottomBounds=newRect();
bottom.copyBounds(mDrawableBottomBounds);
bottom.setCallback(this);
mCompoundDrawables[BOTTOM]=bottom;
}else{
mCompoundDrawables[BOTTOM]=null;
}
invalidate();
requestLayout();
}
publicvoidsetText(CharSequencetext){
this.mText=text;
invalidate();
requestLayout();
}
publicvoidsetTextSize(floattextSize){
this.mTextSize=TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,textSize,getResources().getDisplayMetrics());
invalidate();
requestLayout();
}
publicvoidsetTextColor(@ColorIntinttextColor){
this.mTextColor=ColorStateList.valueOf(textColor);
invalidate();
}
publicvoidsetTypeface(@NullableTypefacetf){
if(mTextPaint.getTypeface()!=tf){
mTextPaint.setTypeface(tf);
requestLayout();
invalidate();
}
}
privatevoidcalcTextBounds(){
mTextBounds=newRect();
if(TextUtils.isEmpty(mText))return;
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.Q){
mTextPaint.getTextBounds(mText,0,mText.length(),mTextBounds);
}else{
intwidth=(int)Math.ceil(mTextPaint.measureText(mText.toString()));
Paint.FontMetricsfontMetrics=mTextPaint.getFontMetrics();
intheight=(int)Math.ceil(fontMetrics.descent-fontMetrics.ascent);
mTextBounds.set(0,0,width,height);
}
}
}
感谢大家的支持,如有错误请指正。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。