在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);
}
}
详细的实现请参考实例。