12

How to show date or today , yesterday like text in between conversation

like whatsapp

enter image description here

Gaurav
  • 3,615
  • 2
  • 27
  • 50
  • check http://stackoverflow.com/questions/33226491/how-do-i-display-the-calendar-date-on-the-top-of-chat-messages – Shahab Rauf Nov 15 '16 at 16:17
  • 1
    @ShahabRauf I asked this question on 30th Sep 2015, and you are giving link of question asked in 20th Oct 2015 – Gaurav Nov 16 '16 at 05:26
  • It is not for you, check your question views which are 647 times. It is for the viewers who are facing the same problem as you were and if they read your question they can be redirected to the answer via the link i wrote here. I hope you'll understand – Shahab Rauf Nov 16 '16 at 07:38
  • 1
    @ShahabRauf Good :) , but This question is answered here, So why to redirect somewhere else. – Gaurav Nov 16 '16 at 12:43

3 Answers3

15

enter image description here

MainActivity

public class MainActivity extends AppCompatActivity {

    private ChatAdapter chatAdapter;
    private RecyclerView recyclerView;
    private Context context;
    private int loggedInUserID;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        bindRecyclerView();
        // TODO get logged in user id and initialize into 'loggedInUserID'
    }

    @Override
    protected void onResume() {
        super.onResume();
        getData();
    }

    private void getData() {
        /**
         *Your server call to get data and parse json to your appropriate model
         * after parsing json to model simply call the
         */
        List<ChatModel> chatModelList = ParseData.chatParser(jsonArray);
        groupDataIntoHashMap(chatModelList);
    }

    private void bindRecyclerView() {
        chatAdapter = new ChatAdapter(null);
        chatAdapter.setUser(loggedInUserID);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(chatAdapter);
    }


    private void groupDataIntoHashMap(List<ChatModel> chatModelList) {
        LinkedHashMap<String, Set<ChatModel>> groupedHashMap = new LinkedHashMap<>();
        Set<ChatModel> list = null;
        for (ChatModel chatModel : chatModelList) {
            //Log.d(TAG, travelActivityDTO.toString());
            String hashMapKey = DateParser.convertDateToString(chatModel.getChatTime());
            //Log.d(TAG, "start date: " + DateParser.convertDateToString(travelActivityDTO.getStartDate()));
            if (groupedHashMap.containsKey(hashMapKey)) {
                // The key is already in the HashMap; add the pojo object
                // against the existing key.
                groupedHashMap.get(hashMapKey).add(chatModel);
            } else {
                // The key is not there in the HashMap; create a new key-value pair
                list = new LinkedHashSet<>();
                list.add(chatModel);
                groupedHashMap.put(hashMapKey, list);
            }
        }
        //Generate list from map
        generateListFromMap(groupedHashMap);

    }


    private List<ListObject> generateListFromMap(LinkedHashMap<String, Set<ChatModel>> groupedHashMap) {
        // We linearly add every item into the consolidatedList.
        List<ListObject> consolidatedList = new ArrayList<>();
        for (String date : groupedHashMap.keySet()) {
            DateObject dateItem = new DateObject();
            dateItem.setDate(date);
            consolidatedList.add(dateItem);
            for (ChatModel chatModel : groupedHashMap.get(date)) {
                ChatModelObject generalItem = new ChatModelObject();
                generalItem.setChatModel(chatModel);
                consolidatedList.add(generalItem);
            }
        }

        chatAdapter.setDataChange(consolidatedList);

        return consolidatedList;
    }

}

ChatModel.java

public class ChatModel implements Serializable {
        private String messageId;
        private int userId;
        private String firstName;
        private String userName;
        private String message;
        private Date chatTime;

        //TODO generate getter and setter

    }

ListObject.java (to determind the type of message)

public abstract class ListObject {
        public static final int TYPE_DATE = 0;
        public static final int TYPE_GENERAL_RIGHT = 1;
        public static final int TYPE_GENERAL_LEFT = 2;

        abstract public int getType(int userId);
    }

DateObject.java

public class DateObject extends ListObject {
        private String date;

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        @Override
        public int getType(int userId) {
            return TYPE_DATE;
        }
    }

