底部导航栏我门一般的实现方式就是
RadioGroup 和RadioButton这种组合.但是这样会有很多弊端.比如有个消息提示.比如要随时改变图标
/**
* Created by sdx on 2016/12/28.
* 底部导航栏图标
*/
public class TabView extends View {
private String mText;
private Bitmap mBitmap;
private Bitmap mClickBitmap;
/**
* 字体的大小.默认是12
*/
private float textSize = 12f;
private Rect tvRect;
private Paint tvPaint;
private RectF ivRect;
private int padding;
private int ivWidth;
private int color;
private int msgCount;
/**
* 条目普通的颜色
*/
private static final int normalColor = 0X999999;
/**
* 条目点击的颜色
*/
private static final int clickColor = 0XEF6160;
/**
* 消息的背景颜色(消息的数字是白色)
*/
private static final int msgColor = 0XEF6160;
/**
* 设置当前的条目是否是点击状态
*/
private boolean isClick = false;
public TabView(Context context) {
this(context, null);
}
public TabView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TabView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TabView);
int indexCount = typedArray.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int index = typedArray.getIndex(i);
switch (index) {
case R.styleable.TabView_tab_text:
mText = typedArray.getString(index);
break;
case R.styleable.TabView_tab_image:
BitmapDrawable mBitmapDraawable = (BitmapDrawable) typedArray.getDrawable(index);
mBitmap = mBitmapDraawable.getBitmap();
break;
case R.styleable.TabView_tab_text_size:
textSize = typedArray.getDimension(index, 12);
break;
case R.styleable.TabView_tab_click_image:
BitmapDrawable clickDrawable = (BitmapDrawable) typedArray.getDrawable(index);
mClickBitmap = clickDrawable.getBitmap();
break;
}
}
typedArray.recycle();
tvRect = new Rect();
tvPaint = new Paint();
reText();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
padding = UIUtils.dp2px(getContext(), 4);
int width = getMeasuredWidth() - padding * 2;
int height = getMeasuredHeight() - padding * 2 - tvRect.height();
ivWidth = Math.min(width, height);
int left = getMeasuredWidth() / 2 - ivWidth / 2;
int top = (getMeasuredHeight() - tvRect.height() - ivWidth) / 2;
ivRect = new RectF(left, top, left + ivWidth, top + ivWidth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isClick) {
drawBitmap(canvas, mClickBitmap);
color = clickColor;
} else {
drawBitmap(canvas, mBitmap);
color = normalColor;
}
drawText(canvas);
if (msgCount > 0) {
drawMessage(canvas);
}
}
/**
* 绘制消息
*
* @param canvas
*/
private void drawMessage(Canvas canvas) {
//数字画笔内容大小等创建
Paint textPaint = new Paint();
Rect textRect = new Rect();
String text = msgCount > 99 ? "99+" : msgCount + "";
int size ;
if (text.length() == 1) {
size = UIUtils.dp2px(getContext(), 10);
} else if (text.length() == 2) {
size = UIUtils.dp2px(getContext(), 9);
} else {
size = UIUtils.dp2px(getContext(), 7);
}
textPaint.setColor(Color.WHITE);
textPaint.setFakeBoldText(true);
textPaint.setAntiAlias(true);
textPaint.setTextSize(size);
textPaint.setTypeface(Typeface.MONOSPACE);
textPaint.getTextBounds(text, 0, text.length(), textRect);
textPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
//画圆
int width = UIUtils.dp2px(getContext(), 17);
Paint paint = new Paint();
paint.setColor(msgColor);
paint.setAlpha(255);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
RectF messageRectF = new RectF(ivRect.right - width / 2, ivRect.top, ivRect.right + width / 2, ivRect.top + width);
canvas.drawOval(messageRectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
//画数字
float x = messageRectF.right - messageRectF.width() / 2f;
float y = messageRectF.bottom - messageRectF.height() / 2f - fontMetrics.descent + (fontMetrics.descent - fontMetrics.ascent) / 2;
canvas.drawText(text, x, y, textPaint);
}
private void drawBitmap(Canvas canvas, Bitmap bitmap) {
Bitmap bitmapTem = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvasTem = new Canvas(bitmapTem);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
canvasTem.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
canvasTem.drawOval(ivRect, paint);
canvasTem.drawBitmap(bitmap, null, ivRect, paint);
canvas.drawBitmap(bitmapTem, 0, 0, null);
}
private void drawText(Canvas canvas) {
tvPaint.setColor(color);
tvPaint.setAlpha(255);
float x = getMeasuredWidth() / 2 - tvRect.width() / 2;
float y = ivRect.bottom + tvRect.height();
canvas.drawText(mText, x, y, tvPaint);
}
/**
* 重绘
*/
private void invalidateView() {
if (Looper.getMainLooper() == Looper.myLooper()) {
invalidate();
} else {
postInvalidate();
}
}
public void setClick(boolean isClick) {
this.isClick = isClick;
invalidateView();
}
/**
* 设置一个网络的地址.加载出来bitmap
*
* @param src
*/
private String lastSrc;
public void setSrc(String src) {
if (src == null) return;
//如果两次传进来的地址一样.就没必要重新绘制bitmap
if (src.equals(lastSrc)) return;
lastSrc = src;
Observable.just(src).observeOn(Schedulers.io()).subscribe(new Action1<String>() {
@Override
public void call(String s) {
try {
mBitmap = mClickBitmap = Picasso.with(getContext()).load(s).transform(new Transformation() {
@Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
@Override
public String key() {
return "circleImageTransformation";
}
}).get();
invalidateView();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
* 设置消息的数量
*
* @param count 消息的数量
*/
public void setMessage(int count) {
this.msgCount = count;
invalidateView();
}
/**
* 设置文字
*
* @param text tab的文本
*/
public void setText(String text) {
this.mText = text;
reText();
invalidateView();
}
private void reText() {
tvPaint.setTextSize(textSize);
tvPaint.getTextBounds(mText, 0, mText.length(), tvRect);
tvPaint.setAntiAlias(true);
}
private final static String KEY_NORMAL = "key_normal";
private final static String KEY_STATE = "key_state";
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putBoolean(KEY_STATE, isClick);
bundle.putParcelable(KEY_NORMAL, super.onSaveInstanceState());
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
isClick = bundle.getBoolean(KEY_STATE);
super.onRestoreInstanceState(bundle.getParcelable(KEY_NORMAL));
} else {
super.onRestoreInstanceState(state);
}
}
/**
* 设置背景图片
*
* @param normal 普通状态的drawable
* @param click 点击状态的drawable
*/
public void setImageView(final int normal, final int click) {
Observable.just(normal).observeOn(Schedulers.io()).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
try {
mBitmap = Picasso.with(getContext()).load(normal).get();
mClickBitmap = Picasso.with(getContext()).load(click).get();
invalidateView();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
}
<declare-styleable name="TabButton">
<!--初始显示的图标-->
<attr name="image" format="reference"/>
<!--选中之后显示的图标-->
<attr name="clickimage" format="reference"/>
<!--选中之后显示的颜色-->
<attr name="clickcolor" format="color"/>
<attr name="normalcolor" format="color"/>
<!--图标下显示的文字,不要太长!-->
<attr name="text" format="string"/>
<!--文字的大小-->
<attr name="text_size" format="dimension"/>
</declare-styleable>
<com.ui.widgets.TabView
android:id="@+id/tab_my"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:tab_click_image="@drawable/ic_tab_mine_s"
app:tab_image="@drawable/ic_tab_mine_f"
app:tab_text="我的"
app:tab_text_size="12sp"
/>
参考: http://blog.csdn.net/tyzlmjj/article/details/47186249