obtainStyledAttributes 工作错误
obtainStyledAttributes works wrong
我正在尝试创建自己的键盘。使用 Android 键盘不足以完成我的任务,因此我决定直接从 View.class 创建继承者 class。作为基础,我决定使用 Keyboard.class 的代码,然后开始一项一项地进行更改。
我在尝试编译 class 时遇到了很多问题,使用了一些反射和 hack 来获取私有字段。我创建了文件 attrs 以便能够使用键盘的属性和标签。最后 class compilled 并且知道它崩溃了,因为应该来自膨胀的参数是空的。
我发现的是方法 context.obtainStyledAttributes(attrs, R.styleable.MyKeyboardView); returns 错误的结果和 a.getIndexCount();之后 returns 0.
这是我的 attr.xml 文件:
<resources>
<declare-styleable name="MyKeyboardView">
<attr name="keyBackground" format="reference" />
<attr name="keyTextSize" format="dimension" />
<attr name="labelTextSize" format="dimension" />
<attr name="state_long_pressable" format="boolean" />
<attr name="keyTextColor" format="color" />
<attr name="keyPreviewLayout" format="reference" />
<attr name="keyPreviewOffset" format="dimension" />
<attr name="keyPreviewHeight" format="dimension" />
<attr name="verticalCorrection" format="dimension" />
<attr name="shadowColor" format="color" />
<attr name="shadowRadius" format="float" />
<attr name="backgroundDimAmount" format="float" />
<attr name="popupLayout" format="reference" />
</declare-styleable>
这是我键盘的一部分 class:
public MyKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, Resources.getSystem().getIdentifier("keyboardViewStyle", "attr", "android"));
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.MyKeyboardView);
LayoutInflater inflate =
(LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int previewLayout = 0;
int keyTextSize = 0;
int n = a.getIndexCount();
这是我在布局中使用键盘的方式:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_gravity="bottom">
<com.test.features.keyboard.MyKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="2.5dip"
android:keyPreviewHeight="@dimen/key_height"
android:shadowRadius="0"
android:keyPreviewLayout="@layout/keyboard_key_preview"
android:keyPreviewOffset="0dp"
android:keyBackground="@drawable/keyboard_key_background"
android:keyTextColor="@color/keyboard_key_color"
android:background="@color/primary"
android:popupLayout="@layout/keyboard_popup_layout"/>
试过像这样使用它,length() 返回了 11,但是 switch case 几乎找不到匹配项。如果找到,则使用默认值:
int n = a.length();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.MyKeyboardView_keyBackground:
mKeyBackground = a.getDrawable(attr);
break;
case R.styleable.MyKeyboardView_verticalCorrection:
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewLayout:
previewLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewOffset:
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewHeight:
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
break;
case R.styleable.MyKeyboardView_keyTextSize:
mKeyTextSize = a.getDimensionPixelSize(attr, 18);
break;
case R.styleable.MyKeyboardView_keyTextColor:
mKeyTextColor = a.getColor(attr, 0xFF000000);
break;
case R.styleable.MyKeyboardView_labelTextSize:
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
break;
case R.styleable.MyKeyboardView_popupLayout:
mPopupLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowColor:
mShadowColor = a.getColor(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowRadius:
mShadowRadius = a.getFloat(attr, 0f);
break;
}
}
您的自定义 View
属性将位于您应用的命名空间中,而不是系统命名空间中,因此当它们带有系统命名空间前缀时,在给定的 AttributeSet
中找不到它们.
直接在 <MyKeyboardView>
标签或祖先标签中添加 xmlns:app="http://schemas.android.com/apk/res-auto"
命名空间声明,并将所有属性的前缀更改为 app
.
请注意,前缀可以是您喜欢的任何有效名称,但 app
可能是最常见的名称。
我正在尝试创建自己的键盘。使用 Android 键盘不足以完成我的任务,因此我决定直接从 View.class 创建继承者 class。作为基础,我决定使用 Keyboard.class 的代码,然后开始一项一项地进行更改。
我在尝试编译 class 时遇到了很多问题,使用了一些反射和 hack 来获取私有字段。我创建了文件 attrs 以便能够使用键盘的属性和标签。最后 class compilled 并且知道它崩溃了,因为应该来自膨胀的参数是空的。
我发现的是方法 context.obtainStyledAttributes(attrs, R.styleable.MyKeyboardView); returns 错误的结果和 a.getIndexCount();之后 returns 0.
这是我的 attr.xml 文件:
<resources>
<declare-styleable name="MyKeyboardView">
<attr name="keyBackground" format="reference" />
<attr name="keyTextSize" format="dimension" />
<attr name="labelTextSize" format="dimension" />
<attr name="state_long_pressable" format="boolean" />
<attr name="keyTextColor" format="color" />
<attr name="keyPreviewLayout" format="reference" />
<attr name="keyPreviewOffset" format="dimension" />
<attr name="keyPreviewHeight" format="dimension" />
<attr name="verticalCorrection" format="dimension" />
<attr name="shadowColor" format="color" />
<attr name="shadowRadius" format="float" />
<attr name="backgroundDimAmount" format="float" />
<attr name="popupLayout" format="reference" />
</declare-styleable>
这是我键盘的一部分 class:
public MyKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, Resources.getSystem().getIdentifier("keyboardViewStyle", "attr", "android"));
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.MyKeyboardView);
LayoutInflater inflate =
(LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int previewLayout = 0;
int keyTextSize = 0;
int n = a.getIndexCount();
这是我在布局中使用键盘的方式:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_gravity="bottom">
<com.test.features.keyboard.MyKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="2.5dip"
android:keyPreviewHeight="@dimen/key_height"
android:shadowRadius="0"
android:keyPreviewLayout="@layout/keyboard_key_preview"
android:keyPreviewOffset="0dp"
android:keyBackground="@drawable/keyboard_key_background"
android:keyTextColor="@color/keyboard_key_color"
android:background="@color/primary"
android:popupLayout="@layout/keyboard_popup_layout"/>
试过像这样使用它,length() 返回了 11,但是 switch case 几乎找不到匹配项。如果找到,则使用默认值:
int n = a.length();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.MyKeyboardView_keyBackground:
mKeyBackground = a.getDrawable(attr);
break;
case R.styleable.MyKeyboardView_verticalCorrection:
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewLayout:
previewLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewOffset:
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewHeight:
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
break;
case R.styleable.MyKeyboardView_keyTextSize:
mKeyTextSize = a.getDimensionPixelSize(attr, 18);
break;
case R.styleable.MyKeyboardView_keyTextColor:
mKeyTextColor = a.getColor(attr, 0xFF000000);
break;
case R.styleable.MyKeyboardView_labelTextSize:
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
break;
case R.styleable.MyKeyboardView_popupLayout:
mPopupLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowColor:
mShadowColor = a.getColor(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowRadius:
mShadowRadius = a.getFloat(attr, 0f);
break;
}
}
您的自定义 View
属性将位于您应用的命名空间中,而不是系统命名空间中,因此当它们带有系统命名空间前缀时,在给定的 AttributeSet
中找不到它们.
直接在 <MyKeyboardView>
标签或祖先标签中添加 xmlns:app="http://schemas.android.com/apk/res-auto"
命名空间声明,并将所有属性的前缀更改为 app
.
请注意,前缀可以是您喜欢的任何有效名称,但 app
可能是最常见的名称。