Android 自己画View -- drawable.draw 以及 drawText

原创 2015年11月18日 22:20:35
今天遇到一个要自己画View的问题,  其实可以通过多个View 组合来实现, 但是不是太好, 于是就自己画了
效果图如下:


其实可以一个ImageView  在加TextView TranslationY来解决
用translation来解决的画, 需要自己设置 minHeight, 防止 移动的过程中 TextView被移到外面去了看不见

ok 下面来说说, 自己画的画 该怎么解决,
很明显, 需要画一个图片 和一个 Text
1. 画图 Drawable.draw(canvas);
     需要注意的是,  我们的设计给了两个状态的图,  一个是按压状态下的一个是正常状态下得.
     所以我们在获取Drawable 的是时候 转成BitMapDrawable 再来获取bitmap 是不可取的.
     其实drawable 它本身有一个 draw 方法, 只要我们调用 setBounds 设置范围, 在调用draw 方法就可以直接画了
2. 画 Text 
void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) 
x 代表  左上角顶点位置 x坐标
y 代表的是 基准线的位置,  注意这不是左上角顶点y坐标
所以在 drawText的时候需要注意 位置的问题

ok 下面直接上代码: 
public class ImgWithNumTipsView extends View {
    public static final String TAG = "IconImgWithTipNumView";

    public ImgWithNumTipsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttr(attrs);
        initView();
    }

    public ImgWithNumTipsView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttr(attrs);
        initView();
    }

    private int mTipsTextColor;
    private int mImgScrId;
    private int mTipsNum;
    private int mTipsTextSize;
    private int textMarginLeftSize;

    private Drawable mDrawable;
    private Paint mTxtPain;
    private String mTipsString;

    private void initAttr(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ImageNumTipsView);
        mTipsTextColor = typedArray.getColor(R.styleable.ImageNumTipsView_numTipsTextColor, 0XFFFFFFFF);
        mImgScrId = typedArray.getResourceId(R.styleable.ImageNumTipsView_imgSrc, -1);

        int defaultTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 11, getResources().getDisplayMetrics());
        int defaultMarginLeftSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());

        mTipsTextSize = typedArray.getDimensionPixelSize(R.styleable.ImageNumTipsView_numTipsTextSize, defaultTextSize);
        textMarginLeftSize = typedArray.getDimensionPixelSize(R.styleable.ImageNumTipsView_numTipsTextMarginLeft, defaultMarginLeftSize);

        mTipsNum = typedArray.getInt(R.styleable.ImageNumTipsView_numTipsText, 10);
        mTipsString = mTipsNum + "";

        if (mImgScrId == -1) {
            throw new RuntimeException("ImgScrId is error");
        }
    }

    private void initView() {
        mTxtPain = new Paint();
        mTxtPain.setColor(mTipsTextColor);
        mTxtPain.setFlags(Paint.ANTI_ALIAS_FLAG);
        mTxtPain.setTextSize(mTipsTextSize);
        setDrawable(getResources().getDrawable(mImgScrId));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mDrawable.draw(canvas);

        int textLeft = mDrawable.getIntrinsicWidth() + textMarginLeftSize;
        int textTop = 0;
        int textRight = textLeft + getStringWidth(mTipsString);
        int textBottom = getStringHeight();

        Rect textRect = new Rect(textLeft, textTop, textRight, textBottom);
        Paint.FontMetricsInt fontMetrics = mTxtPain.getFontMetricsInt();
        int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;

        canvas.drawText(mTipsString, textLeft, baseline, mTxtPain);
    }

    private int getStringWidth(String str) {
        return (int) mTxtPain.measureText(str);
    }

    private int getStringHeight() {
        Paint.FontMetrics fr = mTxtPain.getFontMetrics();
        return (int) Math.ceil(fr.descent - fr.top) + 2;  //ceil() 函数向上舍入为最接近的整数。
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = getStringWidth(mTipsString) + mDrawable.getIntrinsicWidth() + textMarginLeftSize;
        int heightSize = getStringHeight() / 2 + mDrawable.getIntrinsicWidth();

        widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }

    public int getTipsNum() {
        return mTipsNum;
    }

    public void setTipsNum(int tipsNum) {
        mTipsNum = tipsNum;
        if (mTipsNum < 999) {
            mTipsString = "" + tipsNum;
        } else {
            mTipsString = "999+";
        }
        requestLayout();
    }

    public void setTipsText(String text) {
        mTipsString = text;
        requestLayout();
        requestLayout();
    }

    public void setTipsTextColor(int color) {
        mTipsTextColor = color;
        mTxtPain.setColor(color);
        invalidate();
    }

    /**
     * @param sizePx 像素为单位
     */
    public void setTipsTextSize(int sizePx) {
        mTipsTextSize = sizePx;
        mTxtPain.setTextSize(sizePx);
        requestLayout();
    }

    public void setDrawable(Drawable drawable) {
        mDrawable = drawable;
        Rect drawableRect = new Rect(0, getStringHeight() / 2, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight() + getStringHeight() / 2);
        mDrawable.setBounds(drawableRect);
        requestLayout();
    }

}

