自定义view--打折标签view

Posted TC风之翼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义view--打折标签view相关的知识,希望对你有一定的参考价值。

自定义View

打折标签,数量增减可带动画效果。底部下载链接里的代码不是最新,本文才是。

  • 学习心得

    1. 创建自定义view,首先分析所需的界面显示以及功能需求,然后确定自身所需的自定义属性,创建attr文件。
    2. 接下来就是绘制部分的设计了。根据界面效果,拆分或者组合出所需要的效果。要注意的是我一般先写onDraw方,然后据此编写onMeasure进行测量自适应操作。按照调用顺序onMeasure、onDraw、onLayout进行调用,由于布局的层级深度可能会多次调用onMeasure等。一般我们要编写的就是这三个。
    3. 一般都是在构造函数里创建一个init方法,来获取自定义属性(attr),在获取结束后记得a.recycle();释放掉。
    4. 注意:在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的主要内容,如果未能解决你的问题,请参考以下文章

自定义View(1)

自定义View之onMeasure

是否可以将 Chrome 自定义标签作为 View 对象

自定义View都写不好还做什么Android开发

自定义View 篇一--------《自定义View流程分析》

自定义View之MenuItemView