2017-09-08 2 views
0

Ich habe ein ListView gesetzt, das dynamisch/entfernt hinzugefügt werden kann und seine Höhe dynamisch angepasst ArrayAdapter Verwendung ein benutzerdefinierte und Runnable jeweils:ListView.post arbeiten, aber nur auf einigen Geräten

Hier ist, wie meine Gewohnheit ArrayAdapter genannt ItemListAdapter initialisiert:

private Activity activity; 
    public ListView listView; 

    public ItemListAdapter(Activity activity, ListView listView...) { //other items are irrelevant 
    super(context, resource, values); //typical initalization 
    this.activity = activity; 
    this.listView = listView; 
    ... other codes are irrelevant 
    } 

der wichtigste Teil ist, dass der Adapter eine Aktivität und ein ListView nimmt die in dieser Tätigkeit des Layout verwendet wird.

Und dann, natürlich, ich habe auch den folgenden überschrieben notifyDataSetChanged Code, der aufgerufen wird, wenn ein Datensatz in dem Adapter geändert wird:

@Override 
    public void notifyDataSetChanged() { 
    if(listView != null) { 
     listView.post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //works well but only once 
//  activity.runOnUiThread(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //this also not working 
    } 
    } 

Da die neue Höhe nicht vor dem UI bekannt sein wird gezogen, wenn der Datensatz wird geändert, die obige notifyDataSetChanged wird dynamisch die richtige Höhe der listView mit ListView.post Methode eingerichtet.

Das Runnable Argument wird von einem static Methode GetRunnableSetCorrectHeight im ListViewHelperclass genommen, wie im Folgenden dargestellt:

public static Runnable GetRunnableSetCorrectHeight(final ListView listView){ 
    return new Runnable() { 
     @Override 
     public void run() { 
     ViewGroup.LayoutParams params = listView.getLayoutParams(); 
     params.height = DataHolder.LvBaseOffset + getHeight(listView, listView.getAdapter()); //this is the actual set up of the view, the view should be changed because of this, except for the first time... 
     listView.setLayoutParams(params); //if this is not there, the first show in the main activity will nor be complete (only show the first item) 
//  listView.requestLayout(); //not needed 
     } 
    }; 
    } 

und kann nicht direkt mit dem Thema in Beziehung gesetzt werden, sondern nur der Vollständigkeit halber, die getHeight Verfahren in dem obigen Verfahren aufgerufen ist die folgende:

public static int getHeight(ListView listView, ListAdapter adapter){ 
    int totalHeight = 0; 
    int listWidth = listView.getMeasuredWidth(); 

    for (int i = 0; i < adapter.getCount(); i++) { 
     View mView = adapter.getView(i, null, listView); 
     mView.measure(View.MeasureSpec.makeMeasureSpec(listWidth, View.MeasureSpec.EXACTLY), 
      View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 
     totalHeight += mView.getMeasuredHeight(); 
    } 

    return totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1)); 
    } 

in dem Layout der Aktivität, habe ich eine Add und Delete Taste, die die notifyDataSetChanged löst genannt zu werden ein Element hinzufügen/entfernen und die ListView mit der richtigen Höhe neu gezeichnet:

enter image description here

Zum Beispiel, wenn die Add Taste gedrückt wird, wird das Ergebnis der folgenden :

enter image description here

Die oben genannten Codes funktionieren zumindest in meinem Android-Simulator, eine Hua Wei Tablette und ein Xiao Mi Telefon gut. Und wenn ich gut sage, bedeutet dies, dass die Schaltfläche Add mehrfach angeklickt werden kann und immer eine neue Zeile erzeugt und die Höhe angepasst wird.

enter image description here

Aber wenn ich in einem anderen Gerät zu implementieren versuchen, es nur funktionieren, wenn. Was ich meine ist, wenn ich die Add oder Delete Taste das erste Mal drücke, wurde der Artikel im ListView hinzugefügt/gelöscht. Aber wenn ich zum zweiten Mal klicken, wird der Absturz der Anwendung mit typischer Fehlermeldung Feld:

Unfortunately, [Application Name] has stopped. 

                OK 

Nun las ich einige Beiträge in Bezug auf diese, die erwähnt, dass das Problem wahrscheinlich durch nicht läuft die Runnable in dem UI-Thread verursacht wird .So habe ich die Aktivität in dem Bau der ItemListAdapter hinzugefügt, wie oben gezeigt, und ich versuche auch die Methode zu ändern:

@Override 
    public void notifyDataSetChanged() { 
    if(listView != null) { 
     listView.post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //works well but only once 
//  activity.runOnUiThread(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //this also not working 
    } 
    } 

in

@Override 
    public void notifyDataSetChanged() { 
    if(listView != null) { 
     //listView.post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //works well but only once 
     activity.runOnUiThread(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //this also not working 
    } 
    } 

Aber das Problem immer noch besteht. Ich versuche auch, Verzögerung zu geben:

@Override 
    public void notifyDataSetChanged() { 
    if(listView != null) { 
     //listView.post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //works well but only once 
     activity.runOnUiThread(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //this also not working 

     try { 
     sleep(500); // does not help 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 

Und zu verwenden Handler(Looper.getMainLooper()).post:

@Override 
    public void notifyDataSetChanged() { 
    if(listView != null) { 
     //listView.post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //works well but only once 
     new Handler(Looper.getMainLooper()).post(ListViewHelper.GetRunnableSetCorrectHeight(listView)); //this also not working 

     try { 
     sleep(500); // does not help 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 

Aber nichts funktioniert und ich laufe aus Ideen ...

Warum ist das so? Warum funktioniert die post nur einmal, obwohl ich versucht habe, auf dem UI-Thread zu laufen, mit dem Haupt-Looper oder mit Verzögerung? Wie man es repariert?

+0

Versuch zu gehen für Recyclerview –

+0

@LalitJadav Was ist das? Wie überprüfe ich etwas? – Ian

+0

hast du versucht, listview height zu wrap_content? –

Antwort

0

RecyclerView ist große Vorausversion von ListView. Sie finden es official doc.

Wenn Sie Demo gehen wollen check this blog

+0

Es scheint nicht in meinem Fall zu helfen ... – Ian

Verwandte Themen