webentwicklung-frage-antwort-db.com.de

Android: RecyclerView-Inhalt nach dem Scrollen durcheinander gebracht

Ich verwende RecyclerView, um eine Liste von Marken anzuzeigen, und jede Marke des Werts wird als CardView angezeigt. Einige Inhalte der Karten gehen jedoch verloren, nachdem Sie den RecyclerView nach unten und zurück gescrollt haben, wie in den beiden folgenden Screenshots gezeigt. Der Inhalt im roten Rechteck geht nach dem Scrollen verloren.

VOR DEM SCROLLEN; enter image description here

NACH DEM SCROLLEN; enter image description here

Ich frage mich, ob es ein Fehler von RecyclerView ist oder nicht und finde nach dem Googeln keine Lösung dafür.

Alle Ansichten außer dem Titel sind unsichtbar, ihre Sichtbarkeit hängt vom Wert der Marke ab.

Weiß jemand, warum das passieren würde?

26
Swisyn

onBindHolder wurde mehrmals aufgerufen, da der Recycler eine Ansicht benötigt, es sei denn, eine neue Ansicht wurde geändert. Jedes Mal, wenn Sie die Sichtbarkeit in untergeordneten Ansichten festlegen, werden auch andere Ansichtszustände geändert.

Wenn Sie nach oben und unten scrollen, werden diese Ansichten mit falschen Sichtbarkeitsoptionen neu gezeichnet.

Lösung:

Sie haben eine setValue-Methode zum Überprüfen von Werten und zum Anzeigen festgelegt. Bei Bedarf wird eine andere Methode "showView" aufgerufen. Sie müssen else-Anweisung implementieren (der Wert ist 0 oder null) und hideView dort ...

void setValue(Object value, TextView textView, TableRow row, View seperator) {
    if (value != null) {
        if (!isEmpty(value.toString())) {
            textView.setText(String.valueOf(value));
            showViews(row, seperator);
        }
    } else
        hideViews(row, seperator);
}

private void showViews(TableRow row, View seperator) {
    row.setVisibility(View.VISIBLE);
    seperator.setVisibility(View.VISIBLE);
}

private void hideViews(TableRow row, View seperator) {
    row.setVisibility(View.INVISIBLE); // if there is a empty space change it with View.GONE
    seperator.setVisibility(View.INVISIBLE);
}
29
Emre Aktürk

Nachdem ich ungefähr 24 Stunden lang mit dem gleichen Problem gekämpft hatte, fand ich eine Lösung, die für mich funktionierte. Der Schlüssel verwendete die Methode setIsRecyclable() der Klasse RecyclerView.ViewHolder.

Hier ist ein Abschnitt meines onBindViewHolder() Codes.

@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
    final DataSource dataSource = dataSourceList.get(position);

    holder.setIsRecyclable(false);

    holder.name.setText(dataSource.getName());
    holder.active.setChecked(dataSource.getActive());

    String logoStr = dataSource.getLogo();

    //Logo
    /**
     * Do all the logo insertion stunts here
     */
    /**
     * Register the changes to the Switch
     */
    holder.active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked){
            dataSource.setActive(isChecked);
        }
    });
}
32
aphoe

onBindHolder wurde mehrmals aufgerufen, da Recycler View eine Ansicht benötigt, sofern keine neue vorhanden ist. Jedes Mal, wenn Sie die Sichtbarkeit in untergeordneten Ansichten festlegen, werden auch andere Ansichtszustände geändert.

Wenn Sie nach oben und unten scrollen, werden diese Ansichten mit falschen Sichtbarkeitsoptionen neu gezeichnet. Geben Sie daher immer beide Bedingungen an, da die Recycler-Ansicht den vorherigen Status/die vorherigen Bedingungen/Werte unserer Widgets nicht kennt.

Lösung:

