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 ListViewHelper
class
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:
Zum Beispiel, wenn die Add
Taste gedrückt wird, wird das Ergebnis der folgenden :
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.
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?
Versuch zu gehen für Recyclerview –
@LalitJadav Was ist das? Wie überprüfe ich etwas? – Ian
hast du versucht, listview height zu wrap_content? –