在Recyclerview的一个TextView中显示相同键的值 [英] Show values of same key in one TextView in Recyclerview

查看:60
本文介绍了在Recyclerview的一个TextView中显示相同键的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在GSON和Retrofit中解析了以下JSON.我想在一个TextView中显示相同的 id 的值.现在发生的是,所有值都添加到了数组中,并在单独的TextView中显示.我想显示所有具有相同 id 的值,这些值将显示在一个TextView中.例如. id:240 ab 值应位于一个TextView中.当前,所有 ab 值都位于单独的TextView中.

I have the following JSON which I'm parsing in GSON and Retrofit. I want to display the values of the same id in one TextView. What's happening right now is that all the values are added to the array and they are being displayed in separate TextViews. I want to show all values which have the same id to be displayed in one TextView. For eg. id: 240 ab values should be in one TextView. Currently, all ab values are in separate TextView.

这是当前数据显示的方式:

This is how the data is currently displaying:

这就是我希望数据为:

This is how I want the data to be:

JSON ::

{
  "abc": {
    "1": {
      "1": {
        "ab": "some content",
        "id": "240",
        "key": "value"
      },
      "2": {
        "ab": "some content",
        "id": "240",
        "key": "value"
      },
      "3": {
        "ab": "some content",
        "id": "240",
        "key": "value"
      }
    },
    "2": {
      "1": {
        "ab": "more content",
        "id": "241",
        "key": "value"
      },
      "2": {
        "ab": "more content 1",
        "id": "241",
        "key": "value"
      },
      "3": {
        "ab": "more content 2",
        "id": "241",
        "key": "value"
      }
    }
  }
}

POJOContent ::

POJOContent::

public class POJOContent {

    @SerializedName("ab")
    public String content;

    @SerializedName("id")
    public String id;

    @SerializedName("key")
    public String key;

    @Override
    public String toString() {
        return content;
    }

    //getters and setters

}

MyContentWrapper ::

MyContentWrapper::

public class MyContentWrapper {
    public Map<Integer, MyMap> abc;
}

MyMap ::

public class MyMap extends HashMap<Integer, POJOContent> {
    @Override
    public POJOContent put(Integer key, POJOContent value) {
        if(null==value.getContent() || value.getContent().isBlank()) {
            return null;
        }
        // Added only if content = "ab" is not blank.
        return super.put(key, value);
    }
}

回调:

    Callback<MyContentWrapper> myCallback = new Callback<MyContentWrapper>() {
                @Override
                public void onResponse(Call<MyContentWrapper> call, Response<MyContentWrapper> response) {
                    if (response.isSuccessful()) {
                        Log.d("Callback", " Message: " + response.raw());
                        Log.d("Callback", " Message: " + response.body().abc.values());

                        MyContentWrapper contentWrapper = response.body();

                        List<POJOContent> pojo = new ArrayList<>();

                        for (Map.Entry<Integer, MyMap> entry : contentWrapper.abc.entrySet()) {
                            Integer key = entry.getKey();
                            MyMap map = entry.getValue();
                            if (!map.isEmpty()){
                                Log.d("Callback", " Key: " + key);
                                Log.d("Callback", " Value: " + map.values());

                                pojo.addAll(map.values());
                            }
                        }

                        MyContentViewAdapter adapter = new MyContentViewAdapter(pojo);
                        recyclerView.setAdapter(adapter);
                    } else {
                        Log.d("Callback", "Code: " + response.code() + " Message: " + response.message());
                    }
                }
                @Override
                public void onFailure(Call<MyContentWrapper> call, Throwable t) {
                    t.printStackTrace();
                }
            };

RecyclerAdapter ::

RecyclerAdapter::

                public class MyContentViewAdapter extends RecyclerView.Adapter<MyContentViewAdapter.ViewHolder> {
    private List<POJOContent> data;
    private MyClickListener clickListener;


    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView text;
        private LinearLayout itemLayout;

        public ViewHolder(View v) {
            super(v);
            text = (TextView) v.findViewById(R.id.text_content);
        }
    }

    public MyContentViewAdapter(List<POJOContent> data) {
        this.data = data;
        Log.d("Recyclerview Data", data.toString());
    }


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

    @Override
    public void onBindViewHolder(MyContentViewAdapter.ViewHolder holder, int position) {
        POJOContent pojo = data.get(position);
        Log.d("Recyclerview", pojo.getContent());
        holder.text.setText(pojo.getContent());
        holder.itemView.setTag(pojo.getContent());
    }

    public void setOnItemClickListener(MyClickListener clickListener) {
        this.clickListener = clickListener;
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

}

推荐答案

我在 ViewHolder 内添加了嵌套的 RecyclerView ,因此内容和值字段将动态显示.我要添加2个 Adapter 的完整代码,然后2个 ViewHolder 类,2个xml布局和屏幕截图

