2017-02-06 2 views
1

Ich weiß, wie eine benutzerdefinierte Stil Attributdefinition erstellen und den Wert in einer benutzerdefinierten Ansicht erhalten (von diesen link):Android xml globaler benutzerdefinierter Tag ohne Subclassing

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

Aber ich bin ich gefragt, ob Es ist Es ist möglich, ein "globales" Tag zu definieren, das ich auf jede Ansicht anwenden kann, entweder benutzerdefiniert oder vom Android SDK.

Lasst uns sagen, dass ich dieses Attribut enthält, eine statische Methode, um die Ansichten ausführen wollen, aber jede Bezugnahme auf die Ansicht (wie findViewById) zu vermeiden:

<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) {} 

Ist das überhaupt möglich?

bearbeiten

Nur um zu klären, was brauche ich wirklich eine Zeichenfolge ist. Das Ziel besteht darin, eine Zeichenfolge in eine andere umzuwandeln und der Texteigenschaft den neuen Wert zuzuweisen.

Mein env ist Xamarin aber jeder nativen Ansatz könnte zu Xamarin übersetzt werden, so dass alle Vorschläge sind willkommen

Antwort

1

Theme Versuchen?

Ein Design ist ein Stil, der auf eine gesamte Aktivität oder Anwendung angewendet wird und nicht auf eine einzelne Ansicht (wie im obigen Beispiel). Wenn ein Stil als Thema angewendet wird, wendet jede Ansicht in der Aktivität oder Anwendung jede Stileigenschaft an, die sie unterstützt.

Hinweis: arbeiten Sie nur für die Eigenschaft der Ansicht unterstützt.

Edit # 1

wenn Sie eine andere Zeichenfolge auf jeder Ansicht übergeben möchten, verwenden Sie einfach android:tag

so etwas wie:

<TextView 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:tag="key" /> 

und die Zeichenfolge

bekommen
String key = textView.getTag(); 

Bearbeiten # 2

Setzen Sie ein Tag, um die gewünschte Ansicht zu identifizieren.

der Tätigkeit, laufen alle Ansichten wie die identifizierte Ansicht finden

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. 
    } 
} 

der Viewgroup Teil the post

+0

Ein Thema würde den gleichen Wert auf alle Ansichten gelten , Recht? Ich muss eine andere Zeichenfolge in jeder Ansicht übergeben – xleon

+0

, wenn Sie nur eine Zeichenfolge übergeben möchten, versuchen Sie Android: Tag – AssIstne

+0

Nun, ich möchte eine Zeichenfolge übergeben und führen Sie einige Code automatisch ohne FindViewById – xleon

0

überprüfen kann ich es selbst nicht ausprobiert, aber theoretisch, können Sie es tun. Ein Beispiel finden Sie in der Calligraphy library.

können Sie globale Attribute deklarieren (wie sie im Rahmen tun) direkt in einer Werte-Ressource-Datei:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <attr name="myCustomAttr" format="string"/> 
</resources> 

Dann können Sie es zu jeder Ansicht hinzufügen ohne Präfix (Sie werden allerdings einen Lint Fehler haben):

<TextView 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    myCustomAttr="key" 
    tools:ignore="MissingPrefix" /> 

Und schließlich sollten Sie es aus Ihrer Sicht AttributeSet (in der Ansicht Konstruktor gegeben abgerufen werden können,).

String myCustomValue = attrs.getAttributeValue(R.attr.myCustomAttr); 

Es gibt ein Problem, wenn Sie aber nicht über eine benutzerdefinierte Ansicht erstellen: mein Wissen, Sie haben keinen Zugriff auf die AttributeSet nach einer Ansicht erstellt wird. Sie müssen sich irgendwo während der Layout-Inflation haken ...

+0

Dies funktioniert in Kalligraphie ohne benutzerdefinierte Ansichten, weil es den LayoutInflater durch Erstellen eines Proxy-Kontext entführt. Dies ist ein komplexer Ansatz, insbesondere weil AppCompat dies auch tut. Daher empfehle ich es nicht. – BladeCoder

+0

Ja, du hast Recht. Die Lösung eines globalen Attributs funktioniert nur, wenn das OP es auf mehrere benutzerdefinierte Ansichten anwenden möchte (anstatt für jede benutzerdefinierte Ansicht ein deklarationsfähiges Format zu haben). Das Einbeziehen des Layout-Inflationsprozesses ist komplex und fehleranfällig, und ich würde es auch nicht empfehlen. Es gibt wahrscheinlich eine Möglichkeit, auf die Ansicht zu zielen, die das OP ändern möchte. –

0

Basierend auf Ihrer Hilfe (@assistne) habe ich eine rekursive Methode gefunden, die den gesamten Viewbaum nach Sichten mit einem Tag durchsuchen wird, der mit "translate:" beginnt. Bisher funktioniert es wie ein Zauber:

<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"/> 

Helper-Klasse (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); 
     } 
    } 
} 

Auf Aktivität OnCreate:

I18NAndroidHelper.Translate(this);