ChatModelObject.java

public class ChatModelObject extends ListObject {

        private ChatModel chatModel;

        public ChatModel getChatModel() {
            return chatModel;
        }

        public void setChatModel(ChatModel chatModel) {
            this.chatModel = chatModel;
        }

        @Override
        public int getType(int userId) {
            if (this.chatModel.getUserId() == userId) {
                return TYPE_GENERAL_RIGHT;
            } else
                return TYPE_GENERAL_LEFT;
        }
    }

DateParse.java to parse date for grouping the chat

public class DateParser {
        private static DateFormat dateFormat1 = new SimpleDateFormat("dd/MM/yyyy");

        public static String convertDateToString(Date date) {
            String strDate = "";
            strDate = dateFormat1.format(date);
            return strDate;
        }
    }

ChatAdapter.java

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

        private List<ListObject> listObjects;
        private int loggedInUserId;

        public ChatAdapter(List<ListObject> listObjects) {
            this.listObjects = listObjects;
        }

        public void setUser(int userId) {
            this.loggedInUserId = userId;
        }

        public void setDataChange(List<ListObject> asList) {
            this.listObjects = asList;
            //now, tell the adapter about the update
            notifyDataSetChanged();
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            RecyclerView.ViewHolder viewHolder = null;
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            switch (viewType) {
                case ListObject.TYPE_GENERAL_RIGHT:
                    View currentUserView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_chat_list_row_right, parent, false);
                    viewHolder = new ChatRightViewHolder(currentUserView); // view holder for normal items
                    break;
                case ListObject.TYPE_GENERAL_LEFT:
                    View otherUserView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_chat_list_row_left, parent, false);
                    viewHolder = new ChatLeftViewHolder(otherUserView); // view holder for normal items
                    break;
                case ListObject.TYPE_DATE:
                    View v2 = inflater.inflate(R.layout.date_row, parent, false);
                    viewHolder = new DateViewHolder(v2);
                    break;
            }

            return viewHolder;

        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
            switch (viewHolder.getItemViewType()) {
                case ListObject.TYPE_GENERAL_RIGHT:
                    ChatModelObject generalItem = (ChatModelObject) listObjects.get(position);
                    ChatRightViewHolder chatViewHolder = (ChatRightViewHolder) viewHolder;
                    chatViewHolder.bind(generalItem.getChatModel());
                    break;
                case ListObject.TYPE_GENERAL_LEFT:
                    ChatModelObject generalItemLeft = (ChatModelObject) listObjects.get(position);
                    ChatLeftViewHolder chatLeftViewHolder = (ChatLeftViewHolder) viewHolder;
                    chatLeftViewHolder.bind(generalItemLeft.getChatModel());
                    break;
                case ListObject.TYPE_DATE:
                    DateObject dateItem = (DateObject) listObjects.get(position);
                    DateViewHolder dateViewHolder = (DateViewHolder) viewHolder;
                    dateViewHolder.bind(dateItem.getDate());
                    break;
            }
        }

        @Override
        public int getItemCount() {
            if (listObjects != null) {
                return listObjects.size();
            }
            return 0;
        }

        @Override
        public int getItemViewType(int position) {
            return listObjects.get(position).getType(loggedInUserId);
        }

        public ListObject getItem(int position) {
            return listObjects.get(position);
        }
    }

ChatRightViewHolder.java for current user message

public class ChatRightViewHolder extends RecyclerView.ViewHolder {
        private final String TAG = ChatRightViewHolder.class.getSimpleName();

        public ChatRightViewHolder(View itemView) {
            super(itemView);
            //TODO initialize your xml views
        }

        public void bind(final ChatModel chatModel) {
            //TODO set data to xml view via textivew.setText();
        }
    }

ChatLeftViewHolder.java for display other user messages.

public class ChatLeftViewHolder extends RecyclerView.ViewHolder {
        private final String TAG = ChatRightViewHolder.class.getSimpleName();

        public ChatLeftViewHolder(View itemView) {
            super(itemView);
            //TODO initialize your xml views
        }

