2017-02-06 6 views
1

Я знаю, как создать определение атрибута пользовательского стиля и получить значение в настраиваемое представление (от этого link):Android XML глобальный пользовательский тег без подклассов

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0); 
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute); 

Но если I'm подмигнули интересно можно определить «глобальный» тег, который я могу применить к любому представлению, как пользовательскому, так и 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) {} 

Является ли это вообще возможно?

Редактировать

Просто чтобы прояснить, что мне действительно нужно это строка. Целью является преобразование строки в другую и назначение нового значения для свойства text.

Мой окр является Xamarin но любой нативный подход может быть переведен на Xamarin поэтому все предложения приветствуются

ответ

1

Попробуйте Theme?

Тема - это стиль, применяемый ко всей деятельности или приложению, а не индивидуальный вид (как в примере выше). Когда стиль применяется как тема, каждый вид в действии или приложении будет применять каждое свойство стиля, которое поддерживает.

Примечание: просто работайте для свойства, которое поддерживает вид.

Редактировать # 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

установить тег, чтобы определить, какой вид вы хотите.

в деятельности, перебирать все точки зрения, чтобы найти определенную точку зрения, как

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

+0

Тема будет применяться одинаковое значение для всех представлений , правильно? Мне нужно передать другую строку в каждом представлении – xleon

+0

, если вы просто хотите передать строку, попробуйте андроид: tag – AssIstne

+0

Ну, я хочу передать строку en, выполнить некоторый код автоматически, не используя FindViewById – xleon

0

Я не пробовал сам, но теоретически, вы можете это сделать. См. Пример 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 после View создается. Вам придется зацепить себя где-нибудь во время макетирования ...

+0

Это работает в каллиграфии без пользовательских представлений, потому что это захватывает LayoutInflater, создавая прокси-контекст. Это сложный подход, особенно потому, что AppCompat также делает это, поэтому я не рекомендую его. – BladeCoder

+0

Да, вы правы. Решение глобального атрибута работает только в том случае, если OP хочет применить его к нескольким пользовательским видам (вместо того, чтобы иметь декларативный стиль для каждого пользовательского представления). Привязка к структуре инфляции сложна и подвержена ошибкам, и я бы тоже ее не рекомендовал. Вероятно, есть какой-то способ настроить таргетинг на вид, который OP хочет изменить. –

0

Вы можете сделать это с помощью a @BindingAdapter method, используя библиотеку привязки данных.

+0

Это выглядит довольно хорошо. К сожалению, он недоступен в Xamarin.Android. – xleon

0

Основываясь на вашей помощи (@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"/> 

Вспомогательный класс (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); 
     } 
    } 
} 

На активность OnCreate:

I18NAndroidHelper.Translate(this); 
Смежные вопросы