I added nested RecyclerView inside ViewHolder, so the content and value fields will be displayed dynamically. I'm Adding full code of 2 Adapter and 2 ViewHolder classes, 2 xml layouts and screenshot

我敢肯定,即使列表很大,它也可以非常流畅地运行.

ID(240,241)下的所有内容都是另一个recyclerView.

Everything under ID(240,241) is another recyclerView.

这个想法是,列表的大小(用于适配器自身填充)应该与不同ID的数量一样多,以便只夸大许多 Viewholders .

The idea is that list's size, for adapter to populate itself, should be as many as the number of distinct ids, so that only that many Viewholders are inflated.

 List<List<POJOContent>> listOfPojoLists = new ArrayList<>();

    for (Map.Entry<Integer, MyMap> entry : contentWrapper.abc.entrySet()) {
        Integer key = entry.getKey();
        MyMap map = entry.getValue();
        if (!map.isEmpty()){
            Log.d("Callback", " Key: " + key);
            Log.d("Callback", " Value: " + map.values());

            listOfPojoLists.add(new ArrayList<>(map.values()));
        }
    }

    MyContentViewAdapter adapter = new MyContentViewAdapter(listOfPojoLists);
    recyclerView.setAdapter(adapter);


MyContentViewAdapter.java

public class MyContentViewAdapter extends RecyclerView.Adapter<MyContentViewAdapter.ViewHolder> {
private List<List<POJOContent>> data;
private MyClickListener clickListener;


MyContentViewAdapter(List<List<POJOContent>> data) {
    this.data = data;
}

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

@Override
public void onBindViewHolder(MyContentViewAdapter.ViewHolder holder, int position) {
    holder.bind(data.get(position));
}

public void setOnItemClickListener(MyClickListener clickListener) {
    this.clickListener = clickListener;
}

@Override
public int getItemCount() {
    return data.size();
}


class ViewHolder extends RecyclerView.ViewHolder {

    private TextView textId;
    private InnerListAdapter innerAdapter;

    // inside constructor we are initializing inner recyclerView and inner Adapter.
    // there will only be 3 - 5 instances of them ever created(using this 
    // particular viewHolder layouts), no more.
    // might be slightly more if u use layouts with lower height
    ViewHolder(View v) {
        super(v);
        textId =  v.findViewById(R.id.tv_Id);
        RecyclerView innerRecycler = v.findViewById(R.id.rv_inner_list);
        // I added DividerItemDecoration so it would be clear that there are actually different viewHolders
        // displayed by recyclerView
        innerRecycler.addItemDecoration(new DividerItemDecoration(v.getContext(), DividerItemDecoration.VERTICAL));
        innerAdapter = new InnerListAdapter();
        innerRecycler.setAdapter(innerAdapter);
    }

    /* We just submit new list for our inner adapter
    so it will handle rebinding values to its viewHolders */
    void bind(List<POJOContent> pojoList){
        textId.setText(pojoList.get(0).id);
        innerAdapter.setNewItems(pojoList);
    }
}

}

InnerListAdapter.java

public class InnerListAdapter extends RecyclerView.Adapter<InnerListAdapter.InnerViewHolder> {

private List<POJOContent> items = new ArrayList<>();

@NonNull
@Override
public InnerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new InnerViewHolder(LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_inner_list, parent, false));
}

@Override
public void onBindViewHolder(@NonNull InnerViewHolder holder, int position) {
    holder.bind(items.get(position));
}

@Override
public int getItemCount() {
    return items.size();
}

void setNewItems(List<POJOContent> newItems){
    items.clear();
    items.addAll(newItems);
    notifyDataSetChanged();
}

class InnerViewHolder extends RecyclerView.ViewHolder{
    TextView tv_value;
    TextView tv_content;

    InnerViewHolder(@NonNull View itemView) {
        super(itemView);
        tv_value = itemView.findViewById(R.id.tv_value);
        tv_content = itemView.findViewById(R.id.tv_content);
    }

    void bind(POJOContent pojoContent){
        tv_value.setText(pojoContent.getKey());
        tv_content.setText(pojoContent.getContent());
    }
}

}

fragment_content_card.xml 布局

    <?xml version="1.0" encoding="utf-8"?>
   <androidx.cardview.widget.CardView 
    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="wrap_content"
    android:layout_margin="8dp"
    android:padding="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_Id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            android:textSize="32sp"
            android:textColor="@color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="ID" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_inner_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_Id" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>


item_inner_list.xml 的内部RecylerVoews视口的布局


item_inner_list.xml layout for inner recylerVoews' viewholder

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
    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="wrap_content">

    <TextView
        android:id="@+id/tv_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="value" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="8dp"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_value"
        tools:text="content" />

</androidx.constraintlayout.widget.ConstraintLayout>

这篇关于在Recyclerview的一个TextView中显示相同键的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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