• D1-从N角星开始论述自定义控件


    零、前言

    [1].个人对安卓绘制逻辑感到繁琐,自己封装了一个绘图框架
    [2].自定义控件的绘制流程都基于我的这个库,详见:开源计划之--Android绘图库--LogicCanvas
    [3].星星控件目的:总结自定义控件的流程
    [4].功能:自定义星星的角数,高矮,胖瘦,填充与否,


    一、准备

    1.新建StarView继承自View,重写构造方法

    这里为了方便,准备了dp转px的方法
    一参数构造用于直接new视图
    二参数构造用于支持视图在xml中有效

    /**
     * 作者:张风捷特烈<br/>
     * 时间:2018/9/3 0003:19:01<br/>
     * 邮箱:1981462002@qq.com<br/>
     * 说明:星星控件
     */
    public class StarView extends View {
       
        public StarView(Context context) {
            this(context, null, 0);
        }
    
        public StarView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public StarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
    
        /**
         * 适配dp
         *
         * @param dp
         * @return
         */
        public Float dp2px(Float dp) {
            if (dp != null) {
                final Float scale = getContext().getResources().getDisplayMetrics().density;
                return dp * scale + 0.5f;
            }
            return dp;
        }
    }
    
    
    2.定义属性
    /**
     * 星星的角数
     */
    private int mAngleNum = 5;
    /**
     * 星星高
     */
    private float mHeight = dp2px(20f);
    /**
     * 星星内接圆直径
     */
    private float mr = dp2px(10f);
    /**
     * 星星颜色
     */
    private int mStarColor = Color.BLUE;
    /**
     * 是否填充
     */
    private boolean isFill = true;
    

    3.先查看绘制效果:重写onDraw方法

    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        Painter painter = PainterEnum.INSTANCE.getInstance(canvas);
            //设置绘图对象
            Shape shape = new ShapeStar().num(mAngleNum).R(mHeight / 2).r(mr / 2).b(dp2px(1f));
            //判断是否填充
            if (isFill) {
                shape.fs(mStarColor);
            } else {
                shape.ss(mStarColor);
            }
            painter.draw(shape);
        }
    
    9414344-7b189a116d1e8ca3.png
    star1.png
    2.设置控件属性:先介绍一下自定义属性吧

    我们常用的TextView、ImageView等都可以在xml里配置相关属性,就是自定义属性

    第一步,明确自己的自定义属性有哪些,最后先想好名字
    第二步,在res/values文件夹下创建attrs.xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!--一个自定义控件-->
        <declare-styleable name="StarView">
            <!--自定义属性名 和 类型-->
            <attr name="z_star_height" format="dimension"/>
            <attr name="z_star_AngleNum" format="integer"/>
            <attr name="z_star_r" format="dimension"/>
            <attr name="z_star_color" format="reference"/>
            <attr name="z_star_isFill" format="boolean"/>
        </declare-styleable>
    </resources>
    

    其中:

    1、reference 引用类型值 : @id/...
    2、color 颜色类型值     #ff00ff
    3、boolean 布尔类型值    true , false
    4、dimension 尺寸类型值     dp / px /sp
    5、integer 整数类型值       weight  progress max
    6、float 浮点型值        0.1f
    7、string 字符串类型值  "atrrs"
    8、<enum> 枚举类型值 :水平/垂直
    9、flag:位或运算
    10、fraction:百分数
    
    第三步:在自定义View的构造函数里使用
        /**
         * 初始化
         * @param attrs 自定义属性
         */
        private void init(AttributeSet attrs) {
            TypedArray ta = attrs == null ? null : getContext().obtainStyledAttributes(attrs, R.styleable.StarView);
            mAngleNum=ta.getInt(R.styleable.StarView_z_star_AngleNum, mAngleNum);
            mHeight=ta.getDimension(R.styleable.StarView_z_star_height, mHeight);
            mr=ta.getDimension(R.styleable.StarView_z_star_height, mr);
            mStarColor=ta.getColor(R.styleable.StarView_z_star_color, mStarColor);
            isFill = ta.getBoolean(R.styleable.StarView_z_star_isFill, isFill);
            ta.recycle();//一定记得回收!!!
        }
    
    第四步:在xml里使用(为简洁、外层的布局省略):

    其中标签头是类全名:com.toly1994.d.view.StarView
    xmlns:toly="http://schemas.android.com/apk/res-auto"是名空间
    因为我英文名叫toly,可见它的随意性,toly:z_star_AngleNum="6"也是基于此
    我习惯自定义属性已z_开头,好找,AndroidStudio自动提示。

        <com.toly1994.d.view.StarView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            xmlns:toly="http://schemas.android.com/apk/res-auto"
            toly:z_star_AngleNum="6"
            toly:z_star_color="#f00"
            toly:z_star_height="40dp"
            toly:z_star_isFill="false"
            toly:z_star_r="20dp"/>
    
    3.Activity中使用:
    setContentView(R.layout.activity_star);
    

    一个不同风格的星星跃然纸上


    9414344-a059b9f10f9e40b8.png
    自定义属性.png

    二、测量:

    现在问题来了:添加背景可以看出控件区域竟然占了全屏,这不是我们想要的。

    9414344-70f46eb2e37901b2.png
    宽高.png
    这时要重写测量方法:onMeasure方法

    这个控件的测量很简单:无论什么测量模式,宽高相同并且等于mHeight,
    也就是layout_width和layout_height无作用,全靠z_star_height确定布局宽高。

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            setMeasuredDimension((int)mHeight,(int) mHeight);
        }
    

    现在你想要多少角星都不是事儿,拿走,不谢

    9414344-8c7be1cddf65ab5f.png
    效果图

    三、事件:效果点击时填充与不填充切换

    @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isFill = !isFill;
                    invalidate();
            return true;
        }
    
    9414344-7c83cc2114986340.gif
    点击事件.gif

    点击事件是你的控件对外的接口,提供修改状态的可能性,你可以发挥无限想象力,这就是自定义控件的魅力。
    比如随机颜色,当然你也可以随机大小,随机角数,一切创造取决于你!

    9414344-24b803c70fdb96e9.gif
    点击事件升级.gif

    这是一个非常简单的自定义控件,作为自定义控件的第一篇,总结一下绘制的流程还是挺不错的
    自定义控件还有很多很多坑,来和我一起填吧。


    后记、

    1.声明:

    [1]本文由张风捷特烈原创,转载请注明
    [2]欢迎广大编程爱好者共同交流
    [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    [4]你的喜欢与支持将是我最大的动力

    2.连接传送门:

    更多安卓技术欢迎访问:安卓技术栈
    我的github地址:欢迎star
    简书首发,腾讯云+社区同步更新
    张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

    3.联系我

    QQ:1981462002
    邮箱:1981462002@qq.com
    微信:zdl1994328

    4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
    9414344-c474349cd3bd4b82.jpg
    公众号.jpg
  • 相关阅读:
    Kth Smallest Element in a BST
    Bitwise AND of Numbers Range
    Happy Number
    Summary Ranges
    linux设置MySQL开机自动启动
    基本PSO算法实现(Java)
    Invert Binary Tree
    Rectangle Area
    Contains Duplicate II
    Contains Duplicate
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781904.html
Copyright © 2020-2023  润新知