自定义底部导航栏图标

底部导航栏我门一般的实现方式就是 

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"
            />




因为项目里边用到了picasso和Rxjava所以这里就直接用了.其实就是在子线程获取到网络图片的bitmap,然后绘制到view上;

参考: http://blog.csdn.net/tyzlmjj/article/details/47186249


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值