2012-06-14 17 views
17

lo hice de la siguiente manera¿Cómo pasar la referencia de vista a la vista personalizada de Android?

1) La creación de un styleable

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

2) la definición de vista personalizada diseño

<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) Creación de la clase requerida

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

y finalmente en una actividad como la siguiente

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

ahora a pesar de que recibiera no cero id en Viewee constractor, findViewById(id) Retuns nulo y NullPointerException occures.

¿Qué me falta?

I did it as described here

Respuesta

17

¡He encontrado la respuesta!

El problema fue con findViewById(id) y donde lo llamé. findViewById solo busca una vista secundaria no existe una vista en el nivel de jerarquía superior como dice documentation. Así que tengo que llamar a algo como getRootView().findViewById(id) pero eso también devuelve null porque cuando lo llamé no era corrent.

En Viewee el propio constractor Viewee no se ha unido todavía a su raíz por lo que la llamada causa NullPointerException.

Así que si llamo a getRootView().findViewById(id) en otro lugar después de la operación de constracción, funciona bien y tanto "@+id/tvTest" como "@id/tvTest" son correctos. ¡Lo he probado!

la respuesta es la siguiente

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

y Foo se llama cuando se requiere para procesar la vista unido a través de su ID de referencia en otra parte de su actividad y similares.

El crédito es completamente para aquellos tipos que contribuyeron en this post. No había visto esa publicación antes de enviar la pregunta.

+0

NO lo coloque en 'onDraw' sino en' onAttachedToWindow'. Colocarlo en onDraw hará que se llame X veces por segundo el método, podría ser 60 veces por segundo. @DanielWilson ¿puede eliminar su comentario? –

2

Tu descrito android:id se establece en app:linkedView="@+id/tvTest. Sin embargo, @+id/tvTest se usa para crear una nueva identificación con el nombre "tvTest". Lo que quiere hacer es usar app:linkedView="@id/tvTest.

+0

Apliqué su respuesta a través de 'Ver view = findViewById (id);' aún devuelve null! – anonim

+0

¿Por qué está utilizando 'id' para mantener el id de la Vista? Debería ser bastante sencillo usar 'R.id.foo' en lugar de crear otra variable. Además, no puedo decir a través de tu comentario si cambiaste el atributo 'app: linkedView' de tu elemento' 'a' "@ id/tvTest'. –

+0

Tengo que mantener el' id 'porque' Viewee' es una vista personalizada que se refiere a otra vista para un reson. No puedo referirme a la vista vinculada como 'R.id.foo' como dijiste. ¿Qué sucede si uso' Viewee' en otro diseño donde 'R .id.foo' no existe? También hice lo recomendado y cambié '' @ + id/tvTest "' a '" @ id/tvTest "' pero sin éxito. – anonim

8

Sé que esta es una pregunta antigua, pero pensé que agregaría otra forma de hacerlo ya que quería encapsular todo en mi vista personalizada.

En lugar de llamar desde el exterior, otra manera de conseguir una visión más arriba en la jerarquía, me ha enganchado en su lugar onAttachedToWindow():

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 se llama bastante temprano, pero al parecer lo suficientemente tarde como para el toda la jerarquía de vista se ha establecido.Funciona sin problemas para mis necesidades al menos y es un poco más controlado y no necesita interacción de fuera para trabajar ;-)

Cuestiones relacionadas