7

Estoy buscando escribir un adaptador personalizado para rellenar una vista de lista con 3 textviews por línea. Encontré bastante código de ejemplo para hacer esto, pero el que parecía el mejor era: http://www.anddev.org/custom_widget_adapters-t1796.htmlNo se puede usar LayoutInflater en el adaptador personalizado

Después de algunos retoques menores para solucionar algunos problemas del compilador con el último SDK de Android, lo ejecuté, 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 encontró muchas posibles razones y soluciones para esto. Nada de lo cual cambió 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 han tratado de la manera comentada de conseguir el inflado y el momento descomentado a cabo. He intentado pasar "padre" para inflar así como nulo, y pasar "verdadero", "falso" y omitir por completo el último parámetro. Ninguno de ellos ha funcionado, y todos los ejemplos que he encontrado hasta ahora han sido del 2008, y tengo la sensación de que están un poco desactualizados.

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

Respuesta

6

Soy un principiante también así que tome esta respuesta con un poco de sal, si no funciona, siga adelante y Google un poco más. No estoy familiarizado con AdapterView ya que tradicionalmente tengo ListView o GridView y un adaptador personalizado extendido desde BaseAdapter y luego listView.setAdapter(myCustomAdapter).

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

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

Luego, en la clase que llama WeatherAdapter:

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

También hay que optimizarlo más en el método getView:

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

3

Para el AdaptertView addView método:.

vacío addView (Ver infantil)

no es compatible con este método y lanza una UnsupportedOperationException cuando llamado"(De la documentación Android)

Probablemente el procedimiento de inflado llame al método addView y esto no es posible desde un AdapterView, o es AdapterView.

De la documentación:

"Un objeto adaptador actúa como un puente entre un AdapterView y los datos subyacentes para ese punto de vista.El adaptador proporciona acceso a los datos elementos. El adaptador también es responsable para hacer una vista para cada elemento en el conjunto de datos ".

creo que la operación de inflado se podía hacer de 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

16

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

El false 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 AdapterView s. Por qué es así, me parece totalmente desconcertante, pero el patrón anterior funcionó para mí.

+2

Al usar un 'AdapterView' desea que sus vistas sean independientes del padre,' getView() 'se encarga de adjuntarlo al padre por usted. –

+0

@AustynMahoney No diría 'getView()' se encarga de ello porque ** usted ** es quien lo escribe, prefiero decir ** lo que llame a 'getView()' ** (en otras palabras, el marco) se encarga de adjuntar la vista ** devuelta por ** 'getView()'. – Joffrey

1

@ La respuesta de Axel22 es clave, pero faltan algunas otras cosas en su código. Primero, debe extender BaseAdapter o ArrayAdapter, según sus preferencias. En segundo lugar, desea practicar el uso de un ViewHolder para evitar hacer llamadas excesivas a findViewById y (lo que es más importante) reciclar su View.

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 vistas y utilizar 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 toneladas más ejemplos (y otros consejos de optimización), ver this blog post (o simplemente google para ViewHolder).

Cuestiones relacionadas