1. Foundation 1: Coordinate calculation

1.1 Android window coordinate system calculation takes the upper left corner of the screen as the origin,

If you go to the right, you have a positive X-axis, and if you go down, you have a positive Y-axis

1.2 View Coordinate system

Note that the coordinates obtained are pixel values, not dp values. Note that the coordinates obtained are pixel values, not DP values.

// Get the relative coordinates (distance) inside the ViewGetX (), getY ()// Get the relative coordinate value of the View relative to the parent View.GetLeft (), getTop(), getRight(), getBottom()// Get the actual coordinate value in the screen (distance)GetRawX (), getRawY ()Copy the code

The activity in the figure refers to a full-screen window. Strictly speaking, it should be a screen

1.3 Actual Development Scenarios

Get the width and height of the View

width = getRight() - getLeft();
height = getBottom() - getTop();
Copy the code

2. Get the upper left corner coordinates of the View in the parent View

Point point = new Point();
point.set(ivState.getLeft() ,ivState.getTop());
Copy the code

3. Obtain the coordinate of the center point of the View in the parent View

Point point = new Point();
point.set(ivState.getRight() - ivState.getLeft() ,ivState.getBottom() - ivState.getTop());
Copy the code

2. Customize attributes

2.1 Constructors & Initialize properties

public class MDButton extends Button {
    // Called when Java dynamically creates a view
    public MDButton(Context context) {
        super(context);
        initInnerView(context);
    }
    // when the XML layout is initialized
    public MDButton(Context context, AttributeSet attrs) {
        super(context, attrs);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
        initAttrs(context, attrs);
    }
    / / the default style, in MDButton (Context Context, AttributeSet attrs) called MDButton (Context, attrs, defStyleAttr);
    public MDButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
        initAttrs(context, attrs);
    }
    // Only used when API version >21
    / / the default style, in MDButton (Context Context, AttributeSet attrs) called MDButton (Context, attrs, defStyleAttr);
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MDButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
        initAttrs(context, attrs);
    }
    // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
    private void initInnerView(Context context) {
        / /...
    }
    private void initAttrs(Context context, AttributeSet attrs) {
        / /...}}Copy the code

2.2 Custom Attributes

1. Write attribute & type in /res/values/attrs. XML in module;


      
<resources>
    <declare-styleable name="MDButton">
        <! You can specify multiple types of values when you define a property -->
        <attr name="mdb_bg" format="color|reference" />
        <attr name="mdb_txt_color" format="color|reference" />
        <! -- String -->
        <attr name="mdb_txt" format="string" />
        <! -- boolean -->
        <attr name="mdb_auto_anim" format="boolean" />
        <! -- Percentage type -->
        <attr name="mdb_anim_pivotX" format="fraction" />
        <! - an int value -- -- >
        <attr name="mdb_auto_anim_delay" format="integer" />
        <! -- floating point value -->
        <attr name="mdb_auto_anim_alpha" format="float" />
        <! -- dp size value -->
        <attr name="mdb_min_width" format="dimension" />
        <! -- Enumeration types -->
        <attr name="mdb_size">
            <enum name="small" value="0" />
            <enum name="normal" value="1" />
            <enum name="big" value="2" />
        </attr>
        <! -- flag: bit or operation -->
        <attr name="mdb_radius_corner">
            <flag name="empty" value="0x00" />
            <flag name="top" value="0x01" />
            <flag name="bottom" value="0x02" />
            <flag name="left" value="0x04" />
            <flag name="right" value="0x08" />
        </attr>
    </declare-styleable>
</resources>
Copy the code

2. Customize the View class to get the property value and use

public class MDButton extends Button {
    // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
    private void initInnerView(Context context) {
        / /...
    }
    private void initAttrs(Context context, AttributeSet attrs) {
        //1. Get the attribute array
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MDButton);
       