一些总结:
mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight() 可以获得 drawable的真实高度
mTxtPain.measureText(str); 可以获取 画出来的 字符串的宽度

Paint.FontMetrics fr = mTxtPain.getFontMetrics();
Math.ceil(fr.descent - fr.top) + 2;  //可以获得 话来着的Text 所占的高度

invalidate(); 会重画, 但是不会重新布局, 不会重新测量
requestLayout(); 会重新布局, 重新测量

普通图片的drawable 可以强转成 bitmapDrawable 
selector 的drawable不可以, 他不是 bitmapDrawable

mTxtPain.setFlags(Paint.ANTI_ALIAS_FLAG);// 设置抗锯齿
mTxtPain.setTextSize(mTipsTextSize);// 这里设置的 像素大小, 不是 sp

关于 DrawText 的一些文章:
Drawable、Bitmap、Canvas和Paint的关系以及部分使用方法

Android Canvas drawText相关:


















Android 如何将Drawable和Bitmap画到屏幕上

Drawable画到屏幕上:protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.on...
  • GaoMatrix
  • GaoMatrix
  • 2011年06月14日 15:34
  • 11084

Android Drawable、Bitmap、Canvas和Paint的区别

很多朋友刚刚开始学习Android平台,对于Drawable、Bitmap、Canvas和Paint它们之间的概念不是很清楚,其实它们除了Drawable外早在Sun的J2ME中就已经出现了,但是在A...
  • GaoMatrix
  • GaoMatrix
  • 2011年06月13日 19:44
  • 11780

Android Drawable 那些不为人知的高效用法

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43752383,本文出自:【张鸿洋的博客】1、概述Drawable在我们平时的开发...
  • lmj623565791
  • lmj623565791
  • 2015年02月26日 09:21
  • 161964

本示例绘制位图,分两种方式1. 绘制Bitmap对象2.使用Drawable.draw方法绘制位图

  • 2013年06月14日 22:42
  • 421KB
  • 下载

Python图像处理库PIL的ImageDraw模块介绍

ImageDraw模块提供了图像对象的简单2D绘制。用户可以使用这个模块创建新的图像,注释或润饰已存在图像,为web应用实时产生各种图形。 PIL中一个更高级绘图库见The aggdraw Modul...
  • icamera0
  • icamera0
  • 2016年02月26日 08:11
  • 13436

【python图像处理】几何图形的绘制与文字的绘制(ImageDraw类详解)

python PIL图像处理模块中的ImageDraw类支持各种几何图形的绘制和文本的绘制,如直线、椭圆、弧、弦、多边形以及文字等。...
  • guduruyu
  • guduruyu
  • 2017年05月05日 16:01
  • 3488

Python PIL ImageDraw 和ImageFont模块学习

ImageDraw      1、模块引入 import ImageDraw      2、ImageDraw.Draw(image) 创建一个可用来对image进行操作的对象。对所有即将使用Ima...
  • Dou_CO
  • Dou_CO
  • 2013年12月30日 14:32
  • 20738

【图像处理】python-ImageDraw

ImageDraw 模块 ImageDraw模块是对Image对象进行简单的二维图像操作的模块。 1.  基本的模块导入,读入图片,画图:      import Image, ImageDraw...
  • chenriwei2
  • chenriwei2
  • 2014年12月22日 09:33
  • 4431

Python PIL ImageDraw 和ImageFont模块学习

 转载地址: ImageDraw  新建一个空白图片为本文作示例,新建空白文件的方法 见Image模块,Image.new: [python] view plain...
  • vola9527
  • vola9527
  • 2014年09月01日 22:54
  • 3931

Android Drawable 详解

详细介绍了 Android 中一些常用 Drawable 的使用方法。
  • ZhangYafengCPP
  • ZhangYafengCPP
  • 2016年09月22日 11:36
  • 1849
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 自己画View -- drawable.draw 以及 drawText
举报原因:
原因补充:

(最多只允许输入30个字)