Wenn Sie im If-Block die Sichtbarkeit von Android widget.setVisibility (View.Gone)) festlegen, müssen Sie im else-Block die Sichtbarkeit gegenüber v mit widget.setVisibility (View.Visible) festlegen, um das zu überwinden obiges Problem.

 @Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {

    viewHolder.tvName.setText(ModelCategoryProducts.name.get(i));
    viewHolder.tvPrice.setText("Rs."+String.format("%.2f", Float.parseFloat(ModelCategoryProducts.price.get(i))));
    if(ModelCategoryProducts.special_price.get(i).equals("null")) {
        viewHolder.tvSpecialPrice.setVisibility(View.GONE); // here visibility is gone and in else it's opposite visibility i set.
        viewHolder.tvPrice.setTextColor(Color.parseColor("#ff0000"));
        viewHolder.tvPrice.setPaintFlags(0);// here Paint flag is 0 and in else it's opposite flag that i want is set.
    }else if(!ModelCategoryProducts.special_price.get(i).equals("null")){
        viewHolder.tvPrice.setTextColor(Color.parseColor("#E0E0E0"));
        viewHolder.tvSpecialPrice.setVisibility(View.VISIBLE);
        viewHolder.tvSpecialPrice.setText("Rs." + String.format("%.2f", Float.parseFloat(ModelCategoryProducts.special_price.get(i))));
        viewHolder.tvPrice.setPaintFlags(viewHolder.tvPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    }
    if (!ModelCategoryProducts.image_url.get(i).isEmpty()) {
        Picasso.with(context)
                .load(ModelCategoryProducts.image_url.get(i))
                .into(viewHolder.ivProduct);
    }

    viewHolder.setClickListener(new ItemClickListener() {
        @Override
        public void onClick(View view, int position, boolean isLongClick) {
            if (isLongClick) {
//                    Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position) + " (Long click)", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(context, "#" + position + " - " + ModelCategoryProducts.name.get(position), Toast.LENGTH_SHORT).show();
                Intent i = new Intent(context, ProductDetail.class);
                i.putExtra("position",position);
                i.putExtra("flagHlvCheck", 5);
                context.startActivity(i);
            }
        }
    });
}
12
Sachin Mandhare

Dies liegt daran, dass die Ansichten beim Scrollen wiederverwendet werden. Um dies zu beheben, müssen Sie alle Ansichten zurücksetzen, die für andere Zellen sichtbar gemacht wurden (YUZME in Ihrem Beispiel).

Innerhalb von setValue (Objektwert, TextView TextView, TableRow-Zeile, View-Trennzeichen) werden alle txtVize * einfach wieder ausgeblendet.


Die Recycler-Ansicht beginnt mit 3 Ansichten:

[0] FIZ104

[1] MAT102

[2] REK361

Wenn die Ansicht nach unten verschoben wird, werden die Ansichten [0] und [1] wiederverwendet. Wenn Sie zurück zur Draufsicht scrollen, wird [2] verwendet, um die in FIZ104 und MAT102 enthaltenen Daten anzuzeigen, und alle für REK361 vorgenommenen Änderungen sind noch vorhanden.

0
Numan1617

Wenn Sie Probleme mit dem Sichtbarkeitsproblem haben, z. Wenn Sie die Sichtbarkeit der Ansicht basierend auf der Bedingung festgelegt haben, aber wenn Sie nach unten scrollen, werden die Ansichten aktualisiert und die Sichtbarkeit der Ansicht in diesem Element der Recycler-Ansicht wird geändert und verstößt somit gegen die Bedingung.

Hier ist eine Lösung:

1. Weisen Sie zuerst der Ansicht, deren Sichtbarkeit Sie beibehalten möchten, ein Tag zu.

    holder.myImageView.setTag(myTeamLists.get(position));
    MyDTOClass checkWetherToShow=(MyDTOClass)holder.myImageView.getTag();

2. Wenden Sie jetzt Ihre Bedingung an und schalten Sie die Sichtbarkeit um

    if (checkWetherToShow.getHasToShowImage()){
        holder.myImageView.setVisibility(View.VISIBLE);
    }else{
        holder.myImageView.setVisibility(View.GONE);
    }

Der Schlüssel zur Antwort lautet hier sonst bitte nicht vergessen.

0
Udit Kapahi