创建视图类

试用 Compose 方式
Jetpack Compose 是推荐在 Android 设备上使用的界面工具包。了解如何在 Compose 中使用布局。
<ph type="x-smartling-placeholder"></ph> Compose 中的自定义布局 →

设计良好的自定义视图与任何其他精心设计的类一样。它封装了 一组特定的 简单的接口,高效地使用 CPU 和内存,诸如此类。在 不仅仅是 类,则自定义视图必须执行以下操作:

  • 符合 Android 标准。
  • 提供适用于 Android XML 布局的自定义可设置样式属性。
  • 发送无障碍事件。
  • 与多种 Android 平台兼容。

Android 框架提供了一组基类和 XML 标记,以帮助您创建 符合所有这些条件 要求。本课将介绍如何使用 Android 框架来创建核心 视图功能 类。

您可在 自定义视图组件中的信息。

子类化视图

Android 框架中定义的所有视图类扩展了 View。您的 自定义视图 直接扩展 View,也可以 节省时间 现有视图 子类,例如 Button

要允许 Android Studio 与视图交互,您必须至少提供一个构造函数,用于接受 ContextAttributeSet 对象作为参数。 此构造函数允许布局编辑器创建和编辑视图的实例。

Kotlin

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Java

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

定义自定义属性

如需向界面添加内置 View,请在 XML 元素中指定,然后 控制其 元素属性对外观和行为的影响。您还可以添加自定义 使用 XML 来创建视图接收者 在自定义视图中启用此行为,请执行以下操作:

  • <declare-styleable> 资源元素中为视图定义自定义属性。
  • 为 XML 布局中的属性指定值。
  • 在运行时检索属性值。
  • 将检索到的属性值应用于您的视图。

本部分介绍如何定义自定义属性并指定其值。 下一部分将介绍 在运行时检索和应用值。

如需定义自定义属性,请向项目添加 <declare-styleable> 资源。通常的做法是将这些资源 res/values/attrs.xml 文件。以下是 attrs.xml 文件示例:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

此代码声明了两个自定义属性:showTextlabelPosition。 属于某个可设定样式的 实体名称为 PieChart。按照惯例,可设置样式实体的名称与 命名为 类名称 定义了自定义视图虽然没有必要遵循此惯例 许多热门代码 编辑器依赖此命名惯例提供语句补全。

定义自定义属性后,您可以像内置属性一样在布局 XML 文件中使用它们 属性。唯一 区别在于自定义属性属于不同的命名空间。而非归属感 http://schemas.android.com/apk/res/android 命名空间时,它们就属于 http://schemas.android.com/apk/res/[your package name]。例如,下面展示了如何使用 属性的定义 PieChart:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

为了避免必须重复冗长的命名空间 URI,该示例使用 xmlns 指令。此指令会将别名 custom 分配给 命名空间 http://schemas.android.com/apk/res/com.example.customviews。 您可以为命名空间选择所需的任何别名。

注意将自定义视图添加到布局的 XML 标记的名称。这是 是 自定义视图类。如果您的视图类是内部类,请进一步限定它 替换为视图外部类的名称。 例如, PieChart 类有一个名为 PieView 的内部类。要使用 自定义属性。 使用标记 com.example.customviews.charting.PieChart$PieView

应用自定义属性

从 XML 布局创建视图时,系统会读取 XML 标记中的所有属性 从资源 bundle 并将其作为 AttributeSet。 虽然 可以直接从 AttributeSet 读取值,这样做 但具有以下缺点:

  • 系统不会解析属性值中的资源引用。
  • 因此不会应用样式。

请改为将 AttributeSet 传递给 obtainStyledAttributes()。 此方法会回传一个 TypedArray 数组 值 已解除引用并设置了样式

Android 资源编译器会做很多工作, obtainStyledAttributes() 。针对每个<declare-styleable> 资源位于 res/ 目录中,则生成的 R.java 会同时定义一个属性数组, 和一组 常量定义数组中每个属性的索引。您可以使用预定义的 要读取的常量 TypedArray 中的属性。具体方法如下 PieChart 类 读取其属性:

Kotlin

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Java

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

请注意,TypedArray 对象 是共享资源 而且必须在使用后回收

添加属性和事件

属性是控制视图行为和外观的有效方式,但是 则只能读取 在视图初始化时触发。如需提供动态行为,请公开一个属性 getter 并 setter 对 自定义属性。以下代码段展示了 PieChart 如何公开属性 名为 showText

Kotlin

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Java

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

请注意,setShowText 会调用 invalidate()requestLayout()。这些通话至关重要 以确保 View 能够可靠运行。您需要 在视图属性发生更改(可能更改其视图)后,使视图失效 确保 系统知道需要重新绘制同样,如果存在以下情况,您需要请求新布局: 更改属性的方式 可能会影响视图尺寸或形状忘记这些方法调用可能会导致 难以找到 bug。

自定义视图还必须支持事件监听器来传达重要事件。对于 实例,PieChart 公开一个名为 OnCurrentItemChanged 的自定义事件,以通知监听器 用户旋转了 饼图,重点显示新的饼图切片。

公开属性和事件很容易忘记,尤其是当您是唯一用户时 自定义视图的效果 花时间仔细定义视图界面可减少未来的维护工作 费用。 一种好的做法是始终公开任何会影响 显示或行为 自定义视图

在设计时充分考虑无障碍功能

您的自定义视图必须支持众多用户。这包括使用 残疾、 来防止他们看到或使用触摸屏。为了给残障用户提供支持, 执行以下操作:

  • 使用 android:contentDescription 为输入字段添加标签 属性。
  • 通过调用 sendAccessibilityEvent() 发送无障碍事件 。
  • 支持备用控制器,例如方向键或轨迹球。

如需详细了解如何创建可访问的视图,请参阅 <ph type="x-smartling-placeholder"></ph> 让应用使用起来更没有障碍