2012-06-14 17 views
17

zrobiłem następującoJak przekazać odwołanie widoku do niestandardowego widoku systemu Android?

1) stworzenie styleable

<declare-styleable name="Viewee"> 
    <attr name="linkedView" format="reference"/> 
</declare-styleable> 

2) zdefiniowanie niestandardowego widoku układu

<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:background="#ffc0"> 
    <TextView 
      android:id="@+id/custom_text" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:text="[text]" 
      /> 
</LinearLayout> 

3) tworzenie wymaganej klasy

public class Viewee extends LinearLayout 
{ 
public Viewee(Context context, AttributeSet attributeSet) 
{ 
    super(context, attributeSet); 
    View.inflate(context, R.layout.viewee, this); 
    TextView textView = (TextView) findViewById(R.id.custom_text); 
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee); 
    int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0); 
    if (id != 0) 
    { 
     View view = findViewById(id); 
     textView.setText(((TextView) view).getText().toString()); 
    } 

    typedArray.recycle(); 
} 
} 

i wreszcie działanie takie jak poniżej:

<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res/com.ns" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical"> 
    <TextView 
      android:id="@+id/tvTest" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:text="android"/> 
    <com.ns.Viewee 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      app:linkedView="@+id/tvTest" 
      /> 
</LinearLayout> 

teraz chociaż ja otrzymaliśmy niezerowej id w Viewee constractor, findViewById(id) retuns null i NullPointerException occures.

czego mi brakuje?

I did it as described here

Odpowiedz

17

Znalazłem odpowiedź!

Problem dotyczył findViewById(id) i gdzie go nazwałem. findViewById szuka tylko widoku podrzędnego, a widok nie istnieje na wyższym poziomie hierarchii, jak mówi documentation. Muszę więc nazywać coś takiego, jak getRootView().findViewById(id), ale to również zwraca null, ponieważ tam, gdzie je nazwałem, nie było to corrent.

Sam w sobie nie został jeszcze podłączony do swojego korzenia, więc wywołanie wywołuje NullPointerException.

Więc jeśli zadzwonię pod numer getRootView().findViewById(id) gdzie indziej po utworzeniu, to działa poprawnie i zarówno "@+id/tvTest" jak i "@id/tvTest" są poprawne. Testowałem to!

odpowiedź brzmi następująco

public class Viewee extends LinearLayout 
{ 
    public Viewee(Context context, AttributeSet a) 
    { 
     super(context, attributeSet); 
     View.inflate(context, R.layout.main6, this); 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee); 
     int id = t.getResourceId(R.styleable.Viewee_linkedView, 0); 
     if (id != 0) 
     { 
      _id = id; 
     } 

     t.recycle(); 
    } 

    private int _id; 

    public void Foo() 
    { 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     View view = getRootView().findViewById(_id); 
     textView.setText(((TextView) view).getText().toString()); 
    } 
} 

i Foo jest wywoływana, gdy jest to wymagane na przetwarzanie widok poprzez jego numer referencyjny w innym miejscu w swojej działalności i tym podobne.

Kredyt w całości trafia do osób, które wniosły wkład w this post. Nie widziałem tego postu przed przesłaniem pytania.

+0

NIE umieszczaj go w 'onDraw', ale w' onAttachedToWindow' Umieszczając go w onDraw będzie wywoływał X razy na sekundę metodę, może być 60 razy na sekundę. @ Danielylson możesz usunąć swój komentarz? –

2

Twój opisane android:id jest ustawiony na app:linkedView="@+id/tvTest. Jednak do utworzenia nowego identyfikatora o nazwie "tvTest" służy @+id/tvTest. To, co chcesz zrobić, to użyć app:linkedView="@id/tvTest.

+0

Zastosowałem twoją odpowiedź, chociaż 'Widok view = findViewById (id);' nadal zwraca null! – anonim

+0

Dlaczego używasz "id" do przechowywania identyfikatora widoku? Powinno być całkiem proste używanie 'R.id.foo' zamiast tworzenia innej zmiennej. Ponadto, nie mogę powiedzieć przez twój komentarz, czy zmieniłeś atrybut 'app: linkedView' twojego elementu' 'na' "@ id/tvTest'. –

+0

Muszę przytrzymać' id 'ponieważ' Viewee' jest niestandardowym widokiem odwołującym się do innego widoku dla rezononu.Nie mogę odwoływać się do połączonego widoku jako 'R.id.foo', jak powiedziałeś, a co jeśli użyję' Viewee' w innym układzie, gdzie 'R .id.foo' nie istnieje? Zrobiłem tak, jak zaleciłeś i zmieniłeś '' @ + id/tvTest "' na '" @ id/tvTest "' ale bez powodzenia – anonim

8

Wiem, że to stare pytanie, ale pomyślałem, że dodam inny sposób robienia tego, ponieważ chciałem zamknąć wszystko w moim widoku niestandardowym.

Zamiast dzwonić z zewnątrz, inny sposób na uzyskanie widoku wyżej w hierarchii, mam podpięty do onAttachedToWindow() zamiast:

public class MyCustomView extends LinearLayout { 
    private int siblingResourceId; 
    private View siblingView; 

    public MyCustomView(Context context, AttributeSet a) { 
     super(context, attributeSet); 
     View.inflate(context, R.layout.main6, this); 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee); 
     siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, 0); 
     t.recycle(); 
    } 

    @Override 
    public void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     if (siblingResourceId != 0) { 
      siblingView = getRootView().findViewById(siblingId); 
     } 
    } 
} 

onAttachedToWindow nazywa się dość wcześnie, ale widocznie na tyle późno, Cała hierarchia widoków została ustalona.Działa to bezbłędnie dla moich potrzeb i jest trochę bardziej kontrolowana i nie wymaga interakcji z zewnątrz do pracy ;-)

Powiązane problemy