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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。