• 自定义View 一 (继承VIew重写onDraw方法)


    项目:具有圆形效果的自定义View

    一、继承View并重写onDraw方法

    public class CircleView extends View{
        private static final int COLOR = Color.RED;
        private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        private int mWidth = 0;
        private int mHeight = 0;
    
        public CircleView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public CircleView(Context context) {
            super(context);
            init();
        }
    
        public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init(){
            mPaint.setColor(COLOR);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //获取当前View的宽/高
            mWidth = getMeasuredWidth();
            mHeight = getMeasuredHeight();
            //获取半径
            int radium = Math.min(mWidth,mHeight)/2;
            //画圆
            canvas.drawCircle(mWidth/2,mHeight/2,radium,mPaint);
        }
    
    }
    CircleView

    在xml中测试margin发现可以用,说明margin是由父容器控制的(想起measureChildMarginLayout源码)

    但是wrap_content和padding都不生效。

    二、让wrap_content生效

    根据上一章View的工作原理:①、重写onMeasure方法  ②、给CircleView设定一个固定的宽高

    //设定wrap_content时候的宽度    
    private static final int AT_WIDTH = 30;
    private static final int AT_HEIGHT = 30;
    
    //重写onMeasure()方法
    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            //获取子View的范围
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
           //判断当属性为wrap_content的时候
            if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST){
                setMeasuredDimension(AT_WIDTH,AT_HEIGHT);
            }
            else if (widthMode == MeasureSpec.AT_MOST){
                setMeasuredDimension(AT_WIDTH,heightSize);
            }
            else if (heightMode == MeasureSpec.AT_MOST){
                setMeasuredDimension(widthSize,AT_HEIGHT);
            }
            else {
                super.onMeasure(widthMeasureSpec,heightMeasureSpec);
            }
        }    

    三、解决无法padding的问题

    原理:只需要在onDraw中,获取padding的参数就可以了

    //重写onDraw方法
     protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //获取padding
            int paddingLeft = getPaddingLeft();
            int paddingRight = getPaddingRight();
            int paddingTop = getPaddingTop();
            int paddingBottom = getPaddingBottom();
            //获取当前View的宽/高 减去padding
            mWidth = getMeasuredWidth() - paddingLeft - paddingRight;
            mHeight = getMeasuredHeight() - paddingTop - paddingBottom;
            //获取半径
            int radium = Math.min(mWidth,mHeight)/2;
            //画圆
            canvas.drawCircle(paddingLeft+mWidth/2,paddingTop - mHeight/2,radium,mPaint);
        }
    CircleView

    四、自定义属性

    步骤:①、在values目录中创建xml文件名,文件名必须以attr_开头。②、内容的编写:<declare-styleadable>标签中:name代表自定义属性(该为CircleView类) 

    <attr>标签中 name代表之后使用的属性名(circle_color),format代表格式(color)

    <resources>
        <declare-styleable name="CircleView">
            <attr name="color_circle" format="color"/>
        </declare-styleable>
    </resources>
    attr_circleview

    步骤③、在布局文件中使用自定义属性  必须在schemas声明:xmlns:app="http://schemas.android.com/apk/res-auto" 其中app名字可以随便替换。

    但是circleView中自定义属性名的前缀必须是和这里一致(一般习惯使用app)

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        //这一段必须要加    app名字可以替换
    xmlns:app
    ="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.maikefengchao.circleview.MainActivity"> <com.maikefengchao.circleview.CircleView android:layout_width="80dp" android:layout_height="80dp"
    //前缀与添加的声明前缀一致
    app:color_circle="#9999"/> </LinearLayout>

    步骤④:在CircleView中获取自定义属性参数

    //在构造方法中使用 
     public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //加载自定义属性集合CircleView
            TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.CircleView);
            //解析集合中的circle_circle,设置默认颜色
            mColor = a.getColor(R.styleable.CircleView_color_circle,Color.RED);
            init();
        }

    全部代码:(P209 ①)

  • 相关阅读:
    Java集合容器面试题(2022最新版)
    消息中间件MQ与RabbitMQ面试题(2022最新版)
    Spring面试题(2022最新版)
    程序员何苦为难程序员!
    HashMap的remove树节点的时候树会进行退化
    Spring Boot面试题(2022最新版)
    Spring MVC面试题(2022最新版)
    Redis面试题(2022最新版)
    Java虚拟机(JVM)面试题(2022最新版)
    那些游戏告诉我们,这就是人生!
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5427062.html
Copyright © 2020-2023  润新知