Android xml 没有子类化的全局自定义标签
Android xml global custom tag without subclassing
我知道如何创建自定义样式属性定义并在自定义视图中获取值(来自此 link):
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);
但我想知道是否可以定义一个 "global" 标签,我可以将其应用于任何视图,无论是自定义视图还是来自 Android SDK。
假设我想对包含该属性的视图执行一个静态方法,但要避免对视图的任何引用(如 FindViewById):
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
whatever:custom_global_tag="key" />
MyStaticClass.Process(View view, String key) {}
这可能吗?
编辑
澄清一下,我真正需要的是一个字符串。目标是将一个字符串转换为另一个字符串并将新值分配给文本 属性.
我的环境是 Xamarin,但任何本机方法都可以转换为 Xamarin,因此欢迎所有建议
尝试Theme?
A theme is a style applied to an entire Activity or application, rather than an individual View (as in the example above). When a style is applied as a theme, every View in the Activity or application will apply each style property that it supports.
注意:仅适用于 属性 视图支持。
编辑 #1
如果您想在每个视图上传递不同的字符串,只需使用 android:tag
类似于:
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="key" />
并获取字符串
String key = textView.getTag();
编辑#2
设置一个标签来标识您想要的视图。
在activity中,遍历所有视图以找到像
这样标识的视图
final ViewGroup viewGroup = (ViewGroup)((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
for(int i = 0; i < viewGroup.getChildCount(); i++) {
View childView = viewGroup.getChildAt(i);
if ("identificaton".equals(childView.getTag())) {
// do some work to child view.
}
}
viewGroup部分可以勾选the post
我自己没试过,不过理论上是可以的。有关示例,请参见 Calligraphy library。
您可以直接在值资源文件中声明全局属性(就像它们在框架中所做的那样):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myCustomAttr" format="string"/>
</resources>
然后你可以将它添加到任何视图而无需任何前缀(但是你会遇到 Lint 错误):
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myCustomAttr="key"
tools:ignore="MissingPrefix" />
最后,您应该能够从您的视图 AttributeSet 中检索它(在视图构造函数中给出)。
String myCustomValue = attrs.getAttributeValue(R.attr.myCustomAttr);
如果您不创建自定义视图,则会出现问题:据我所知,创建视图后您无权访问 AttributeSet。你将不得不在布局过程中将自己挂在某个地方 inflation...
您可以使用数据绑定库 a @BindingAdapter
method 完成此操作。
根据您的帮助 (@assistne),我最终得到了一种递归方法,该方法将扫描整个视图树以查找带有以 "translate:" 开头的标签的视图。到目前为止,它就像一个魅力:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="translate:TextWithLineBreakCharacters" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="translate:Animals"/>
助手 class (Xamarin/C#):
public static class I18NAndroidHelper
{
public static void Translate(object view)
{
if(view is TextView)
{
var textView = (TextView)view;
var tag = (string)textView.Tag;
if(tag != null && tag.StartsWith("translate:", StringComparison.Ordinal))
{
var key = tag.Split(new [] {":"}, StringSplitOptions.None)[1];
textView.Text = key.Translate(); // Translate() is an string extension method
}
}
else if(view is ViewGroup)
{
var viewGroup = (ViewGroup)view;
var childCount = viewGroup.ChildCount;
for(var i = 0; i < childCount; i++)
Translate(viewGroup.GetChildAt(i));
}
else if(view is Activity)
{
var activity = (Activity)view;
var content = activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
Translate(content);
}
}
}
在 Activity OnCreate
:
I18NAndroidHelper.Translate(this);
我知道如何创建自定义样式属性定义并在自定义视图中获取值(来自此 link):
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);
但我想知道是否可以定义一个 "global" 标签,我可以将其应用于任何视图,无论是自定义视图还是来自 Android SDK。
假设我想对包含该属性的视图执行一个静态方法,但要避免对视图的任何引用(如 FindViewById):
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
whatever:custom_global_tag="key" />
MyStaticClass.Process(View view, String key) {}
这可能吗?
编辑
澄清一下,我真正需要的是一个字符串。目标是将一个字符串转换为另一个字符串并将新值分配给文本 属性.
我的环境是 Xamarin,但任何本机方法都可以转换为 Xamarin,因此欢迎所有建议
尝试Theme?
A theme is a style applied to an entire Activity or application, rather than an individual View (as in the example above). When a style is applied as a theme, every View in the Activity or application will apply each style property that it supports.
注意:仅适用于 属性 视图支持。
编辑 #1
如果您想在每个视图上传递不同的字符串,只需使用 android:tag
类似于:
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="key" />
并获取字符串
String key = textView.getTag();
编辑#2
设置一个标签来标识您想要的视图。
在activity中,遍历所有视图以找到像
这样标识的视图final ViewGroup viewGroup = (ViewGroup)((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
for(int i = 0; i < viewGroup.getChildCount(); i++) {
View childView = viewGroup.getChildAt(i);
if ("identificaton".equals(childView.getTag())) {
// do some work to child view.
}
}
viewGroup部分可以勾选the post
我自己没试过,不过理论上是可以的。有关示例,请参见 Calligraphy library。
您可以直接在值资源文件中声明全局属性(就像它们在框架中所做的那样):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myCustomAttr" format="string"/>
</resources>
然后你可以将它添加到任何视图而无需任何前缀(但是你会遇到 Lint 错误):
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myCustomAttr="key"
tools:ignore="MissingPrefix" />
最后,您应该能够从您的视图 AttributeSet 中检索它(在视图构造函数中给出)。
String myCustomValue = attrs.getAttributeValue(R.attr.myCustomAttr);
如果您不创建自定义视图,则会出现问题:据我所知,创建视图后您无权访问 AttributeSet。你将不得不在布局过程中将自己挂在某个地方 inflation...
您可以使用数据绑定库 a @BindingAdapter
method 完成此操作。
根据您的帮助 (@assistne),我最终得到了一种递归方法,该方法将扫描整个视图树以查找带有以 "translate:" 开头的标签的视图。到目前为止,它就像一个魅力:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="translate:TextWithLineBreakCharacters" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="translate:Animals"/>
助手 class (Xamarin/C#):
public static class I18NAndroidHelper
{
public static void Translate(object view)
{
if(view is TextView)
{
var textView = (TextView)view;
var tag = (string)textView.Tag;
if(tag != null && tag.StartsWith("translate:", StringComparison.Ordinal))
{
var key = tag.Split(new [] {":"}, StringSplitOptions.None)[1];
textView.Text = key.Translate(); // Translate() is an string extension method
}
}
else if(view is ViewGroup)
{
var viewGroup = (ViewGroup)view;
var childCount = viewGroup.ChildCount;
for(var i = 0; i < childCount; i++)
Translate(viewGroup.GetChildAt(i));
}
else if(view is Activity)
{
var activity = (Activity)view;
var content = activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
Translate(content);
}
}
}
在 Activity OnCreate
:
I18NAndroidHelper.Translate(this);