Android 自定义View (三)

一、前言

 

上节 讲解了旋转圆环基本的实现方法。本文将在此基础上进一步改进,在属性文件中自定义控件属性,避免代码中显式调用setXXX() 方法。

 

二、流程

 

首先,在资源文件 values 中新建一个 attr.xml,其中定义了我们即将使用的几个旋转环的属性,如下所示

 

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RotatingRing">
        <attr name="width" format="integer"/>
        <attr name="radius" format="integer"/>
        <attr name="start_angle" format="integer"/>
        <attr name="sweep_angle" format="integer"/>
        <attr name="start_color" format="color"/>
        <attr name="end_color" format="color"/>
        <attr name="color" format="color"/>
        <attr name="duration" format="integer"/>
    </declare-styleable>
</resources>

 

在 RotatingRing 类中,添加第三个构造函数 (含3个参数的),如下所示

 

public RotatingRing(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

 

根据属性清单获取属性值

 

public RotatingRing(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RotatingRing);
        radius = typedArray.getInt(R.styleable.RotatingRing_radius, 100);
        width = typedArray.getInt(R.styleable.RotatingRing_width, 20);
        startAngle = typedArray.getInt(R.styleable.RotatingRing_start_angle, 0);
        sweepAngle = typedArray.getInt(R.styleable.RotatingRing_sweep_angle, 270);
        startColor = typedArray.getColor(R.styleable.RotatingRing_start_color, Color.WHITE);
        endColor = typedArray.getColor(R.styleable.RotatingRing_end_color, typedArray.getColor(R.styleable.RotatingRing_color, Color.BLUE));
        duration = typedArray.getColor(R.styleable.RotatingRing_duration, 1000);
        typedArray.recycle();
    }

 

由上所述,默认值可以被第三个构造函数所定义,故可以去除第一个构造函数里定义的的默认值,改进后的构造函数如下所示

 

public RotatingRing(Context context) {
        this(context, null);
    }

    public RotatingRing(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RotatingRing(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RotatingRing);
        radius = typedArray.getInt(R.styleable.RotatingRing_radius, 100);
        width = typedArray.getInt(R.styleable.RotatingRing_width, 20);
        startAngle = typedArray.getInt(R.styleable.RotatingRing_start_angle, 0);
        sweepAngle = typedArray.getInt(R.styleable.RotatingRing_sweep_angle, 270);
        startColor = typedArray.getColor(R.styleable.RotatingRing_start_color, Color.WHITE);
        endColor = typedArray.getColor(R.styleable.RotatingRing_end_color, typedArray.getColor(R.styleable.RotatingRing_color, Color.BLUE));
        duration = typedArray.getColor(R.styleable.RotatingRing_duration, 1000);
        typedArray.recycle();
    }

 

到此,可以去除 MainActivity 中的 RotatingRing.setXXX()方法,而在 activity_main.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">

    <draw.bitmap.canvas.RotatingRing
        android:id="@+id/rotating_ring"
        android:layout_width="400dp"
        android:layout_height="400dp"

        app:width="30"
        app:radius="150"
        app:start_angle="0"
        app:sweep_angle="270"
        app:duration="1500"
        app:start_color="@color/colorWhite"
        app:end_color="@color/colorRed"

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

其中‘app’为原布局文件里定义好的命名空间,这里我直接拿来用了,也可以自己定义命名空间,只须在布局文件头加上 

 

xmlns:命名空间="http://schemas.android.com/apk/res-auto"

 

这里我为区分定义了一个红色的圆环,而其他参数与原先 MainActivity 里setXXX() 方法里的参数一致,修改后的代码为

 

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    RotatingRing rotatingRing;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rotatingRing = findViewById(R.id.rotating_ring);
        rotatingRing.startAnim();
    }
}

 

运行效果

 

Android 自定义View (三)

 

到此已经初步掌握了自定义view的一些必要性质,下一节将深入了解一些高级属性以及绘制相关源码等。

 

Android 自定义View (三)

上一篇:Android+uiautomator函数方法(1)


下一篇:手机号正则验证