嵌套的RecyclerView消息系统

时间:2017-03-10 20:58:15

标签: java android android-activity android-recyclerview

我正在尝试创建一个看起来像这样的嵌套RecyclerView消息系统:

http://i.imgur.com/Oodhv44.png

我想如何实现这个是缩进每个孩子(depth * 16dp)。此外,我需要能够创建它,以便在用户单击消息时,它会折叠/展开其子消息。

消息以JSON响应的形式出现,如下所示:

[
    {
        "id":1,
        "parent_id":0,
        "depth":0,
        "text":"This is a top-level message (depth of 0)",
        "children":[
            {
                "id":2,
                "parent_id":1,
                "depth":1,
                "text":"This is a child message (depth of 1)",
                "children":[
                    {
                        "id":3,
                        "parent_id":2,
                        "depth":2,
                        "text":"This is a child message (depth of 2)",
                        "children":[

                        ]
                    }
                ]
            },
            {
                "id":4,
                "parent_id":1,
                "depth":1,
                "text":"This is a child message (depth of 1)",
                "children":[

                ]
            }
        ]
    },
    {
        "id":5,
        "parent_id":0,
        "depth":0,
        "text":"This is a top-level message (depth of 0)",
        "children":[
            {
                "id":6,
                "parent_id":5,
                "depth":1,
                "text":"This is a child message (depth of 1)",
                "children":[

                ]
            }
        ]
    }
]

JSON非常明显。每条消息都有一个children属性,可以包含更多消息。

我当前的代码输出以下结果:

http://i.imgur.com/anI2pyM.png

正如您所看到的,它没有显示任何儿童消息。如何将代码修改为:

  1. 显示子邮件并正确缩进
  2. 创建点击事件,以便在用户点击邮件时隐藏/显示子邮件
  3. 这是我的MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        private List<Message> messages;
    
        private RecyclerView recyclerView;
    
        private RecyclerView.LayoutManager mLayoutManager;
    
        private MessageAdapter messageAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    
            mLayoutManager = new LinearLayoutManager(this);
    
            recyclerView.setLayoutManager(mLayoutManager);
            recyclerView.setItemAnimator(new DefaultItemAnimator());
    
            // Set the adapter
            messageAdapter = new MessageAdapter(MainActivity.this, messages);
            recyclerView.setAdapter(messageAdapter);
        }
    }
    

    这是我的MessageAdapter.java

    public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
    
        private Context context;
    
        private List<Message> messages;
    
        public MessageAdapter(Context context, List<Message> messages) {
            this.context = context;
            this.messages = messages;
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            public Message message;
    
            public RelativeLayout messageContainer;
    
            public TextView messageText;
    
            public ViewHolder(View v) {
                super(v);
    
                messageContainer = (RelativeLayout) v.findViewById(R.id.messageContainer);
    
                messageText = (TextView) v.findViewById(R.id.messageText);
            }
    
            public void setMessage(Message message) {
                this.message = message;
            }
        }
    
        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(R.layout.message_layout, parent, false);
    
            ViewHolder viewHolder = new ViewHolder(view);
    
            return viewHolder;
        }
    
        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            final Message message = messages.get(position);
    
            holder.setMessage(message);
    
            holder.message.setText(message.getText());
        }
    
        @Override
        public int getItemCount() {
            return messages.size();
        }
    }
    

    这是我的message_layout.xml

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/messageContainer">
    
        <TextView
            android:id="@+id/messageText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </RelativeLayout>
    

    最后,这是我的Message.java模型类:

    public class Message implements Serializable {
    
        @SerializedName("id")
        @Expose
        private Integer id;
    
        @SerializedName("parent_id")
        @Expose
        private Integer parentId;
    
        @SerializedName("depth")
        @Expose
        private Integer depth;
    
        @SerializedName("text")
        @Expose
        private String text;
    
        @SerializedName("children")
        @Expose
        private List<Message> children = null;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getParentId() {
            return parentId;
        }
    
        public void setParentId(Integer parentId) {
            this.parentId = parentId;
        }
    
        public Integer getDepth() {
            return depth;
        }
    
        public void setDepth(Integer depth) {
            this.depth = depth;
        }
    
        public String getText() {
            return text;
        }
    
        public void setText(String text) {
            this.text = text;
        }
    
        public List<Message> getChildren() {
            return children;
        }
    
        public void setChildren(List<Message> children) {
            this.children = children;
        }
    
    }
    

1 个答案:

答案 0 :(得分:0)

setMessage的{​​{1}}中,您只需将填充应用于ViewHolder即可。

RelativeLayout

编辑:

实际上,最好在适配器的构造函数中计算填充,这样你只需要计算一次,但这只是一个小细节。

编辑2:

对于第1点:您需要将子项展平,以便它们位于适配器中的一个长连续列表中。只要您按顺序保存它们,它们就会按照RecyclerView的顺序显示。因此,您需要以递归方式关闭每条消息并将子项添加到适配器列表中。

你可以在模型中做一个简单的方法来像这样展平它们:

public class ViewHolder extends RecyclerView.ViewHolder {
    private final padding;

    public Message message;

    public RelativeLayout messageContainer;

    public TextView messageText;

    public ViewHolder(View v) {
        super(v);

        // Get the padding offset in pixels.
        Resources r = v.getContext().getResources();
        padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, r.getDisplayMetrics());

        messageContainer = (RelativeLayout) v.findViewById(R.id.messageContainer);

        messageText = (TextView) v.findViewById(R.id.messageText);
    }

    public void setMessage(Message message) {
        this.message = message;

        // Set the padding of the relativelayout.
        final depth = this.message.getDepth();
        messageContainer.setPadding(depth * 16, 0, 0, 0); // left, top, right, bottom
    }
}

对于第2点:您需要set up a click listener来监听项目点击次数。然后,您需要确定单击时要删除的项目数。这个逻辑比较复杂,所以它不仅仅需要对适配器进行简单的修改。但基本上,在你的模型中,创建一个名为&#34; getTotalNumberOfChildren&#34;这将计算整个树中有多少个节点。像这样:

public class Message implements Serializable {
   public List<Message> flattenChildren() {
       ArrayList<Message> childs = new ArrayList();
       if(children != null) {
         for (Message m : children) {
            // First add the child then request the flattened children of that child.
            childs.add(m);
            childs.addAll(m.flattenChildren());
         }
       }
       return childs;
   }
}

然后,只要用户点击某条消息,就可以删除该索引中的消息数。如果消息已经关闭,请重新添加。