1. Mitglieder surfen ohne Werbung auf Android-Hilfe.de! ✔ Jetzt kostenlos Mitglied in unserer Community werden.
Schlagworte:
  1. JoEntwickler, 24.06.2018 #1
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Hallo,

    ich habe ein Problem mit der Listview.

    Ich habe für die Items ein eigenes Layout und einen eigenen ArrayAdapter. Das funktioniert auch sehr gut und wird super angezeigt. Nur wenn ich dann das Handy in den Querformat nehme lädt es ein paar Items doppelt und ein paar garnicht. Es sieht auch jedes mal ein bisschen anders aus.

    Hatte jemand auch schon dieses Problem?

    Liebe Grüße
     
  2. deek, 24.06.2018 #2
    deek

    deek Android-Experte

    Idee: Du handlest den configuration change nicht korrekt. Verwendest du Fragments und machst FragmentTransaction.add statt replace?
    Dann wird beim drehen des Schirms das Fragment NOCHMAL drauf gehauen, das alte bleibt stehen.

    Andere Idee: Deine Datenstruktur, in der deine Items sind überlebt den Change und du machst quasi ein zweites mal add auf einer Liste oder so.
     
  3. JoEntwickler, 30.06.2018 #3
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Also wir haben eine ArrayAdapterklasse die von ArrayAdapter<String> erbt. Da werden dann die Daten übergeben.
    Die Klasse wird dann in der onCreate Methode erstellt und der ListView zugewiesen. Ich denke mal, dass beim Drehen die onCreate Methode dann nochmal ausgeführt wird, aber wenn ich bei der Listview nochmal setAdapter mache müsste der ja die alten Daten überschrieben.
    Das komische ist, dass es nur im queren so verbuggt ist. Wenn ich es dann wieder hochkant halte dann wird es wieder angezeigt wie es soll.
     
  4. markus.tullius, 25.07.2018 #4
    markus.tullius

    markus.tullius Android-Lexikon

    Hi, manchmal hilft es einfach die Methode

    @override
    public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    }
    in der Activity zu implementieren. Frage mich nicht warum.

    Und sonst muss du die Soße in der Methode verarbeiten.

    Doku dazu:
    Handle configuration changes | Android Developers
     
    Zuletzt bearbeitet: 25.07.2018
  5. DagobertDokate, 27.07.2018 #5
    DagobertDokate

    DagobertDokate Android-Lexikon

    Guck dir mal die Architecture Components an. Ein ViewModel könnte dein Problem lösen =)

    lg. Dagobert
     
  6. JoEntwickler, 28.07.2018 #6
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Hallo,
    also die Methode onConfigurationChanged löst das Problem leider nicht.

    Mir ist aufgefallen, dass es nur auftritt wenn man scrollen muss. Beim hoch und runterscrollen ändern sich die Items irgendwie ständig.
    @DagobertDokate hättest du villeicht mal ein Beispiel für ein Viewmodell?

    Liebe Grüße
     
  7. Kardroid, 30.07.2018 #7
    Kardroid

    Kardroid Android-Experte

  8. jogimuc, 30.07.2018 #8
    jogimuc

    jogimuc Android-Hilfe.de Mitglied

    Hallo
    Also einfach nur die Methode onConfigurationChanged“ zu Implementieren reicht sicher nicht.
    Da musst du auch die Orientation abfragen und je nach dem darauf regieren.
    Eine Callback Methode überschreiben und nur die super Klasse aufrufen sonnst nichts, ist das gleiche als wenn du sie nicht überschreibst. Bringt dir gar nicht. Da musste auch in der Methode was machen wenn das einen sinn haben soll.



    Arber viel mehr würde mich mal dein Layout interessieren was du für die Liste benutzt.
    Ist es eine Custom Liste mit eigenen Layout und auch ein Layout für die Listen- Einträge ?
    Zeige auch mal deinen Adapter .
    Ist dein Layout auch richtig in Gedehter Lage sichtbar? Wird auch alles angezeigt?
    Haste auch mal dein Layout im Querformat geprüft ob es da auch richtig angezeigt wird?
    Notfals ein eigenes Layout für Querformat erstellen.


    Ohne Code kommen wir hier nicht weiter.

    Ja beim drehen des Handys wird die Activity beendet und wieder neu gestartet dabei wird auch die onCreate , onResume durchlaufen.
    .
    Ja das müsste und wird er auch aber wo Erstellst und Lädst du deine ArrayListe mit den Daten? Die solltest du vorher immer Löschen . Zumindest wenn sie Global erstellt ist. Mit Lokalen Variablen müsste es gehen.


    ArrayList<String> list = new ArrayList<String>();
    for (int i = 0; i < values.length; ++i) {
    list.add(values);
    }


    DeinArrayAdapter adapter = new DeinArrayAdapter(this,
    android.R.layout.simple_list_item_1, list);
    listview.setAdapter(adapter




    Wenn du die Cursor Pos in der Liste beim drehen behalten willst, musst du die in der onSaveInstanceState Methode selber speichern, und in RestoreInstanceState wieder auslesen und im Adapter setzen.



    Das kann man alles machen muss man nicht bei mir funktionieren Listen ohne dies auch gedreht.
    Das muss auch ohne solchen Sachen gehen. macht es doch nicht noch komplizierter



    Nochmal Ohne etwas Quellcode Ist es schwer für uns .
    Das dies hier noch keiner angefordert hat wundert mich.



    Ps. der Tipp von @deek
    war eigentlich super dem wurde leider nicht nachgegangen.
    ist eigentlich das was ich auch sage.
     
    Zuletzt bearbeitet: 01.08.2018
  9. markus.tullius, 31.07.2018 #9
    markus.tullius

    markus.tullius Android-Lexikon

    Manchmal habe ich das Gefühl, dass hier die Antworten nicht wirklich gelesen werden.

    Sehr interessant finde ich deine Ausführung zu dem Thema super(). Frage mich manchmal, warum es die Methode überhaupt gibt. Und was passiert, wenn in onConfigurationChanged kein super steht. :)
    Ich habe nur erzählt, das es manchmal hilft, denke es liegt an der Reihenfolge der Aufrufe. Und sonst muss man den steinigen Weg gehen.

    Beim Wechsel der ‎Orientierung wird das Layout neu gezeichnet. Das heißt ihr müsst den alten Status speichern (beim Adapter gibt es eine Methode, welche die aktuell angezeigte Items zurück gibt. Der beste Ort dafür ist onConfigurationChanged.

    Dann muss man die richtigen Stelle des Livecycle des Activity bzw Fragment abpassen, und zeichnet die Liste neu. Ich würde am liebsten eine Methode nennen, aber das hängt ein bisschen davon ab, wie du dein ListView erzeugst.

    Kann man alles im Link Handle configuration changes  |  Android Developers nachlesen.

    Ich mache das mit 5 in einander geschachtelten Fragment, bei denen beim Wechsel das Layout komplett ausgetauscht wird.
     
  10. jogimuc, 01.08.2018 #10
    jogimuc

    jogimuc Android-Hilfe.de Mitglied

    Für was die es gibt hast du doch schon selber beantwortet.
    Die Methode wird auch wenn sie nicht Überschrieben wird in der Superklasse aufgerufen.
    Wenn du die Methode Überschreibst wird dann deine aufgerufen und nicht mehr die der Superklasse. Mit dem aufruf der Methode mit dem vorgestellten super wird die ursprüngliche Methode der Superklasse aufgerufen. Das ist das Prinzip von Verketteten Methoden nach OOP.
    Wenn man das super nicht aufruft was da passiert kann man im Vorfeld nicht so genau sagen, es wird halt nur der Code ausgeführt der in deiner Methode steht. Wenn in der Supermethode nichts wichtiges gemacht wird, geht es manchmal auch ohne ist aber keine Garantie und im normal fall handelt man sich da nur ärger ein. Wird ja auch so von Google empfohlen.
    Ansonsten bleibt nur ein blick in den Quellcode, um zu wissen was in der SuperMethodde gemacht wird.

    Richtig das hast du. Aber er hat es so gelesen das es reicht nur deinen Code einzufügen, und er hat sich gewundert das es nichts gebracht hat. Dies wollte ich ihm noch mal verdeutlichen. Das nur ein einfaches Implemtieren der Methode nichts bringen kann.
    Da sind wir uns ja einig.

    Ja das Denke ich manchmal auch und es wird versucht es immer komplizierter zu machen.

    Sein Problem wird einerseits bei den Layouts liegen.
    Sowie beim laden der Liste oder besser ein löschen der Liste vor dem neu laden. Auch könnte sein selbst erstellten Adapter nicht sauber programmiert sein. Mit Fragmenten wird es wohl nichts zu tunen haben, da er scheinbar nicht damit arbeitet. Sonst währe er darauf ein gegangen.
    Zum speichern des Zustandes der Liste gibt es verschiedene Möglichkeiten das war aber eigentlich gar nicht das Thema.


    Aber ohne Code können wir nur raten..
     
    Zuletzt bearbeitet: 01.08.2018
  11. JoEntwickler, 02.08.2018 #11
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Sorry das ich kein Code hingeschrieben hab.

    Einmal mein Layout:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Einstellungen"
    android:background="@color/background">

    <include layout="@layout/toolbar"></include>

    <ListView
    android:id="@+id/lvSettingOptions"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/toolbar"/>

    </RelativeLayout>

    Hiermit fülle ich dann die Arraylist:
    listView = findViewById(R.id.lvSettingOptions);
    CashflowSettingsListAdapter settingsListAdapter = new CashflowSettingsListAdapter(this, getResources().getStringArray(R.array.settingOptions),
    R.array.settingOptionIcons);
    listView.setAdapter(settingsListAdapter);


    Und hier meine Adapter Klasse:
    public class CashflowSettingsListAdapter extends ArrayAdapter<String> {

    private List<String> settingOptions;
    private Activity context;
    private TypedArray images;
    private int iconArrayLength;

    public CashflowSettingsListAdapter(Activity context, String [] settingOptions, int iconArrayId) {
    super(context, R.layout.listview_item_settings);
    this.context = context;
    this.settingOptions = Arrays.asList(settingOptions);
    images = context.getResources().obtainTypedArray(iconArrayId);
    this.iconArrayLength = context.getResources().getIntArray(iconArrayId).length;
    }

    @override
    public int getCount() {
    return settingOptions.size();
    }

    @override
    public long getItemId(int i) {
    return 0;
    }

    @override
    public View getView(final int i, View view, ViewGroup viewGroup) {
    View row = view;
    if(row == null) {
    LayoutInflater inflater = context.getLayoutInflater();
    row = inflater.inflate(R.layout.listview_item_settings, viewGroup, false);
    TextView tvSettingsOption = row.findViewById(R.id.tvSettingsOptionText);
    tvSettingsOption.setText(settingOptions.get(i));
    ImageView ibSettingsOptionIcon = row.findViewById(R.id.ibSettingsOptionIcon);
    if (images != null && i < iconArrayLength) {
    ibSettingsOptionIcon.setImageResource(images.getResourceId(i, -1));
    }
    }
    return row;
    }

    }


    Liebe Grüße
     
  12. jogimuc, 03.08.2018 #12
    jogimuc

    jogimuc Android-Hilfe.de Mitglied

    Hallo

    Also du musst in deinem Adapter auch die Liste dem Konstruktorder der Superklasse mit übergeben.

    Ich würde die Liste nicht im Adapter erstellen sondern ihn gleich übergeben ist auch so üblich. Also erzeuge die Liste außerhalb zB in der onCreate und über gib die dem Adapter.
    Die Methoden getCount(),getItemId() brauchst du dann auch nicht überschreiben.
    Denn er hat ja die liste selber.


    Code:
    //  zB. in der onCreate oder in einem Listner
    //  ArrayList<String> list = new ArrayList<>();
    //  listView = findViewById(R.id.lvSettingOptions);
    //  list = Arrays.asList(getResources().getStringArray(R.array.settingOptions)));
    //  CashflowSettingsListAdapter settingsListAdapter = new CashflowSettingsListAdapter(this,list,R.array.settingOptionIcons);
    //  listView.setAdapter(settingsListAdapter);
    
    public class CashflowSettingsListAdapter extends ArrayAdapter<String> {
    
    private ArrayList<String> settingOptions = new ArrayList<>();
    private Activity context;
    private TypedArray images;
    private int iconArrayLength;
    
    public CashflowSettingsListAdapter(Activity context, ArrayList<String> list, int iconArrayId) {
       super(context, R.layout.listview_item_settings,list);
       this.context = context;
       this.settingOptions = list;
       images = context.getResources().obtainTypedArray(iconArrayId);
       this.iconArrayLength = context.getResources().getIntArray(iconArrayId).length;
    }
    
    @override
    public View getView(final int i, View view, ViewGroup viewGroup) {
       View row = view;
       if(row == null) {
          LayoutInflater inflater = context.getLayoutInflater();
          row = inflater.inflate(R.layout.listview_item_settings, viewGroup, false);
          TextView tvSettingsOption = row.findViewById(R.id.tvSettingsOptionText);
          tvSettingsOption.setText(settingOptions.get(i));
          ImageView ibSettingsOptionIcon = row.findViewById(R.id.ibSettingsOptionIcon);
          if (images != null && i < iconArrayLength) {
             ibSettingsOptionIcon.setImageResource(images.getResourceId(i, -1));
          }
       }
      return row;
    }
    
    }

    Zu deinem Layout
    zu dieser Zeile (android:layout_below="@+id/toolbar")
    Ich hoffe das du nicht in dem Includeten Layout auch die Id mit + erstellst.
    Eigentlich hatte mich auch dein ListItem Layout interessiert vor allen ob das auch im Querformat richtig angezeigt wird.
     
    Zuletzt bearbeitet: 03.08.2018
  13. deek, 03.08.2018 #13
    deek

    deek Android-Experte

    Es wären vielleicht noch Screenshots interessant wie das ganze aussieht und der komplette Code deiner Activity/Fragment. Und bitte in code tags, damit es besser lesen kann.
     
    swa00 bedankt sich.
  14. jogimuc, 03.08.2018 #14
    jogimuc

    jogimuc Android-Hilfe.de Mitglied

    So ich noch mal.
    Deine Images würde ich etweder in einer zweiten Liste übergeben, oder du erstellst dir für deine Liste einen Datendype mittels einer Klasse.
    Dann bist du auch fexibler als mit den Resoursen.
     
  15. JoEntwickler, 04.08.2018 #15
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Hier meine Activity. Also es sollen Einstellungen sein:
    Code:
    public class Einstellungen extends AppCompatActivity {
    
        private Toolbar toolbar;
        private ActionBar actionbar;
        private TextView tvToolbarTitle;
        private ListView listView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_einstellungen);
            toolbar = findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            actionbar = getSupportActionBar();
            actionbar.setDisplayHomeAsUpEnabled(true);
            actionbar.setTitle("");
            tvToolbarTitle = findViewById(R.id.tvToolbarTitle);
            tvToolbarTitle.setText(R.string.settings);
            listView = findViewById(R.id.lvSettingOptions);
            CashflowSettingsListAdapter settingsListAdapter = new CashflowSettingsListAdapter(this, getResources().getStringArray(R.array.settingOptions),
                    R.array.settingOptionIcons);
            listView.setAdapter(settingsListAdapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    switch (i) {
                        case 0:
                            startActivity(new Intent(Einstellungen.this, EinstellungenWaehrungen.class));
                            break;
                        case 1:
                            startActivity(new Intent(Einstellungen.this, EinstellungenSprachen.class));
                            break;
                        case 2:
                            startActivity(new Intent(Einstellungen.this, EinstellungenHilfen.class));
                            break;
                        case 3:
                            startActivity(new Intent(Einstellungen.this, EinstellungenErinnerungen.class));
                            break;
                        case 4:
                            Intent intentOpenInfoWidgetSettings = new Intent(Einstellungen.this, EinstellungenCashflowInfoWidget.class);
                            intentOpenInfoWidgetSettings.putExtra(Keys.WIDGET_TYPE, "infoWidget");
                            startActivityForResult(intentOpenInfoWidgetSettings, 0);
                            break;
                        case 5:
                            TotalExams.openPlayStore(Einstellungen.this);
                            break;
                        case 6:
                            final LayoutInflater dialoginflater2 = getLayoutInflater();
                            final View dialogview2 = dialoginflater2.inflate(R.layout.dialog_about_us, null);
                            final AlertDialog.Builder dialogbuilder2;
                            dialogbuilder2 = new AlertDialog.Builder(Einstellungen.this);
                            dialogbuilder2.setView(dialogview2);
                            dialogbuilder2.create().show();
                            break;
                        case 7:
                            final LayoutInflater dialoginflater3 = getLayoutInflater();
                            final View dialogview3 = dialoginflater3.inflate(R.layout.dialog_data_protection, null);
                            final AlertDialog.Builder dialogbuilder3;
                            dialogbuilder3 = new AlertDialog.Builder(Einstellungen.this);
                            dialogbuilder3.setView(dialogview3);
                            dialogbuilder3.create().show();
                            break;
                        case  8:
                            final LayoutInflater dialoginflater4 = getLayoutInflater();
                            final View dialogview4 = dialoginflater4.inflate(R.layout.dialog_imprint, null);
                            final AlertDialog.Builder dialogbuilder4;
                            dialogbuilder4 = new AlertDialog.Builder(Einstellungen.this);
                            dialogbuilder4.setView(dialogview4);
                            dialogbuilder4.create().show();
                            break;
                    }
                }
            });
            ActivityRegistry.register(this);
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                // Respond to the action bar's Up/Home button
                case android.R.id.home:
                    onBackPressed();
                    return true;
            }
            return super.onOptionsItemSelected(item);
        }
    
    }
    -- Dieser Beitrag wurde automatisch mit dem folgenden Beitrag zusammengeführt --
    Sorry hat nicht richtig hochgeladen.
     

    Anhänge:

  16. jogimuc, 04.08.2018 #16
    jogimuc

    jogimuc Android-Hilfe.de Mitglied

    Hi schön das du den Code noch gepostet hast.
    Mich würde aber interessieren ob das was ich dir gesagt habe geholfen hat.
    Wie ich aus deinem Code sehe hast du die Änderungen noch nicht gemacht.
     
  17. deek, 05.08.2018 #17
    deek

    deek Android-Experte

    Ich dachte eigentlich ein Screenshot vom Problem, also da wo die Sachen doppelt zu sehen sind.

    Beim nochmaligen drüber schauen könnte ich mir vorstellen wo dein Problem liegt:
    Code:
    @override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        View row = view;
        if(row == null) {
            LayoutInflater inflater = context.getLayoutInflater();
            row = inflater.inflate(R.layout.listview_item_settings, viewGroup, false);
            TextView tvSettingsOption = row.findViewById(R.id.tvSettingsOptionText);
            tvSettingsOption.setText(settingOptions.get(i));
            ImageView ibSettingsOptionIcon = row.findViewById(R.id.ibSettingsOptionIcon);
            if (images != null && i < iconArrayLength) {
                ibSettingsOptionIcon.setImageResource(images.getResourceId(i, -1));
            }
        }
        return row;
    }
    
    Hier änderst du den Inhalt deiner View nur, wenn du sie neu inflatest.
    Das ist aber falsch, eine Listview recyclet die einzelnen Views. D.h. wenn sie aus dem Bild scrollen werden sie für ein neues Item wiederverwendet. Die alte View bekommst du hier dann als view rein. Setzt du hier jetzt keine neuen Werte, dann hat die View noch den alten Content und die Liste zeigt items doppelt an.
    Du musst also entweder jedesmal eine neue View infalten (schlechte Performance) oder im Fall dass die view != null ist einfach den Inhalt korrekt setzen ohne vorher zu inflaten.

    In der neuen RecyclerView (die man als Anfänger eigentlich vor ListView präferieren sollte) ist das etwas explizierter dargestellt durch zwei Schritte.
     
  18. JoEntwickler, 18.08.2018 #18
    JoEntwickler

    JoEntwickler Threadstarter Android-Hilfe.de Mitglied

    Ok ich hab jetzt mal das von deek gemacht. Also die View jedesmal neu erstellen lassen.
    Also von der Performance merke ich da keine wirklichen Nachteile. Hab das an meinem 150€ Huawei getestet.
    Alle ListView Items sind da wo sie sein sollen.

    Also mein Problem wäre damit gelöst.
    Klar ist das nicht die schönste Lösung, aber sie
     
  19. ashleyjones, 30.08.2018 #19
    ashleyjones

    ashleyjones Neuer Benutzer

    I's a weird situation you know!
    Make sure you have implemented your adapter properly, especially the getView() method if you are extending Base Adapter.
    Follow this link to get more information on base adapter Adapter  |  Android Developers
     
  20. swa00, 30.08.2018 #20
    swa00

    swa00 Moderator Team-Mitglied

    Hello Ashely,

    welcome in our community and thank you for your answer.
    Pls note : We are a native speaken german community and pls write in german .

    Thx a lot
     
Die Seite wird geladen...
Du betrachtest das Thema "ListView mit eigenem Layout zeigt im Querformat Items doppelt an" im Forum "Android App Entwicklung",
  1. Android-Hilfe.de verwendet Cookies um Inhalte zu personalisieren und dir den bestmöglichen Service zu gewährleisten. Wenn du auf der Seite weitersurfst stimmst du der Cookie-Nutzung zu.  Ich stimme zu.