Pregunta

Estoy buscando en escribir un adaptador personalizado para rellenar un listview con 3 textviews por línea. He encontrado un poco de ejemplo de código para hacer esto, pero el que parecía el mejor fue en: http://www.anddev.org/custom_widget_adapters-t1796.html

Después de algunos ajustes menores para solucionar algunos problemas de compilación con la última Android SDK, lo tengo funcionando, sólo para obtener la excepción:

  

ERROR / Android Runtime (281): java.lang.UnsupportedOperationException: addView (Ver, LayoutParams) no se admite en AdapterView

Así que hice un montón de investigación y encontraron lotes de posibles motivos y soluciones para esto. Ninguno de los cuales ha cambiado nada. Mi código de adaptador es actualmente:

public class WeatherAdapter extends BaseAdapter {

    private Context context;
    private List<Weather> weatherList;

    public WeatherAdapter(Context context, int rowResID,
                        List<Weather> weatherList ) { 
        this.context = context;
        this.weatherList = weatherList;
    }

    public int getCount() {                        
        return weatherList.size();
    }

    public Object getItem(int position) {     
        return weatherList.get(position);
    }

    public long getItemId(int position) {  
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) { 
        Weather weather = weatherList.get(position);

        //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LayoutInflater inflater = LayoutInflater.from(context);

        View v = inflater.inflate(R.layout.weather_row, null, true);
        TextView cityControl = (TextView)v.findViewById( R.id.city );
        TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
        ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
        return v;
    }

}

Así que he tratado de la manera comentada de conseguir el inflado y el momento no comentada a cabo. He tratado de pasar "padre" para inflar así como nulo, y pasando "verdadero", "falso" y omitiendo por completo el último parámetro. Ninguno de ellos ha trabajado, y todos los ejemplos que he encontrado hasta el momento han sido desde 2008, lo que me da la sensación no están actualizados un poco.

Si alguien puede ayudar con esto, entonces me encantaría resolver el problema.

¿Fue útil?

Solución

Soy un principiante también a fin de tomar esta respuesta con una pizca de sal - si no lo hace el trabajo, seguir adelante y Google un poco más. No está familiarizado con AdapterView desde que habitualmente tienen un ListView o GridView y una costumbre extendida adaptador de un BaseAdapter y luego listView.setAdapter(myCustomAdapter).

Se podría intentar hacer algo como esto dentro de la clase WeatherAdapter:

public void addToList(Weather mWeather) {
    weatherList.add(mWeather);
}

A continuación, en la clase que las llamadas WeatherAdapter:

weatherAdapter.addToList(weatherToAdd);
weatherAdapter.notifyDataSetChanged();

También es necesario optimizarlo más en el método getView:

http://www.youtube.com/watch?v=wDBM6wVEO70

Otros consejos

Creo que esta línea tiene la culpa:

View v = inflater.inflate(R.layout.weather_row, null, true);

Es necesario en su lugar:

View v = inflater.inflate(R.layout.weather_row, parent, false);

La falsa hace que la vista inflado independiente de la matriz, no se le atribuye, que muy extrañamente parece ser el diseño aceptado para vistas personalizadas dentro AdapterViews. ¿Por qué esto es así, me parece totalmente desconcertante, pero el patrón anteriormente trabajó para mí.

Para el método AdaptertView addView:

  

vacío addView (Ver infantil)

     

No se admite Este método y   emite una   UnsupportedOperationException cuando   llamada."(De la documentación Android)

Probablemente el procedimiento de inflar llama al método addView y esto no es posible a partir de una AdapterView, o su AdapterView.

A partir de la documentación:

  

"objeto un adaptador actúa como un puente   entre un AdapterView y la   los datos subyacentes para ese punto de vista. los   Adaptador proporciona acceso a los datos   artículos. El adaptador también es responsable   para la fabricación de una vista para cada elemento de la   conjunto de datos".

Creo que la operación se infle puede hacerse desde una simple actividad que los modelos de su punto de vista y todas las demás operaciones, por ejemplo, la recuperación de datos y mostrar los datos en otras clases.

Esperamos que sea útil!

@ respuesta de Axel22 es clave, pero hay algunas otras cosas que faltan en su código. En primer lugar, usted debe ya sea extendiendo BaseAdapter o ArrayAdapter, dependiendo de su preferencia. En segundo lugar, usted desea conseguir en la práctica de utilizar un ViewHolder para evitar hacer llamadas excesivas a findViewById, y (lo más importante) reciclar su punto de vista.

private Class ViewHolder {
  public TextView cityControl;
  public TextView temperatureControl;
  public ImageView skyControl;
  public ViewHolder(TextView cityControl, TextView temperatureControl, ImageView skyControl) {
    this.cityControl = cityControl;
    this.temperatureControl = temperatureControl;
    this.skyControl = skyControl;
  }

Su función getView puede reciclar y utilizar puntos de vista de la clase ViewHolder de la siguiente manera:

public View getView(int position, View convertView, ViewGroup parent) { 
    Weather weather = weatherList.get(position);
    // This is how you attempt to recycle the convertView, so you aren't 
    // needlessly inflating layouts.
    View v = convertView;
    ViewHolder holder;
    if (null == v) {
        v = LayoutInflater.from(getContext()).inflate(R.layout.weather_row, parent, false);
        TextView cityControl = (TextView)v.findViewById( R.id.city );
        TextView temperatureControl = (TextView)v.findViewById( R.id.temperature );
        ImageView skyControl = (ImageView)v.findViewById( R.id.sky );
        holder = new ViewHolder(cityControl, temperatureControl, skyControl);
        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    holder.cityControl.setText("Metropolis");
    holder.temperatureControl.setText("78");
    holder.skyControl.setImageResource(R.drawable.daily_planet);

    return v;

}

Para más ejemplos de toneladas (y otros consejos de optimización), ver esta entrada del blog (o simplemente google para ViewHolder).

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