android - ListView 项目中的动态 LinearLayout

标签 android android-listview

我正在使用带有自定义适配器的 ListView,该适配器获取 JSONArray(来自 Facebook 请求)。每个 ListView 项都有两个 TextView 和一个或两个 ImageView,具体取决于帖子类型。每个列表项还有一个 LinearLayout,我称之为“评论框”。

当我在 xml 中定义列表项时,评论框仅包含标题的 TextView(“评论和喜欢”)。在自定义适配器中,解析评论数据(我希望是正确的),并以编程方式为每个评论添加 TextView,这样我就不会无缘无故地创建和扩充空的 TextView。

我遇到的问题,似乎是一个常见的 ListView 回收问题,是在滚动列表时评论框不保留其内容。我查看了 JSON 数据,数组中的每个对象都有相同的“注释”字段,所以我认为我不会为数据中的任何内容获取 null,特别是如果所有其他数据加载和填充都很好.我不知道我做错了什么,因为除此之外其他一切都有效。这是我的适配器的 getView() 方法。

public View getView(int position, View convertView, ViewGroup parent) {

    final ViewHolder holder;

    try {
        jsonObject = getItem(position);
        jsonFrom = jsonObject.getJSONObject("from");
        postType = jsonObject.getString("type");
        posterName = jsonFrom.getString("name");
        posterID = jsonFrom.getString("id");
        posterPhoto = "http://graph.facebook.com/" + posterID + "/picture?type=square";
        if (jsonObject.has("name")) {
            posterMessage = jsonObject.getString("name");
        }
        else if (jsonObject.has("story")){
            posterMessage = jsonObject.getString("story");
        }
        else if (jsonObject.has("message")){
            posterMessage = jsonObject.getString("message");
        }
        else{
            posterMessage = "No message.";
        }
        if(jsonObject.has("picture")){
            posterImageURL = jsonObject.getString("picture");
        }
        commentsData = jsonObject.getJSONObject("comments");
        commentsCount = commentsData.getInt("count");


    } catch (JSONException e) {
        e.printStackTrace();
    }

    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.post_holder,null);
        holder = new ViewHolder();
        holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
        holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
        holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
        holder.posterImage = (ImageView) convertView.findViewById(R.id.posterImage);
        holder.commentsBox = (LinearLayout) convertView.findViewById(R.id.commentsBox);
        if(postType.equals("photo")){
            holder.posterImage.setVisibility(View.VISIBLE);
        }
        if(commentsCount!=0 && commentsCount!=null){
            try {
                commentsArray = commentsData.getJSONArray("data");
                for(int index = 0; index<commentsArray.length(); index++){
                    comment = commentsArray.getJSONObject(index);
                    commenterName = comment.getJSONObject("from").getString("name");
                    commenterId = comment.getJSONObject("from").getString("id");
                    commentMessage = comment.getString("message");
                    TextView commentMessageHolder = new TextView(activity);
                    commentMessageHolder.setText(Html.fromHtml("<b>"+commenterName+"</b>"+"  "+commentMessage));
                    holder.commentsBox.addView(commentMessageHolder, index+1);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }


        }

        convertView.setTag(holder);
    } 
    else {
        holder = (ViewHolder) convertView.getTag();
        if(postType.equals("photo")){
            holder.posterImage.setVisibility(View.VISIBLE);
        }
        else{
            holder.posterImage.setVisibility(View.GONE);
        }
    }

    if (jsonObject != null) {
        holder.posterName.setText(posterName);
        if (posterMessage != null) {
            holder.posterMessage.setText(posterMessage);
        } else {
            holder.posterMessage.setText("No message for this post.");
        }

        imageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);

        if(postType.equals("photo")){
            if(posterImageURL != null){
                holder.posterImage.setTag(posterImageURL);
                imageLoader.displayImage(posterImageURL, holder.posterImage);
            }
        }
    }

    return convertView;

}

最佳答案

The problem I'm having, which seems like a common ListView recycling problem, is that the comments box doesn't retain its contents when scrolling through the list.

主要问题是当convertViewnull 时,您 构建注释TextViews,当用户滚动 ListView 时,您最终会看到那些最初设置的行 View (带有注释),您不会为不需要的位置进行修改。将注释 for 循环移到检查 convertView 是否为 null 的 if 子句之外。

此外,您可能希望缓存该 json 解析,更不用说您需要考虑不要过度添加注释 TextViews,因为回收的行 View 可能已经有自己的注释 TextViews

关于android - ListView 项目中的动态 LinearLayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14043155/

相关文章:

java - 如果 RxJava 中结果无效,如何发送 onError

java - 在 TextView 框架周围显示旋转箭头

android - 支持 fragment 管理器 .replace() 和 ViewModel

java - 如何将 id 传递到 Parcelable 中?

java - 为什么ListView.setAdapter(null)不会抛出空指针异常?

android - java.lang.NullPointerException : Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()' on a null object reference

android - ListView 膨胀问题

Android:自定义 ListView 中的单选按钮

java - 如何更改数组列表的每个字符串元素?

java - WhatsApp 如何检测联系人列表中的谁使用了该应用程序?