我的第一个自定义View

直接上代码,做个学习笔记好了。

/**
 * Created by Jimbray  .
 * on 2016/7/12
 * Email: jimbray16@gmail.com
 * Description: 这是我第一个真正意义上的自定义View
 */
public class MyFirstProgressbar extends View {

    //max progress 虽然注释写了,但是还是不解释
    private int mMaxProgress = 100;

    // current progress
    private int mCurrentProgress;

    //progress bar 背景颜色
    private int mBackgroundColor;

    //progress bar 进度条颜色
    private int mProgressColor;

    //progress bar 进度条高度
    private float mProgressBarheight;

    //progress bar 背景高度
    private float mBackgroundHeight;

    //设置默认值
    //默认progress bar 背景颜色
    private final int default_background_color = Color.rgb(204, 204, 204);
    //默认progress bar 进度条颜色
    private final int default_progressbar_color = Color.rgb(66, 145, 241);
    //默认 pregress bar 背景高度
    private float default_background_height;
    //默认 porgress 进度条高度
    private float default_progressbar_height;
    //默认progress bar 背景宽度(最小宽度)
    private final float default_background_width = dp2px(45.f);

    //画笔
    private Paint mBackgroundPaint, mProgressbarPaint;

    //progress 需要draw 的矩形区域
    private RectF mBackgroundRectF = new RectF(0, 0, 0, 0);
    private RectF mProgressbarRectF = new RectF(0, 0, 0, 0);


    public MyFirstProgressbar(Context context) {
        super(context);
        init(context, null, 0);
    }

    public MyFirstProgressbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public MyFirstProgressbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);

    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        default_background_height = dp2px(1.0f);
        default_progressbar_height = dp2px(1.5f);
        //progress bar 背景高度 比 progress bar 进度条高度 矮啊

        //都是用默认值,没有把这些数值抛出去做属性
        mBackgroundHeight = default_background_height;
        mProgressBarheight = default_progressbar_height;

        mBackgroundColor = default_background_color;
        mProgressColor = default_progressbar_color;

        initPainters();
    }

    /**
     * 初始化 画笔 Paint
     */
    private void initPainters() {
        mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundPaint.setColor(mBackgroundColor);

        mProgressbarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressbarPaint.setColor(mProgressColor);
    }

    /**
     * 重载 函数
     * @return view 的推荐最小宽度
     * 修改为 progress bar 背景的默认高度
     */
    @Override
    protected int getSuggestedMinimumWidth() {
        return (int) default_background_width;
    }

    /**
     * 重载 函数
     * @return view 的推荐最小高度
     * 修改为 progress bar 的默认高度 (娶个最高的吧,不然高的那个头被截掉了就不好了)
     */
    @Override
    protected int getSuggestedMinimumHeight() {
        return Math.max((int) mBackgroundHeight, (int) mProgressBarheight);
    }

    /**
     * 这个函数的 解析 Google 一大把,就不解释了
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     * 现在这里是个套路活,跟着老司机走就行了
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    /**
     * 测量 view 的 宽高信息
     * @param measureSpec
     * @param isWidth
     * @return
     */
    private int measure(int measureSpec, boolean isWidth) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        //不要忘记 padding ,万一有人设置了呢
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (mode == MeasureSpec.EXACTLY) { //如果 width 或者 height 都设置了 精确值:比如 45dp啊什么的
            result = size; //就按主人的来吧,诶,森么是主人
        } else {
            //其他情况,既然你都不知道要什么,就按我的套路来吧
            result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
            result += padding; //padding 这个小伙子还是很调皮的
            if (mode == MeasureSpec.AT_MOST) {
                if (isWidth) {
                    result = Math.max(result, size);
                } else {
                    result = Math.min(result, size);
                }
            }
        }
        return result;
    }

    /** 要开车了,快上车!
     * @param canvas
     */
    @Override
    protected synchronized void onDraw(Canvas canvas) {
        calRectF();

        canvas.drawRect(mBackgroundRectF, mBackgroundPaint);

        canvas.drawRect(mProgressbarRectF, mProgressbarPaint);
    }

    /**
     * 精华就在这里了。
     * 一开始我也看不懂
     * 现在我也看不懂
     * 可是效果出来了
     * 就这么滴吧
     * 多看几次
     * 说不定就懂了呢
     */
    private void calRectF() {
        mProgressbarRectF.left = getPaddingLeft();
        mProgressbarRectF.top = getHeight() / 2.0f - mProgressBarheight / 2.0f;
        mProgressbarRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft();
        mProgressbarRectF.bottom = getHeight() / 2.0f + mProgressBarheight / 2.0f ;

        mBackgroundRectF.left = mProgressbarRectF.right;
        mBackgroundRectF.top = getHeight() / 2.0f - mBackgroundHeight / 2.0f;
        mBackgroundRectF.right = getWidth() - getPaddingRight();
        mBackgroundRectF.bottom = getHeight() / 2.0f + mBackgroundHeight / 2.0f;

    }

    /** 这个我也不想说
     * 如果三个月之后我看不懂这个代码
     * 说明
     * 我应该是失忆了
     * @return
     */
    public int getProgress() {
        return mCurrentProgress;
    }

    /**
     * 同上
     * @return
     */
    public int getMax() {
        return mMaxProgress;
    }

    /**
     * 同上
     * @param progress
     */
    public void setProgress(int progress) {
        mCurrentProgress = progress;
        invalidate();
    }

    /**
     * 让我的 progress 动起来!
     * ValueAnimator 是个神器
     * Google一下
     * @param progress
     */
    public void anitProgress(int progress) {
        ValueAnimator animator = ValueAnimator.ofInt(0, progress);
        animator.setDuration(1500);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCurrentProgress = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        animator.start();
    }

    public float dp2px(float dp) {
        final float scale = getResources().getDisplayMetrics().density;
        return dp * scale + 0.5f;
    }

这就是我第一个实质意义上的自定义View了,以前一般都是扩展TextView啊,组合LinearLayout
之类的。
虽然这个View也是看着别人的代码写的。
不过总算是自己动手敲出来了。
敲开心啊。
照抄学习的 project 代码家NumberProgressBar
已发布到

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 179,511评论 25 708
  • 国内自定义View的文章汗牛充栋,但是,即便是你全部看完也未必掌握这一知识(实际上,我也看了很多,但是一旦涉及自定...
    SnowDragonYY阅读 1,739评论 3 36
  • 国内自定义View的文章汗牛充栋,但是,即使你全部看完它们也未必能掌握这一知识点(实际上,我就几乎看完了所有的国内...
    工程师milter阅读 37,956评论 143 673
  • 地处安丘西南大约一百里的石埠子镇(原庵上镇,为什么要提庵上呢?后续会有庵上镇的故事的)有座本地很有名的文化名山——...
    天涯行者阅读 3,521评论 0 3
  • 手和嘴不协调,手紧紧握住小馒头,嘴也用劲张的,手抓着小馒头已经送到嘴边,正常应该是松手嘴就吃上了,可是实际上宝宝手...
    宸宸的楠楠妈妈阅读 638评论 0 0

友情链接更多精彩内容