Pregunta

Estaba usando SimpleCursorAdapter con un archivo XML con algunas vistas definidas en él:

<LinearLayout ...>
    <ImageView android:id="@+id/listIcon" />
    <TextView android:id="@+id/listText" />
</LinearLayout>

Mi objetivo era establecer el color de texto de TextView y el color de fondo del LinearLayout (es decir, cada fila en ListView) programáticamente; El color se devuelve de una base de datos.

Estaba obteniendo NPE cuando intentaba manipular el TextView, por ejemplo, después de haberlo encontrado sin quejas:

TextView tv = (TextView) findViewById(R.id.listText);
tv.setTextColor(color); // NPE on this line

Que es justo; Si hay múltiples entradas en la lista, es razonable suponer que "R.id.listText"No funcionará. Así que extendí el adaptador de SimpleCursor:

public View getView(int position, View convertView, ViewGroup parent) {
    View row = super.getView(position, convertView, parent);
    TextView text = (TextView) row.findViewById(R.id.listText);
    // ImageView icon = (ImageView) row.findViewById(R.id.listIcon);

    // If there's an icon defined
    if (mIcon_id != 0) {
        // icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
        text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
        row.setBackgroundColor(mBackgroundColor);
    }
    return(row);
}

Y obtengo dos errores diferentes:

  • Se lanza un NPE similar "text.setTextColor (mtextcolor)"
  • Si las líneas con ImageView no están commentadas, obtengo un "ClasscastException: android.widget.textview"Donde estoy llamando"Row.FindViewByid (R.ID.Listicon)"

Como referencia, estaba tratando de usar el código de muestra del CommonSware, aplicándolo a mi situación. Enlace (PDF)


Cambiado a esto:

public View getView(int position, View convertView, ViewGroup parent) {
    convertView = super.getView(position, convertView, parent);

    if (convertView == null) convertView = View.inflate(mContext, R.layout.theme_item, null);
    TextView text = (TextView) convertView.findViewById(R.id.listText_tv);
    ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon_iv);

    // If there's an icon defined
    if (mIcon_id != 0) {
        icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
        text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
        convertView.setBackgroundColor(mBackgroundColor);
    }
    bindView(convertView, mContext, mCursor);
    return(convertView);
}

Ahora obtengo una ClassCastException en la siguiente actividad (en el elemento de la lista, haga clic). Nada ha sido modificado en la próxima actividad; Funcionó cuando se usa un SimpleListApter para la lista que tenía entradas (en las cuales el clic conduciría a la Actividad2), por lo que creo que todavía es algo que estoy haciendo mal en esta clase extendida.

¿Fue útil?

Solución

No es cierto que convernview siempre será una instancia existente; Debe verificar si es nulo y luego instanciarlo. Si no, puede cambiarlo tal como lo hizo.

Esto debería ser como:

public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null)
        convertView = //inflate your row here
    View row = convertView;
    //Manipulate the row here
    return(row);
}

Otros consejos

Modificaría el método GetView:

public View getView(int position, View convertView, ViewGroup parent) {
    convertView = View.inflate(getContext(), R.layout.myLayout, null);
    TextView text = (TextView) convertView.findViewById(R.id.listText);
    ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon);

    // If there's an icon defined
    if (mIcon_id != 0) {
      icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
      text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
      convertView.setBackgroundColor(mBackgroundColor);
    }

    return convertView;
}

Creo que estás obteniendo NPE porque estás tratando de crear una vista TextView y una vista de imagen en una vista donde no están allí.

Cuando desea inflar una View de Listview con entradas desde una base de datos, en su actividad define main.xml con una lista de list:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/listView1">
</ListView>

y en el método de OnCreate establece la vista en este XML con setContentView(R.layout.main);. Luego crea su cursor en su base de datos y su adaptador personalizado:

    MySimpleCursorAdapter adapter = new MySimpleCursorAdapter(this, R.layout.entry,
                names, new String[] {Phones.NAME, Phones.NUMBER}, new int[] {
                R.id.listIcon, R.id.listText});
    startManagingCursor(cursor);
    ListView listView = (ListView) findViewById(R.id.listView1);
    listView.setAdapter(adapter);

y define una entrada.xml con su listicon y listtext, donde apunta el adaptador. En mi ejemplo, estoy consultando los nombres y números de la lista de contactos.

En su adaptador personalizado, debe acceder a su View e ImageView dentro de GetView o BindView sin ningún problema.

Aquí Tiene un ejemplo para obtener todos los contactos en su lista de contactos con su imagen, nombre y número, pero utilizando ListActivity en lugar de actividad, y solo un XML con dos vistas de texto y una vista de imagen. Si usa ListActivity, no necesita usar un ListView y no necesita establecer la vista de contenido en la actividad.

¡Espero que ayude!

No olvide poner: Layout_Width y Layout_heigth para cada una de sus puntos de vista.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top