        //2. Get the attribute value
        Drawable bgDrawable = typedArray.getDrawable(R.styleable.MDButton_mdb_bg);
        int txtColor = typedArray.getInteger(R.styleable.MDButton_mdb_txt_color,Color.parseColor("# 808080"));
        String txt = typedArray.getString(R.styleable.MDButton_mdb_txt);
        boolean isAutoAnim = typedArray.getBoolean(R.styleable.MDButton_mdb_auto_anim, false);
        float fraction = typedArray.getFraction(R.styleable.MDButton_mdb_anim_pivotX, 1.1.1.0 f);
        float alpha = typedArray.getFloat(R.styleable.MDButton_mdb_auto_anim_alpha , 1.0 f);
        float minWidth = typedArray.getDimension(R.styleable.MDButton_mdb_min_width, 32.0 f);
        int sizeType = typedArray.getInt(R.styleable.MDButton_mdb_size, 1);//0=small 1=normal 2=big
        int radiusCorner = typedArray.getInt(R.styleable.MDButton_mdb_radius_corner ,0);
        int delay = typedArray.getInt(R.styleable.MDButton_mdb_auto_anim_delay ,0);
        Log.e("bgDrawable".""+bgDrawable);
        Log.e("txtColor".""+txtColor);
        Log.e("txt".""+txt);
        Log.e("isAutoAnim".""+isAutoAnim);
        Log.e("fraction".""+fraction);
        Log.e("alpha".""+alpha);
        Log.e("minWidth".""+minWidth);
        Log.e("sizeType".""+sizeType);
        Log.e("radiusCorner".""+radiusCorner);
        Log.e("delay".""+delay);
        Log.e("= = = = = = = = = = = = = ="."= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
        
        //3. Set the attribute value to the corresponding attribute
        setText(txt);
        //tv.setDelay(delay);
        / /...
        
        4 / / release
        typedArray.recycle();
    }
    // Called when Java dynamically creates a view
    public MDButton(Context context) {
        super(context);
        initInnerView(context);
    }
    // when the XML layout is initialized
    public MDButton(Context context, AttributeSet attrs) {
        super(context, attrs);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
        initAttrs(context, attrs);
    }
    / / the default style, in MDButton (Context Context, AttributeSet attrs) called MDButton (Context, attrs, defStyleAttr);
    public MDButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be called
        initAttrs(context, attrs);
    }
    // Only used when API version >21
    // When there is a default style, call in MDButton(Context Context, AttributeSet attrs)
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public MDButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
// initInnerView(context); // When you combine a custom View (ViewGroup), you need to initialize the internal subview; An extended custom View does not need to be calledinitAttrs(context, attrs); }}Copy the code

3. Use the control in the layout file.xml.

 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:orientation="vertical"
        >
        <com.cupster.base_super_resource.MDButton
            app:mdb_anim_pivotX="80%"
            app:mdb_auto_anim="true"
            app:mdb_auto_anim_alpha="1.0"
            app:mdb_auto_anim_delay="100"
            app:mdb_bg="@drawable/shape_btn_gray_radius5"
            app:mdb_min_width="60dp"
            app:mdb_radius_corner="right"
            app:mdb_size="big"
            app:mdb_txt="btn1"
            app:mdb_txt_color="#ff00ff"

            android:layout_width="120dp"
            android:layout_height="60dp"
            />
        <com.cupster.base_super_resource.MDButton
            app:mdb_anim_pivotX="70%"
            app:mdb_auto_anim="false"
            app:mdb_auto_anim_alpha="0.4"
            app:mdb_auto_anim_delay="100"
            app:mdb_bg="@drawable/shape_btn_gray_radius5"
            app:mdb_min_width="60px"
            app:mdb_radius_corner="bottom|left|top|right"
            app:mdb_size="small"
            app:mdb_txt="btn1"
            app:mdb_txt_color="#ff00ff"

            android:layout_width="120dp"
            android:layout_height="60dp"
            />
        <com.cupster.base_super_resource.MDButton
            app:mdb_anim_pivotX="100%"
            app:mdb_auto_anim_alpha="0.9"
            app:mdb_auto_anim_delay="100"
            app:mdb_bg="@drawable/shape_btn_gray_radius5"
            app:mdb_min_width="90dp"
            app:mdb_radius_corner="empty"
            app:mdb_size="normal"
            app:mdb_txt="btn1"
            app:mdb_txt_color="#ff00ff"

            android:layout_width="120dp"
            android:layout_height="60dp"
            />
    </LinearLayout>
Copy the code

** Addendum: Correctness verification of attribute value acquisition **

3. Customize the View category

3.1 combined

As the name implies, the root layout of the XML file uses a RelativeLayout(similar to other layout controls), and the internal use of other View controls, layout, combined to create the original layout of the XxxView. The Java class then inherits from the container class corresponding to the root layout tag, overrides the constructor, and initializes variables for each child View. Is the most commonly used, the most reliable, not easy to produce excessive drawing, memory leaks and other problems.

Android Custom View(2) : composite

3.2 Inheritance overrides, derivations, and extensions

In short, if you inherit Button, change the default background, Button elevation value when state_press state, cancel the default minimum height 56dp, and so on. It is also the most commonly used feature that directly extends/modifies native Views

Android Custom View(3) : inherit rewrite, derivative/extension

3.3 since the painting style

Strong advice: Be familiar with View drawing, Android event passing, gesture processing and then start drawing yourself.

Method: Directly inherit View, rewrite the drawing process three steps

  1. Measure () measurement
  2. Calculate the layout coordinates
  3. The draw ()

Android Custom View(4) : self – drawn

4. The lifecycle of the View

The lifecycle of the View and the sequence of function calls associated with the Activity linkage

  1. [View] The constructor
  2. “The View” onFinishInflate ()
  3. “The Activity” onCreate ()
  4. “The Activity” onStart ()
  5. “The Activity” onResume ()
  6. “The View” onAttachedToWindow ()
  7. 【View】onMeasure()
  8. 【View】onSizeChanged()
  9. 【View】onLayout()
  10. 【View】onDraw()
  11. 【View】onWindowFocusChanged() (called before activity.onPause (), hasWindowFocus==false)
  12. “The Activity” onPause ()
  13. “The Activity” onStop ()
  14. “The Activity” onDestroy ()
  15. “The View” onDetachedFromWindow