        public void bind(final ChatModel chatModel) {
            //TODO set data to xml view via textivew.setText();
        }
    }

DateViewHolder.java to display date

public class DateViewHolder extends RecyclerView.ViewHolder {
        public DateViewHolder(View itemView) {
            super(itemView);
            //TODO initialize your xml views
        }

        public void bind(final String date) {
            //TODO set data to xml view via textivew.setText();
        }
    }
akhilesh0707
  • 6,709
  • 5
  • 44
  • 51
10

You need to create a new ViewHolder for that purpose

For example:

// Different types of rows
private static final int TYPE_ITEM_LEFT = 0;
private static final int TYPE_ITEM_RIGHT = 1;
private static final int TYPE_ITEM_DATE_CONTAINER = 2;

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class ViewHolder0 extends RecyclerView.ViewHolder {
    // Viewholder for row type 0
}

class ViewHolder1 extends RecyclerView.ViewHolder {
    // Viewholder for row type 1
}

class ViewHolder2 extends RecyclerView.ViewHolder {
    // Viewholder for row type 2
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
     if (viewHolder.getItemViewType() == TYPE_ITEM_LEFT) {
         // Code to populate type 0 view here

     } else if (viewHolder.getItemViewType() == TYPE_ITEM_RIGHT) {
         // Code to populate type 1 view here

     } else if (viewHolder.getItemViewType() == TYPE_ITEM_DATE_CONTAINER) {
         // Code to populate type 2 view here

     }
}
Abdullah
  • 9,005
  • 1
  • 23
  • 24
Silvestr
  • 704
  • 4
  • 13
0

You just have to compare the date when scrolling and set the visibility of date view. The advantage of this is there's no hard-coded today/yesterday in data list and is able to refresh the correct date immediately (scrolling) after 12.00 a.m.

e.g. in your onBindViewHolder() in recycleview:

        if (position != 0) {
            processDate(holder.topDateTextView, myData.getDate()
                    , this.myDataList.get(position - 1).getDate()
                    , false)
            ;
        } else {
            processDate(holder.topDateTextView, data.getDay()
                    , null
                    , true)
            ;
        }

Method to process that date view (Assume your list has format "dd/MM/yyyy"):

   private void processDate(@NonNull TextView tv, String dateAPIStr
        , String dateAPICompareStr
        , boolean isFirstItem) {

    SimpleDateFormat f = new SimpleDateFormat("dd/MM/yyyy");
    if (isFirstItem) {
        //first item always got date/today to shows
        //and overkill to compare with next item flow
        Date dateFromAPI = null;
        try {
            dateFromAPI = f.parse(dateAPIStr);
            if (DateUtils.isToday(dateFromAPI.getTime())) tv.setText("today");
            else if (DateUtils.isToday(dateFromAPI.getTime() + DateUtils.DAY_IN_MILLIS)) tv.setText("yesterday");
            else tv.setText(dateAPIStr);
            tv.setIncludeFontPadding(false);
            tv.setVisibility(View.VISIBLE);
        } catch (ParseException e) {
            e.printStackTrace();
            tv.setVisibility(View.GONE);
        }
    } else {
        if (!dateAPIStr.equalsIgnoreCase(dateAPICompareStr)) {
            try {
                Date dateFromAPI = f.parse(dateAPIStr);
                if (DateUtils.isToday(dateFromAPI.getTime())) tv.setText("today");
                else if (DateUtils.isToday(dateFromAPI.getTime() + DateUtils.DAY_IN_MILLIS)) tv.setText("yesterday");
                else tv.setText(dateAPIStr);
                tv.setIncludeFontPadding(false);
                tv.setVisibility(View.VISIBLE);
            } catch (ParseException e) {
                e.printStackTrace();
                tv.setVisibility(View.GONE);
            }
        } else {
            tv.setVisibility(View.GONE);
        }
    }
}

Note: You also need to do yourAdapter.notifyDataSetChanged(); if append new item to redraw to dismiss previous "today"/date after 12.00 a.m on the same page, not just rely on yourAdapter.notifyItemInserted(new_item_position) which doesn't redraw previous items.

林果皞
  • 7,539
  • 3
  • 55
  • 70