自定义view--打折标签view
Posted TC风之翼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义view--打折标签view相关的知识,希望对你有一定的参考价值。
自定义View
打折标签,数量增减可带动画效果。底部下载链接里的代码不是最新,本文才是。
学习心得
- 创建自定义view,首先分析所需的界面显示以及功能需求,然后确定自身所需的自定义属性,创建attr文件。
- 接下来就是绘制部分的设计了。根据界面效果,拆分或者组合出所需要的效果。要注意的是我一般先写onDraw方,然后据此编写onMeasure进行测量自适应操作。按照调用顺序onMeasure、onDraw、onLayout进行调用,由于布局的层级深度可能会多次调用onMeasure等。一般我们要编写的就是这三个。
- 一般都是在构造函数里创建一个init方法,来获取自定义属性(attr),在获取结束后记得a.recycle();释放掉。
- 注意:在onDraw不要创建新的实例,这样减少不必要的开支。
attr类
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="OffFlagView">
<attr name="offTopTitleTextSize" format="dimension"/>
<attr name="offCenterTitleTextSize" format="dimension"/>
<attr name="offTextBackgroundColor" format="color"/>
<attr name="offIsAnim" format="boolean"/>
</declare-styleable>
</resources>
- view类
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* author: tc
* date: 2015/12/11 & 16:04
* version 1.0
* description 折扣标签
* modify by
*/
public class OffFlagView extends View
public static final String TAG = OffFlagView.class.getSimpleName();
private int mTextBackgroundColor = -1;
private String mTopText = "00%";
private String mCenterText = "OFF";
/**
* op文本的大小
*/
private int mTopTitleTextSize = 0;
/**
* center文本的大小
*/
private int mCenterTitleTextSize = 0;
private TextPaint mPaint;
/**
* 绘制时控制文本绘制的范围
*/
private Rect mBound;
/**
* 是否启用数值变化动画
*/
private boolean mIsAnim;
private Path mPath;
private int mPaddingTop;
private int mPaddingLeft;
private int mPaddingRight;
private int mPaddingBottom;
public OffFlagView(Context context)
this(context, null);
public OffFlagView(Context context, AttributeSet attrs)
this(context, attrs, 0);
public OffFlagView(Context context, AttributeSet attrs, int defStyleAttr)
this(context, attrs, defStyleAttr, 0);
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public OffFlagView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
super(context, attrs, defStyleAttr, defStyleRes);
initView(attrs);
public int getTopValue()
return mTopValue;
public void setTopValue(int topValue)
this.mTopText = String.valueOf(topValue + "%");
this.mTopValue = topValue;
if (mIsAnim)
this.startAnimation(anim);//动画形式的动态显示数值
public String getCenterText()
return mCenterText;
public void setCenterText(String centerText)
this.mCenterText = centerText;
public int getTextBackgroundColor()
return mTextBackgroundColor;
public void setTextBackgroundColor(int textBackgroundColor)
this.mTextBackgroundColor = textBackgroundColor;
public int getTopTitleTextSize()
return mTopTitleTextSize;
public void setTopTitleTextSize(int topTitleTextSize)
this.mTopTitleTextSize = topTitleTextSize;
public int getCenterTitleTextSize()
return mCenterTitleTextSize;
public void setCenterTitleTextSize(int centerTitleTextSize)
this.mCenterTitleTextSize = centerTitleTextSize;
public boolean isIsAnim()
return mIsAnim;
public void setIsAnim(boolean mIsAnim)
this.mIsAnim = mIsAnim;
private void initView(AttributeSet attrs)
if (attrs != null)
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.OffFlagView);
mTopTitleTextSize = a.getDimensionPixelSize(R.styleable.OffFlagView_offTopTitleTextSize, 0);
mCenterTitleTextSize = a.getDimensionPixelSize(R.styleable.OffFlagView_offCenterTitleTextSize, 0);
mTextBackgroundColor = a.getResourceId(R.styleable.OffFlagView_offTextBackgroundColor, -1);
mIsAnim = a.getBoolean(R.styleable.OffFlagView_offIsAnim, false);
a.recycle();
/**
* 获得绘制文本的宽和高
*/
mPaint = new TextPaint();
mBound = new Rect();
mPaint.setTextSize(mTopTitleTextSize);
mPaint.getTextBounds(mTopText, 0, mTopText.length(), mBound);
mPath = new Path();
anim = new BarAnimation();
anim.setDuration(1000);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY)
width = widthSize;
else
mPaint.setTextSize(mTopTitleTextSize);
if (mTopText.length() >= 3)
mPaint.getTextBounds(mTopText, 0, mTopText.length(), mBound);
else
mPaint.getTextBounds("00%", 0, 3, mBound);//可能打折的数值是4%这种2位长度,所以宽度计算需要调整,避免小于OFF的宽度。
float textWidth = mBound.width();
mPaddingLeft = getPaddingLeft() <= 0 ? dip2px(getContext(), 2) : getPaddingLeft();
mPaddingRight = getPaddingRight() <= 0 ? dip2px(getContext(), 2) : getPaddingRight();
width = (int) (mPaddingLeft + textWidth + mPaddingRight);
if (heightMode == MeasureSpec.EXACTLY)
height = heightSize;
else
mPaint.setTextSize(mTopTitleTextSize);
mPaint.getTextBounds(mTopText, 0, mTopText.length(), mBound);
float textHeight = mBound.height();
mPaddingTop = getPaddingTop() <= 0 ? dip2px(getContext(), 5) : getPaddingTop();
mPaddingBottom = getPaddingBottom();
height = (int) (mPaddingTop * 2 + textHeight * 3 + mPaddingBottom);
setMeasuredDimension(width, height);
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
int threeCanvasHeight = canvasHeight / 3;
if (mTopTitleTextSize <= 0)
mTopTitleTextSize = dip2px(getContext(), 10);
if (mCenterTitleTextSize <= 0)
mCenterTitleTextSize = dip2px(getContext(), 10);
if (mTextBackgroundColor != -1)
mPaint.setColor(getContext().getResources().getColor(mTextBackgroundColor));
mPaint.setAntiAlias(true);//无齿轮感
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);//设置为抗锯齿
mPath.moveTo(0, 0);// 此点为多边形的起点
mPath.lineTo(canvasWidth, 0);
mPath.lineTo(canvasWidth, threeCanvasHeight * 2 + mPaddingTop);
mPath.lineTo(0, threeCanvasHeight * 2 + mPaddingTop);
mPath.close(); // 使这些点构成封闭的多边形
canvas.drawPath(mPath, mPaint);
mPath.reset();
mPath.moveTo(0, threeCanvasHeight * 2 + mPaddingTop);// 此点为多边形的起点
mPath.lineTo(canvasWidth / 2, threeCanvasHeight * 2 + mPaddingTop);
mPath.lineTo(0, canvasHeight);
mPath.close(); // 使这些点构成封闭的多边形
canvas.drawPath(mPath, mPaint);
mPath.reset();
mPath.moveTo(canvasWidth / 2, threeCanvasHeight * 2 + mPaddingTop);// 此点为多边形的起点
mPath.lineTo(canvasWidth, threeCanvasHeight * 2 + mPaddingTop);
mPath.lineTo(canvasWidth, canvasHeight);
mPath.close(); // 使这些点构成封闭的多边形
canvas.drawPath(mPath, mPaint);
mPaint.reset();
mPaint.setTextSize(mTopTitleTextSize);
mPaint.setColor(getContext().getResources().getColor(R.color.white));
mPaint.setAntiAlias(true);//无齿轮感
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);//设置为抗锯齿
mPaint.setTypeface(Typeface.DEFAULT_BOLD);//加粗
//设置居中对齐
mPaint.setTextAlign(Paint.Align.CENTER);//设置居中对齐
canvas.save();
canvas.translate(canvasWidth / 2, threeCanvasHeight / 2 + mPaddingTop);
canvas.drawText(mTopText, 0, 0, mPaint);
canvas.restore();
mPaint.setTextSize(mCenterTitleTextSize);
mPaint.setTextAlign(Paint.Align.CENTER);//设置居中对齐
canvas.save();
canvas.translate(canvasWidth / 2, threeCanvasHeight + threeCanvasHeight / 2 + mPaddingTop);
canvas.drawText(mCenterText, 0, 0, mPaint);
canvas.restore();
private BarAnimation anim;
private int mTopValue;//正在动画中的打折数值
public class BarAnimation extends Animation
/**
* Initializes expand collapse animation, has two types, collapse (1) and expand (0).
*/
public BarAnimation()
@Override
protected void applyTransformation(float interpolatedTime, Transformation t)
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f)
mTopText = String.valueOf((int) (interpolatedTime * mTopValue) + "%");
else
mTopText = String.valueOf(mTopValue + "%");
postInvalidate();
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
private int dip2px(Context context, final float dpValue)
float density = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * density + 0.5f);
源码下载地址:http://download.csdn.net/detail/u010716109/9424223
以上是关于自定义view--打折标签view的主要内容,如果未能解决你的问题,请参考以下文章