转载自http://blog.csdn.net/chen930724/article/details/49913969
今天遇到一个要自己画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;
- }
-
- @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();
- }
-
-
-
-
- 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相关: