2. Custom View basic knowledge attr


Foreword:
Custom view is one of the core of android custom control, so before learning custom view, let's first understand the usage of attr of custom attribute of custom view.

1.attr

1.1 Concept

(1) The simple understanding of attr is an attribute constraint, which constrains the data type of the attribute of a specific attribute field (boolean, string, float...)

(2) The file name of attr is not fixed, but it is easy to understand and standardize, and it can also be other names. Create attr file under res/values

2.attr function

The role of attr is to constrain the attribute data type. Various attrs are defined in the xml resource file to specify the data type of the attr.

3. Attr usage

(1) Add attributes to the custom View
(2) Declare the attribute value for the corresponding attribute in xml
(3) Obtain the attribute value at runtime (usually the constructor)
(4) Apply the obtained attribute value to the View

2. Simple creation of attr

(1) We created a new file named attrs.xml in the res/values ​​directory. The file name is not important, as long as it is an xml file.
(2) Define the xml attributes supported by our custom view in this file.

E.g:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="sext" format="string|integer"/>  公共属性
    <attr name="isSignal" format="boolean"/>

    <declare-styleable name="View1">
        <attr name="viewBg" format="reference"/>
        <attr name="cirColor" format="color|integer"/>
        <attr name="txtVisibility" format="string"/>
        <attr name="isSignal"/>                    直接引用公共属性
    </declare-styleable>>
</resources>

declare-styleable name : is the name of the custom view
attr name : is the custom attribute
format : the types enum, boolean, color, dimension, flag, float, fraction, integer, reference, string supported by the custom attribute.

Note :
If you define multiple <declare-styleable names, the attr name cannot be the same, otherwise an error will be reported, then extract the same outside of <declare-styleable and define it as a public attribute, such as "<"attr name="isSignal" />"

3.Specific reference for format data type

1.reference : refer to a resource ID

1)属性定义:
    <declare-styleable name = "名称">
          <attr name = "background" format = "reference" />
    </declare-styleable>2)属性使用:
     <ImageView
         android:layout_width = "42dip"
         android:layout_height = "42dip"
         android:background = "@drawable/图片ID"/> 

2.color : color value

1)属性定义:
    <declare-styleable name = "名称">
         <attr name = "textColor" format = "color" />
    </declare-styleable>2)属性使用:
   <TextView
         android:layout_width = "42dip"
         android:layout_height = "42dip"
          android:textColor = "#00FF00"/> 

3. boolean : Boolean value

1)属性定义:
    <declare-styleable name = "名称">
        <attr name = "focusable" format = "boolean" />
    </declare-styleable>2)属性使用:
    <Button
       android:layout_width = "42dip"
       android:layout_height = "42dip"
       android:focusable = "true"/> 

4. dimension : dimension value

1)属性定义:
    <declare-styleable name = "名称">
           <attr name = "layout_width" format = "dimension" />
    </declare-styleable>2)属性使用:
   <Button
          android:layout_width = "42dip"
          android:layout_height = "42dip"/> 

5. float : floating point value

1)属性定义:
     <declare-styleable name = "AlphaAnimation">
         <attr name = "fromAlpha" format = "float" />
         <attr name = "toAlpha" format = "float" />
      </declare-styleable>2)属性使用:
     <alpha
         android:fromAlpha = "1.0"
         android:toAlpha = "0.7"/> 

6. integer : integer value

1)属性定义:
     <declare-styleable name = "AnimatedRotateDrawable">
          <attr name = "visible" />
          <attr name = "frameDuration" format="integer" />
          <attr name = "framesCount" format="integer" />
          <attr name = "pivotX" />
          <attr name = "pivotY" />
          <attr name = "drawable" />
     </declare-styleable>2)属性使用:
   <animated-rotate
     xmlns:android = "http://schemas.android.com/apk/res/android"  
        android:drawable = "@drawable/图片ID"  
        android:pivotX = "50%"  
        android:pivotY = "50%"  
        android:framesCount = "12"  
        android:frameDuration = "100" /> 

7. string : string

1)属性定义:
    <declare-styleable name = "MapView">
       <attr name = "apiKey" format = "string" />
    </declare-styleable>2)属性使用:
   <com.google.android.maps.MapView
        android:layout_width = "fill_parent"
        android:layout_height = "fill_parent"
                    android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"
     /> 

8. Fraction : percentage

1)属性定义:
    <declare-styleable name="RotateDrawable">
        <attr name = "visible" />
        <attr name = "fromDegrees" format = "float" />
        <attr name = "toDegrees" format = "float" />
        <attr name = "pivotX" format = "fraction" />
        <attr name = "pivotY" format = "fraction" />
        <attr name = "drawable" />
   </declare-styleable>2)属性使用:

   <rotate
    xmlns:android = "http://schemas.android.com/apk/res/android" 
             android:interpolator = "@anim/动画ID"
             android:fromDegrees = "0" 
             android:toDegrees = "360"
             android:pivotX = "200%"
             android:pivotY = "300%" 
             android:duration = "5000"
             android:repeatMode = "restart"
             android:repeatCount = "infinite"  /> 

9. enum : enumerated value

1)属性定义:
      <declare-styleable name="名称">
         <attr name="orientation">
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
         </attr>            
       </declare-styleable>2)属性使用:
        <LinearLayout
          xmlns:android = "http://schemas.android.com/apk/res/android"
          android:orientation = "vertical"
          android:layout_width = "fill_parent"
          android:layout_height = "fill_parent">
        </LinearLayout> 

10. Flag : bitwise OR operation

1)属性定义:
   <declare-styleable name="名称">
      <attr name="windowSoftInputMode">
            <flag name = "stateUnspecified" value = "0" />
            <flag name = "stateUnchanged" value = "1" />
            <flag name = "stateHidden" value = "2" />
            <flag name = "stateAlwaysHidden" value = "3" />
            <flag name = "stateVisible" value = "4" />
            <flag name = "stateAlwaysVisible" value = "5" />
            <flag name = "adjustUnspecified" value = "0x00" />
            <flag name = "adjustResize" value = "0x10" />
            <flag name = "adjustPan" value = "0x20" />
            <flag name = "adjustNothing" value = "0x30" />
     </attr>         
   </declare-styleable>2)属性使用:
     <activity
        android:name = ".StyleAndThemeActivity"
        android:label = "@string/app_name"
        android:windowSoftInputMode = "stateUnspecified | stateUnchanged | stateHidden">
        <intent-filter>
            <action android:name = "android.intent.action.MAIN" />
               <category android:name = "android.intent.category.LAUNCHER" />
                   </intent-filter>
             </activity> 

Note:
You can specify multiple types of values ​​when defining attributes

1)属性定义:
     <declare-styleable name = "名称">
        <attr name = "background" format = "reference|color" />
     </declare-styleable>2)属性使用:
     <ImageView
        android:layout_width = "42dip"
        android:layout_height = "42dip"
        android:background = "@drawable/图片ID|#00FF00" /> 

4. Use of attr

Simple implementation steps for custom view:
(1) First create attrs custom attribute file name, define attributes and related data types
(2) Create custom view again, and then read relevant attributes to complete the required view related layout, drawing and other tasks
( 3) Finally reference in the xml layout file or directly use a new related object in the code for use

For example: customize a textview to display attrs.xml on the screen

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="viewText" format="string|integer"/>
    <attr name="isSignal" format="boolean"/>
    <attr name="viewBg" format="color"/>

    <declare-styleable name="YText">
        <attr name="viewText"/>
        <attr name="isSignal"/>
        <attr name="viewBg" />
        <attr name="viewTextBg" format="color"/>
        <attr name="viewSize" format="integer"/>
    </declare-styleable>
</resources>

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout   
    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.demo.YText
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:isSignal="false"
        app:viewText="自定义View"
        app:viewBg="@color/colorYellow"
        app:viewTextBg="@color/colorRed"
        app:viewSize="80">
    </com.example.demo.YText>
    
</androidx.constraintlayout.widget.ConstraintLayout>

Note: res/android and res-auto

xmlns:android=http://schemas.android.com/apk/res/android
xmlns:app=http://schemas.android.com/apk/res-auto
These two actually let you reference the system With its own attributes, the latter allows you to use custom attributes in the attrs library.

YText.java

public class YText extends View {
    
    
    private String mText;
    private boolean isSignal;
    private int viewTextbg;
    private int viewBg;
    private int mTextSize;
    private Paint paint;
    public YText(Context context) {
    
    
        this(context,null); //手动new 调用
    }

    public YText(Context context, @Nullable AttributeSet attrs) {
    
    
        this(context, attrs,0); //xml 中调用
        parseXmlAttributes(context,attrs);
    }
    public YText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
    }
    public void parseXmlAttributes(Context context,AttributeSet attributeSet) {
    
    
        TypedArray typedArray = context.obtainStyledAttributes(attributeSet,R.styleable.YText);
        for (int i=0;i<typedArray.getIndexCount();i++) {
    
    
                switch (typedArray.getIndex(i)) {
    
    
                    case R.styleable.YText_viewText:
                        mText = typedArray.getString(R.styleable.YText_viewText);
                        break;
                    case R.styleable.YText_isSignal:
                        isSignal = typedArray.getBoolean(R.styleable.YText_isSignal,true);
                        break;
                    case R.styleable.YText_viewBg:
                        viewBg  = typedArray.getColor(R.styleable.YText_viewBg, Color.YELLOW);
                        break;
                    case R.styleable.YText_viewTextBg:
                        viewTextbg  = typedArray.getColor(R.styleable.YText_viewTextBg, Color.YELLOW);
                        break;
                    case R.styleable.YText_viewSize:
                        mTextSize = typedArray.getInt(R.styleable.YText_viewSize,38);
                        break;
                }
            }
        typedArray.recycle();
        paint = new Paint();
        paint.setTextSize(mTextSize);

    }
    @Override
    protected void onDraw(Canvas canvas) {
    
    
        paint.setColor(viewBg);
        canvas.drawRect(0,0,getMeasuredWidth(), getMeasuredHeight(), paint);
        paint.setColor(viewTextbg);
       canvas.drawText(mText,100,100,paint);
    }
}

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_41477306/article/details/106741644