Android 属性自定义及使用获取浅析

摘要:
半径=“150dp”/>attrname=“位置”>enumname=“right_top”value=“2”/>enumname=“right_bottom”value=“3”/>attrname=“position”/>&书信电报;privatestaticfinaintRIGHT_TOP=2;
一、概述

相信你已经知道,Android 可使用 XML 标签语言进行界面的定义。每个标签中有一个一个的属性,这些属性有相应的属性值。例如:

<cn.neillee.composedmenu.RotatingArcMenu
	android: 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:background="?attr/barBgColor"
	app:position="left_bottom"
	app:radius="150dp"/>

有两点可以注意到:

  • 其一,在某个自定义 ViewGroup 中,有两个自定义属性 positionradius,与其他属性不同的是,这两个属性的命名空间为 app

  • 其二,系统属性 background 的属性值为 ?attr/barBgColor

二、详细介绍

2.1 自定义属性

这里介绍

app:position="left_bottom"
app:radius="150dp"

的使用。

自定义属性常见于自定义的 View 中,让我们还是以概述中的代码作为例子。自定义属性及其属性值在 /values/attr.xml 中有如下定义:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="position">
        <enum name="left_top" value="0"/>
        <enum name="left_bottom" value="1"/>
        <enum name="right_top" value="2"/>
        <enum name="right_bottom" value="3"/>
    </attr>
    <attr name="radius" format="dimension"/>

    <declare-styleable name="ComposedMenu">
        <attr name="position"/>
        <attr name="radius"/>
    </declare-styleable>
</resources>

在该文件中,枚举了 position 有四个属性值,并为每个属性值提供了不同的 value 值作区分。而 radius 定义为 dimension 引用,表示其值须为 dimension 类型的值。类似地,还有如有其他类型,参考文章 【Android】Android自定义属性,attr format取值类型

接下来如何获取自定义属性值就成了关键。我在自定义 ViewGroup 中使用如下代码获取到用户在 layout 文件中,自定义 ViewGroup 标签下使用到的值。

private static final int LEFT_TOP = 0;
private static final int LEFT_BOTTOM = 1;
private static final int RIGHT_TOP = 2;
private static final int RIGHT_BOTTOM = 3;

protected static final int DEFAULT_RADIUS = 150;
protected static final int DEFAULT_POSITION = RIGHT_BOTTOM;

protected int mRadius;

...
public RotatingArcMenu(Context context, AttributeSet attrs, int defStyleAttr) {
	TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ComposedMenu, defStyleAttr, 0);
	int pos = a.getInt(R.styleable.ComposedMenu_position, DEFAULT_POSITION);
	mRadius = (int) a.getDimension(R.styleable.ComposedMenu_radius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_RADIUS, getResources().getDisplayMetrics()));
	a.recycle();// 使用完后记得回收
}

2.2 获取系统属性

这里介绍 android:background="?attr/barBgColor" 属性的定义与获取。

我之所以如此定义,是为了使得 背景色 能够随着应用的主题切换而变化,最简单的例子就是 夜间模式
首先,我在 values/attr.xml 文件中对 barBgColor 进行定义:

<?xml version="1.0" encoding="utf-8"?>
<resources>
	...
    <attr name="barBgColor" format="color"/>
</resources>

其次,在 values/styles.xml 中对该属性值进行了定义:

<resources>

    <style name="AppDayTheme" parent="Theme.AppCompat.Light.NoActionBar">
		<item name="barBgColor">@color/ZHIHUBlue</item>
	</style>
	<style name="AppNightTheme" parent="Theme.AppCompat.Light.NoActionBar">
		<item name="barBgColor">#263238</item>
	</style>
</resources>

最后,我在控件的属性中对该属性值进行了使用

<cn.neillee.composedmenu.RotatingArcMenu
	android: 
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:background="?attr/barBgColor"
	app:position="left_bottom"
	app:radius="150dp"/>

需要说明的是,可以不再控件属性中使用自定义的属性值,可在代码中进行获取与设置。如:

TypedValue typedValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.barBgColor, typedValue, true);
mRotatingArcMenu.setBackgroundColor(typedValue.data);

这里使用到了 TypedValue 这个类。

2.3 关于 TypedValue

详细介绍见官网:
https://developer.android.com/reference/android/util/TypedValue.html

此处我仅对我在上一小节中的使用做简单介绍。在使用过程中,我观察到在不同主题下,TypedValue 读取到的值如下:

在 DayTheme 中,由于我定义的是 @color/ZHIHUBlue ,对color的引用即 resourceId。因此,typedValue.resourceId 有值,且直接等效于 R.color.ZHIHUBlue,typedValue.type=TYPE_INT_COLOR_RGB8,表示 typedValue.data 有值,为8位的颜色代码值(#rrggbb)。
Android 属性自定义及使用获取浅析第1张

在 NightTheme 中,由于我定义的是 #263238,颜色代码值。因此,TypedValue.resourceId 无值,但 typedValue.type=TYPE_INT_COLOR_RGB8,表示 typedValue.data 有值,为8位的颜色代码(#rrggbb)。
Android 属性自定义及使用获取浅析第2张

此文在我的 Github Pages 上同步发布,地址为:Android-属性自定义及使用获取浅析

免责声明:文章转载自《Android 属性自定义及使用获取浅析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Vue指令和事件Toolbar 工具栏 菜单 标题栏 Menu下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JDK自带方法实现AES对称加密

请看代码。 1 package jdbc.pro.lin; 2 3 import java.security.InvalidAlgorithmParameterException; 4 import java.security.InvalidKeyException; 5 import java.security.NoS...

火柴棍等式

现手中有m(m<=24)个火柴棍,希望拼出A+B=C等式。等式中的A、B、C均为火柴棍拼出来的整数(若该数非0,则最高位不能为0)。 注意:1、加号与等号各自需要2根火柴棍; 2、如果A不等于B,则A+B=C与B+A=C视为不同的等式(三者均大于0); 3、所有根火柴棍必须全都用上。 #include<stdio.h> int fun(i...

一、数组---两数之和(升级版)

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。 说明: 返回的下标值(index1 和 index2)不是从零开始的。你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。示例: 输入: numbers = [2...

Ajax取PHP JSON数据并显示

<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-sc...

element 导航菜单 控制路由跳转

首先复制官网的例子,在这基础上再修改成我们想要的样子。 <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"> <el-menu-item index="1">处理中心</el...

JS 的map和array集合组合返回JSON字符串

使用map 和array 返回自定义对象的JSON字符串: function getObjectJSON() {   var array = new Array();   for (var i = 0; i < 5; i++) {     var map = {};     map[1] = "张三";     map[2] = "李四";...