在android的xml布局中,几百上千行的xml文件是常事。布局文件的增大一定程度上增加了视图编写的复杂度,而且如果视图的嵌套越深android在加载视图时的性能也会越差,甚至会出现一些低端设备内存不足而崩溃等奇异情况。
对性能要求比较高或适配终端机型广泛的应用,通过编写自定视图控件来优化应用是常用的方式。今天我实现一个类似appstore的更新应用个数提醒的实例,来探讨自画视图的应用场合。
或许很多人一看到上图就会想到用FrameLayout来实现,但一个复杂的视图想添加这种功能往往会非常复杂或有很多的顾虑,而且framelayout的过多使用又会陷入优化的陷阱。所以我用一个折中而且比较保险的方法,最小的修改视图布局结合自绘方式来实现这种功能。下面是最终截图
5个底部tab通过RadioGroup结合RadioButton来实现,如果您不清楚怎么实现该视图请参阅《RadioGroup&RadioButton小技巧 》。红圆和数字"8"通过继承RadioGroup的类MyRadioGroup
重载dispatchDraw方法绘制,再用MyRadioGroup 替换布局里的RadioGroup。为什么重载的不是onDraw而是dispatchDraw呢?下面先来看看dispatchDraw的描述
在onDraw绘制您画的元素在原布局元素的下面,而我们是想把自己画的元素覆盖在原布局元素的上面,所以得用dispatchDraw。好了一些思路讲完了上代码
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.RadioGroup; /** * 转载请注明 http://hemowolf.iteye.com */ public class MyRadioGroup extends RadioGroup { Drawable mBg; Paint mPaintText; @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (mBg == null) mBg = getResources().getDrawable(R.drawable.tab_unread_bg); if(mPaintText==null){ mPaintText=new Paint(); mPaintText.setTextSize(18f); mPaintText.setColor(Color.WHITE); mPaintText.setFakeBoldText(true); } //获取字体所占宽度和高度 String text="8"; Rect rect= new Rect(); mPaintText.getTextBounds(text, 0, text.length(), rect); int textWidth = rect.width(), textHeight = rect.height(); int bgWidth = textWidth+30 > mBg.getIntrinsicWidth() ? textWidth +30: mBg.getIntrinsicWidth() , bgHeight = textHeight > mBg.getIntrinsicHeight() ? textHeight : mBg.getIntrinsicHeight(); int bgX = this.getWidth() + this.getPaddingLeft() - bgWidth ,bgY = this.getPaddingTop(); mBg.setBounds(bgX, bgY, bgX + bgWidth, bgY + bgHeight); mBg.draw(canvas); int x = bgX + (bgWidth - textWidth) / 2 - rect.left, y = bgY + (bgHeight - textHeight) / 2 - rect.top; canvas.drawText(text, x, y, mPaintText); } public MyRadioGroup(Context context) { super(context); } public MyRadioGroup(Context context, AttributeSet attrs) { super(context, attrs); } }
详细的实现请参考实例。