6

Próbuję odwołać się do kontroli rodzeństwa za pomocą XML.Jak powiązać jedną kontrolę z drugą podczas inflacji?

Aby zadeklarować atrybut odwołać identyfikator z MyTextView:

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

fragment_example.xml - Jak korzystać z niestandardowego atrybutu:

<!-- 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 - pompowania formanty

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     // calls MyTextView Ctor 
    View v = inflater.inflate(R.layout.fragment_example, container, false); 
} 

MyTextView klasy konstruktor - Podczas inflacji zrobić coś z wymienionej 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 
     } 
    } 
} 

w tym przykładzie v jest zawsze null. Zakładam, że podczas Inflacji Układu kontrolki nie zostały jeszcze dodane. Inną rzeczą, na którą należy zwrócić uwagę, jest to, że jest to Fragment, dlatego może to być powód, dla którego nie mogę znaleźć widoku w macierzystej aktywności.

Czy możliwe jest odwoływanie się do kontrolki z innego takiego?

Odpowiedz

2

Czy możliwe jest odwoływanie się do formantu z innego takiego?

Możliwe jest odniesienie innego View z View.

Ale nie jest zalecane sprawdzanie właściwości w konstruktorze z View.
Nie ma gwarancji, że konkretna wersja View zostanie utworzona przed innymi podczas View inflation.

Porównaj te dwa układy:
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" /> 

W tym przykładzie, to jasne, że nieruchomość sprawdzanie od konstruktora nie będą działać w jednym z tych układów.

Zgadzam się, że jest to możliwe do przechowywania odwołanie do innego View w View:

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

Ale powinno się zrobić wszelką własność sprawdzanie obrębie Activity lub Fragment:

@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

jeśli tekst z identyfikatorem paska jest dostępny w id paska, możesz zrobić coś takiego.

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

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

i

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 
} 

chciałbym tylko przekazać identyfikator jako znak na swojej MyTextView więc nie trzeba tworzyć nowego atrybutu.

+0

To interesujące i początek. Jednak nie mam możliwości przekazania 'mActivity', gdy używam' LayoutInflator'. To sprawia, że ​​zastanawiam się, czy atrybut kontekstu w Ctor jest samą czynnością ... –

+1

To może być. sprawdź przez 'if (context instanceof Activity)', a następnie rzuć go w kontekst '' ((Activity)) ' – r2DoesInc

+0

Być może nie wykonuj tej logiki w konstruktorze. Dodaj metodę do MyTextView dla 'setActivityValue (mActivity)', a następnie po wyraźnym ustawieniu działania, wykonaj swoją logikę ukrywania lub manipulowania innym tekstem jak tylko możesz. – r2DoesInc

1

Zapisz referencje we własnych prywatnych polach w konstruktorze. W twoim przypadku zapisz refId w prywatnym polu. Następnie użyj ich w funkcji onMeasure.


Zalecam, aby nie używać swojego podejścia do uzyskania widoku z odniesieniami. Jeśli spojrzysz na zwykłe przypadki, takie jak layout_toLeftOf dzieci RelativeView, zauważysz, że id jest zawsze jednym z dzieci RelativeView, a tym samym rodzeństwem bieżącego widoku. W takim przypadku łatwo jest uzyskać widok, pobierając obiekt nadrzędny, używając getParent(), przesyłając go do ViewGroup (niekoniecznie) i znajdując widok z odnośnikiem, używając findViewById. Jeśli możesz zrobić tego rodzaju ograniczenie (id powinno być rodzeństwem), możesz prawdopodobnie pozbyć się tej zależności w kontekście, co ostatecznie sprawi, że twój widok stanie się bezużyteczny. Prawdopodobnie lepiej jest ustawić widok przy użyciu metody setBla() zamiast używać własnego atrybutu (może wyrzucić błąd runtime w swoim narzędziu onMeasure, jeśli nie został wywołany ten program ustawiający).

1

O ile mi wiadomo, nie ma gwarancji, że układ Activity's został ukończony w metodzie onCreateView().

można spróbować tej metody zamiast:

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

onActivityCreated() jest wywoływana, gdy tworzenie aktywny jest zakończona, a po onCreateView() w Fragmentlifecycle.

Powiązane problemy