7

Ich möchte einen benutzerdefinierten Adapter schreiben, um eine Listview mit 3 Textansichten pro Zeile zu füllen. Ich habe ziemlich viel Beispielcode dafür gefunden, aber dasjenige, das am besten zu sein schien, war: http://www.anddev.org/custom_widget_adapters-t1796.htmlLayoutFlater kann nicht im benutzerdefinierten Adapter verwendet werden

Nach ein paar kleineren Verbesserungen, um einige Compilerprobleme mit dem neuesten Android SDK zu beheben, habe ich es laufen lassen, nur die Ausnahme zu erhalten:

ERROR/Android Runtime (281): java.lang.UnsupportedOperationException: addView (Ansicht, LayoutParams) nicht in AdapterView unterstützt

Also habe ich eine Menge Forschung und fand viele mögliche Gründe und Korrekturen dafür. Nichts davon hat etwas verändert. Mein Adapter Code ist zur Zeit:

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

} 

So habe ich versucht, den Kommentar gesetzt Weg, um die Aufblaseinrichtung zu bekommen, und die zur Zeit unkommentiert aus. Ich habe versucht, "Elternteil" zu übergeben, sowie Null, und "wahr", "falsch" zu übergeben und vollständig den letzten Parameter wegzulassen. Keiner von ihnen hat funktioniert, und alle Beispiele, die ich bisher gefunden habe, stammen aus dem Jahr 2008, und ich habe das Gefühl, dass sie ein bisschen veraltet sind.

Wenn jemand damit helfen könnte, würde ich gerne das Problem lösen.

Antwort

6

Ich bin ein Anfänger auch so nehmen Sie diese Antwort mit einer Prise Salz - wenn es nicht funktioniert, weitermachen und Google mehr. Nicht vertraut mit AdapterView, da ich traditionell eine ListView oder GridView und einen benutzerdefinierten Adapter von einem BaseAdapter und dann listView.setAdapter(myCustomAdapter) verlängert haben.

Sie könnten versuchen, so etwas wie dies in der WeatherAdapter Klasse machen:

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

Dann in der Klasse, die WeatherAdapter ruft:

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

Darüber hinaus müssen Sie es in dem getView Verfahren optimieren:

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

3

Für die AdaptertView addView Methode.

Leere addView (Kinder)

Diese Methode wird nicht unterstützt und wirft einen UnsupportedOperationException wenn genannt“(Aus Android Dokumentation)

Wahrscheinlich ruft die Aufblasprozedur das addView-Verfahren auf, und dies ist nicht möglich von AdapterView oder AdapterView.

Aus der Dokumentation:

„Ein Adapter-Objekt dient als Brücke zwischen einem AdapterView und die zugrunde liegenden Daten für diese Ansicht.Der Adapter ermöglicht den Zugriff auf die Daten Artikel. Der Adapter ist auch verantwortlich für die Herstellung einer Ansicht für jedes Element in der Datensatz“.

Ich denke, dass die aufblähenden Betrieb von einer einfachen Aktivität getan werden könnte, dass die Modelle Ihrer Sicht und alle anderen Operationen, zum Beispiel ., Daten und zeigt Daten in anderen Klassen Abrufen

Hoffe, dass es hilfreich sein wird

16

ich glaube, diese Linie schuld ist:

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

Sie müssen stattdessen:

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

Die falsche machen die aufgeblasene Ansicht unabhängig von der Mutter, nicht mit ihm verbunden, was sehr seltsam das akzeptierten Design für benutzerdefinierte Ansichten innerhalb AdapterView s zu sein scheint. Warum das so ist, finde ich absolut verwirrend, aber das obige Muster hat für mich funktioniert.

+2

Wenn Sie ein 'AdapterView' verwenden, möchten Sie, dass Ihre Ansichten unabhängig vom übergeordneten Objekt sind,' getView() 'kümmert sich darum, dass es an das übergeordnete Objekt angehängt wird. –

+0

@AustynMahoney Ich würde nicht sagen, 'getView()' kümmert sich darum, da ** du ** derjenige ist, der es schreibt, würde ich lieber sagen ** was auch immer 'getView()' ** heißt (mit anderen Worten, das Framework) sorgt dafür, dass die von ** 'getView()' zurückgegebene View ** angehängt wird. – Joffrey

1

@ Axel22s Antwort ist der Schlüssel, aber es gibt ein paar andere Dinge, die in Ihrem Code fehlen. Zunächst sollten Sie je nach Vorliebe entweder BaseAdapter oder ArrayAdapter erweitern. Zweitens möchten Sie in der Praxis einen ViewHolder verwenden, um übermäßige Aufrufe von ViewVieById zu vermeiden und (am wichtigsten) Ihre Ansicht zu recyceln.

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

Ihre getView Funktion können Ansichten recyceln und die ViewHolder Klasse verwenden wie folgt:

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; 

}

Für jede weitere Beispiele (und andere Optimierungstipps)

finden this blog post (oder nur google für ViewHolder).