美文网首页
Android自定义View

Android自定义View

作者: 你大爷终归是你大爷 | 来源:发表于2020-05-24 23:14 被阅读0次

    xml创建自定义View

    一、创建View的属性

    在values中创建attrs.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="TestView">
            <attr name="test_boolean" format="boolean"></attr>
            <attr name="test_string" format="string"></attr>
            <attr name="test_integer" format="integer"></attr>
            <attr name="test_emum" format="enum">
                <enum name="top" value="1"></enum>
                <enum name="bottom" value="2"></enum>
            </attr>
            <attr name="test_dimension" format="dimension"></attr>
        </declare-styleable>
    </resources>
    

    二、创建View类

    package com.example.testcustomview;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.os.Parcelable;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    
    import androidx.annotation.Nullable;
    
    public class TestView extends View {
        private static final String TAG = "TestView";
    
        private boolean booleanTest;
        private int integerTest;
        private String stringTest = "TestString";
        private int enumTest;
        private float dimensionTest;
        private Paint mPaint;
    
        public TestView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            initPant();
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TestView);
            booleanTest = typedArray.getBoolean(R.styleable.TestView_test_boolean, false);
            int count = typedArray.getIndexCount();
            for (int i=0;i<count;i++) {
                int index = typedArray.getIndex(i);
                switch (index) {
                    case R.styleable.TestView_test_boolean:
                        booleanTest = typedArray.getBoolean(R.styleable.TestView_test_boolean,false);
                        break;
                    case R.styleable.TestView_test_integer:
                        integerTest = typedArray.getInteger(R.styleable.TestView_test_integer,0);
                        break;
                    case R.styleable.TestView_test_string:
                        stringTest = typedArray.getString(R.styleable.TestView_test_string);
                        break;
                    case R.styleable.TestView_test_emum:
                        enumTest = typedArray.getInt(R.styleable.TestView_test_emum,1);
                        break;
                    case R.styleable.TestView_test_dimension:
                        dimensionTest = typedArray.getDimension(R.styleable.TestView_test_dimension,0);
                        break;
                }
            }
            Log.d(TAG, "TestView() called with: context = [" + context + "], attrs = [" + attrs + "]");
            Log.d(TAG, "TestView: \n  booleanTest:"+booleanTest +
                    "\n  integerTest:"+integerTest +
                    "\n  stringTest:"+stringTest +
                    "\n  enumTest:"+enumTest +
                    "\n  dimensionTest:"+dimensionTest);
    
            //回收
            typedArray.recycle();
        }
    
        private void initPant() {
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(6);
            mPaint.setColor(0xFFFF0000);
            mPaint.setAntiAlias(true);
        }
    
        //测量
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec,heightMeasureSpec);
            //本控件宽
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int width = 0;
            // MeasureSpec.EXACTLY 确定宽高
            if (widthMode == MeasureSpec.EXACTLY) {
                width = widthSize;
            } else {
                int needWidth = measureWidth() + getPaddingLeft() + getPaddingRight();
                // MeasureSpec.AT_MOST 不错过给定宽度
                if (widthMode == MeasureSpec.AT_MOST) {
                    width = Math.min(needWidth,widthSize);
                } else { //MeasureSpec.UNSPECIFIED 按照计算宽度
                    width = needWidth;
                }
            }
    
            //本控件高
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int height = 0;
            if (heightMode == MeasureSpec.EXACTLY) {
                height = heightSize;
            } else {
                int needHeight = measureHight() + getPaddingTop() + getPaddingBottom();
                if (heightMode == MeasureSpec.AT_MOST) {
                    height = Math.min(needHeight,heightSize);
                } else {
                    height = needHeight;
                }
            }
            setMeasuredDimension(width,height);
        }
    
        private int measureHight() {
            return 0;
        }
    
        private int measureWidth() {
            return 0;
        }
    
        //绘制
        @Override
        protected void onDraw(Canvas canvas) {
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(6);
            canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2-mPaint.getStrokeWidth(),mPaint);
            mPaint.setStrokeWidth(1);
            //横线
            canvas.drawLine(0,getHeight()/2,getWidth(),getHeight()/2,mPaint);
            //竖线
            canvas.drawLine(getWidth()/2,0,getWidth()/2,getHeight(),mPaint);
    
            mPaint.setTextSize(96);
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawText(stringTest,0,getHeight(),mPaint);
        }
    
        //触发事件
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            stringTest = "8888";
            invalidate();
            return true;
        }
    
        private static final String INSTANCE = "instance";
        private static final String KEY_TEXT = "key_text";
    
        //点击后stringTest改为8888,为保存状态用下面两个方法
        //保存数据状态
        @Nullable
        @Override
        protected Parcelable onSaveInstanceState() {
            Bundle bundle = new Bundle();
            bundle.putString(KEY_TEXT,stringTest);
            //保存父View的状态
            bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
            return bundle;
        }
    
        //获取状态
        @Override
        protected void onRestoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                Bundle bundle = (Bundle) state;
                Parcelable parcelable = bundle.getParcelable(INSTANCE);
                super.onRestoreInstanceState(parcelable);
                stringTest = bundle.getString(KEY_TEXT);
                return;
            }
            super.onRestoreInstanceState(state);
        }
    }
    

    三、在activity_main.xml中加入View

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        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=".MainActivity">
    
        <com.example.testcustomview.TestView
            android:id="@+id/mainView"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_centerInParent="true"
            android:background="@color/colorPrimaryDark"
            app:test_boolean="true"
            app:test_integer="1"
            app:test_string="abcgjef"
            app:test_dimension="100dp"
            app:test_emum="bottom">
    
        </com.example.testcustomview.TestView>
    
    </RelativeLayout>
    

    相关文章

      网友评论

          本文标题:Android自定义View

          本文链接:https://www.haomeiwen.com/subject/nvisahtx.html