在RecyclerView图像的奇怪行为 [英] Strange behaviour of images in RecyclerView

查看:322
本文介绍了在RecyclerView图像的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用android.support.v7.widget.RecyclerView显示包含文本的简单项目,并在某些情况下也图像。基本上,我跟着从这里教程<一个href=\"https://developer.android.com/training/material/lists-cards.html\">https://developer.android.com/training/material/lists-cards.html而距离的String []以JSONArray和ViewHolder的XML改变mDataset的类型。我RecyclerView坐落在一个简单的片段:

I am using android.support.v7.widget.RecyclerView to show simple items containing text and in some cases also images. Basically I followed the tutorial from here https://developer.android.com/training/material/lists-cards.html and just changed the type of mDataset from String[] to JSONArray and the xml of the ViewHolder. My RecyclerView is located in a simple Fragment:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
    android:id="@+id/my_hopps_recycler_view"
    android:scrollbars="vertical"
    android:layout_centerInParent="true"
    android:layout_width="200dp"
    android:layout_height="wrap_content"/>

</RelativeLayout>

在这个片段我加载从一个网络服务器的所有信息。接到信息后,我初始化在RecyclerView的项目。我使用的是我的片段的onCreate方法设置LinearLayoutManager。加上适配器后,我呼吁我的RecyclerView setHasFixedSize(true)方法。我的适配器类看起来是这样的:

In this fragment I am loading all information from a webserver. After receiving the information I initialize the items in the RecyclerView. I use a LinearLayoutManager which is set in the onCreate method of my Fragment. After adding the Adapter, I call the setHasFixedSize(true) method on my RecyclerView. My Adapter class looks like this:

import android.graphics.BitmapFactory;
import android.support.v7.widget.RecyclerView;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import saruul.julian.MyFragment;
import saruul.julian.R;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

/**
* Fragment holding the RecyclerView.
*/
private MyFragment myFragment;
/**
* The data to display.
*/
private JSONArray mDataset;

public static class ViewHolder extends RecyclerView.ViewHolder {

    public TextView text;
    ImageView image;

    public ViewHolder(View v) {
        super(v);
        text = (TextView) v.findViewById(R.id.my_view_text);
        image = (ImageView) v.findViewById(R.id.my_view_image);
    }
}

public MyAdapter(MyFragment callingFragment, JSONArray myDataset) {
    myFragment = callingFragment;
    mDataset = myDataset;
}

@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.my_view, parent, false);
    ViewHolder vh = new ViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    try {
        JSONObject object = mDataset.getJSONObject(position);
        if ( object.has("image") ){
            if ( !hopp.getString("image").equals("") ){
                try {
                    byte[] decodedString = Base64.decode(StringEscapeUtils.unescapeJson(object.getString("image")), Base64.DEFAULT);
                    holder.image.setImageBitmap(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length));
                    holder.image.setVisibility(View.VISIBLE);
                } catch ( Exception e ){
                    e.printStackTrace();
                }
            } 
        }
        if ( object.has("text") ){
            holder.text.setText(object.getString("text"));
        }
    } catch ( Exception e ){
        e.printStackTrace();
    }
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.length();
}
}

和我的XML我RecyclerView内部的视图:

And my xml for a view inside my RecyclerView:

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="4dp">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/my_hopp_people_reached"/>

    <ImageView
        android:id="@+id/my_hopp_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:adjustViewBounds="true"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/my_hopp_text"/>

    <ImageButton
        android:id="@+id/my_hopp_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:src="@drawable/ic_action_discard"
        />

</LinearLayout>

</android.support.v7.widget.CardView>

所以,现在这里是我的问题:一切工作正常。文字和图片在我RecyclerView正确显示。但是,如果我向下滚动到达列表的末端,并再次向上滚动,图片示于其不应包含图片的物品。
目前,我有九个项目。他们中的最后两个包含一个图像。所以,我向下滚动,刚才看到第一七品的文字。到达列表的末尾显示我两张图片预期。但是,如果我滚动再次那些照片出现在其他项目。

So now here is my problem: Everything works fine. Text and picture are shown correctly in my RecyclerView. However if I reach the end of the list by scrolling down and scroll up again, pictures are shown in items which should not contain pictures. At the moment I have got nine items. The last two of them contain a picture. So I scroll down and just see text in the first seven items. Reaching the end of the list shows me two pictures as expected. But if I scroll up again those pictures appear in other items.

滚动向上和向下永远改变了图片在同一顺序:

Scrolling up and down changes the pictures always in the same order:


  • 第一个滚动起来会在第二个项目的图片(即下一次后)。

  • 向下滚动会在第7项的图片。

  • 滚动起来会在第一项的图片。

  • 向下滚动创造什么。

  • 滚动起来创建的第三项和第二项中的图象的图象与其他图象被覆盖。

  • 向下滚动会在第6项的画面,让在第7项的画面消失。

  • 等等...

我已经发现onBindViewHolder(ViewHolder持有人,INT位置)方法被调用每次一个项目在屏幕上再次出现。我检查的位置和我mDataset给定的信息。一切正常的位置:位置是正确的,给定的信息了。在所有项目的文本不会更改,并始终正确显示。
有没有人有什么样的这一问题,并知道一些解决方案?任何形式的帮助是非常AP preciated。 :)

I already discovered that the onBindViewHolder(ViewHolder holder, int position) method is called everytime an item appears again on the screen. I checked for the position and the given information in my mDataset. Everything works fine here: The position is right and the given information too. The text in all items does not change and is always shown correctly. Does anyone have any kind of this problem and knows some solution? Any kind of help is highly appreciated. :)

推荐答案

我想你需要一个其他子句添加到您的如果(对象。先后(图像)) onBindViewHolder(ViewHolder持有人,INT意见书)方法中,图像设置为null:

I think you need to add an else clause to your if ( object.has("image") ) statement in the onBindViewHolder(ViewHolder holder, int position) method, setting the image to null:

holder.image.setImageDrawable(null);

我觉得<一个href=\"https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onBindViewHolder(VH,%20int)\">the对于onBindViewHolder文档最好的形容它为什么这是必要的:

I think the documentation for onBindViewHolder describe it best why this is necessary:

由RecyclerView调用在指定位置显示的数据。此方法应更新ItemView控件的内容,以在给定的位置反映项目

Called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position.

您应该总是假设ViewHolder传递需要被完全更新:)

You should always assume that the ViewHolder passed in needed to be completely updated :)

这篇关于在RecyclerView图像的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