6

Ich versuche, eine Geschwistersteuerung über XML zu referenzieren.Wie wird während des Aufpumpens auf ein anderes Steuerelement Bezug genommen?

ein Attribut zu deklarieren eine ID von MyTextView zu verweisen:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <declare-styleable name="MyTextView"> 
     <attr name="valueTextViewId" format="reference" /> 
    </declare-styleable> 
</resources> 

fragment_example.xml - Wie benutzerdefinierte Attribute verwenden:

<!-- Declare a "Title" text view that references a "Value" --> 
<com.example.MyTextView 
    android:id="@+id/foo" 
    example:valueTextViewId="@id/bar" 
    ... /> 

<!-- Depending on the "text" attribute of this "Value" textview --> 
<!-- Do something within "Title" textview --> 
<com.example.MyTextView android:id="@+id/bar" /> 

MyFragment.java - das Aufpumpen Kontrollen

MyTextView Klassenkonstruktors - Während die Inflation etwas mit referenzierten Textview:

public TextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 

    TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.MyTextView); 
    int refId = a.getResourceId(R.styleable.MyTextView_valueTextViewId); 

    // Updated to use context 
    if (refId > -1 && context instanceof Activity) { 
     Activity a = (Activity)context; 
     View v = a.findViewById(refId); 

     // THE PROBLEM: v is null 
     if (v != null) { 
      // In my case, I want to check if the "Value" textview 
      // is empty. If so I will set "this" textColor to gray 
     } 
    } 
} 

in diesem Beispiel v ist immer null. Ich nehme an, weil während der Layout-Inflation die Steuerelemente noch nicht hinzugefügt wurden. Eine andere Sache zu beachten ist, dass dies in einer ist, daher könnte das der Grund sein, warum ich die Ansicht in der übergeordneten Aktivität nicht finden kann.

Ist es möglich, ein Steuerelement von einem anderen so zu referenzieren?

Antwort

2

Ist es möglich, ein Steuerelement von einem anderen wie diesem zu referenzieren?

Es ist möglich, einen weiteren View von einem View zu referenzieren.

Aber zu Eigenschaftsprüfung im Erbauer von View wird nicht geraten.
Es kann nicht garantiert werden, dass ein bestimmter View vor einem anderen während View inflation instanziiert wird.

Vergleichen Sie diese zwei Layouts:
first_layout.xml

<com.example.MyTextView 
    ... 
    android:id="@+id/foo" 
    example:valueTextViewId="@+id/bar" /> 

<com.example.MyTextView 
    ... 
    android:id="@+id/bar" /> 

second_layout.xml

<com.example.MyTextView 
    ... 
    android:id="@+id/bar" /> 

<com.example.MyTextView 
    ... 
    android:id="@+id/foo" 
    example:valueTextViewId="@+id/bar" /> 

In diesem Beispiel ist es klar, dass das Eigentum von dem Konstruktor überprüft in einem dieses Layout wird nicht funktionieren.

Ich bin damit einverstanden, dass es möglich ist, den Verweis auf eine andere View innerhalb eines View zu speichern:

public MyTextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView); 
    mReferenceId = a.getResourceId(R.styleable.MyTextView_valueTextViewId); 
    ... 
} 

private int mReferenceId; 

public View getReferenceViewFromActivity() { 
    if (getContext() instanceof Activity) { 
     return ((Activity)getContext()).findViewById(mReferenceId); 
    return null; 
} 

public View getReferenceView(View view) { 
    return view.findViewById(mReferenceId); 
} 

Aber Sie sollten auf jeden Fall innerhalb der Activity oder Fragment Überprüfung jegliche Eigenschaft tun:

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    MyTextView myTextView = (MyTextView)view.findViewById(R.id.foo); 
    MyReferenceView refView = (MyReferenceView)myTextView.getReferenceView(view); 
    // 
    // do property checking 
    // 
} 
1

Wenn eine Textansicht mit der ID des Balkens innerhalb der ID des Balkens verfügbar ist, können Sie so etwas tun.

<com.example.MyTextView 
    android:id="@+id/foo" 
    ... 
    android:tag="bar" /> 

<com.example.MyTextView android:id="@+id/bar" /> 

und

public TextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 

     int barId = getResources().getIdentifier(getTag(), "id", packageName); 
     TextView bar = mActivity.findViewById(barId); 

    if (bar.getText() == "") { 
     // Gray out this "title" textview 
     setColor(android.R.color.gray); 
    } 

    // maybe set a text change listener to bar to make it future-proof 
} 

ich würde nur die ID als Tag auf Ihrem MyTextView geben, so dass Sie nicht ein neues Attribut erstellen müssen.

+0

Das ist interessant und ein Anfang. Ich habe jedoch nicht die Fähigkeit, "Mactivity" zu übergeben, wenn ich 'LayoutInflator' verwende. Das wundert mich ob das Kontextattribut im Ctor die Aktivität selbst ist ... –

+1

kann es sein. check über 'if (context instanceof Activity)' und dann umwandeln '' ((Activity) context) ' – r2DoesInc

+0

Vielleicht mach diese Logik nicht im Konstruktor. Fügen Sie MyTextView eine Methode für 'setActivityValue (mActivity)' hinzu und dann, nachdem die Aktivität explizit festgelegt wurde, führen Sie Ihre Logik des Verbergens oder Manipulierens der anderen Textansicht aus. – r2DoesInc

1

Speichern Sie die Referenzen in Ihren eigenen privaten Feldern im Konstruktor. Speichern Sie in Ihrem Fall die RefId in einem privaten Feld. Dann verwenden Sie sie in der onMeasure Funktion.


Ich würde empfehlen Sie nicht Ihren Ansatz zu verwenden, die referenzierten Ansicht zu bekommen. Wenn Sie sich die üblichen Fälle wie die RelativeView-Kinder layout_toLeftOf ansehen, werden Sie feststellen, dass die ID immer eines der untergeordneten Elemente der RelativeView und damit ein Geschwister der aktuellen Ansicht ist. In diesem Fall ist es einfach, die Ansicht zu erhalten, indem Sie das übergeordnete Element mit getParent() abrufen, es in ViewGroup umwandeln (nicht unbedingt) und die Ansicht mit der Referenz unter Verwendung von findViewById finden. Wenn Sie diese Art von Einschränkung durchführen können (ID sollte ein Geschwister sein), können Sie vielleicht diese Abhängigkeit vom Kontext loswerden, die Ihre Ansicht schließlich unbrauchbar machen wird. Sie sind wahrscheinlich besser dran, die Ansicht mit setBla() zu setzen, anstatt Ihr eigenes Attribut zu verwenden (Vielleicht werfen Sie einen Laufzeitfehler in Ihre onMeasure, wenn dieser Setter nicht aufgerufen wurde).

1

Soweit ich weiß, gibt es keine Garantie dafür, dass das Activity's Layout fertig ist und in der onCreateView() Methode erstellt wird.

Sie könnten versuchen, diesen Ansatz statt:

@Override 
public void onActivityCreated(Bundle savedInstanceState){ 
    mView.customMethodToSetTextColor(...) 
} 

onActivityCreated() aufgerufen wird, wenn die Aktivität Schöpfung beendet ist, und nach onCreateView() in den Fragmentlifecycle.