From 12bdee1617cbe76321d58d8c8e45f0217fb2066e Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Wed, 15 Aug 2018 18:59:52 +0200 Subject: [PATCH] Use RecyclerView for conversation messages --- .../adapters/ConversationMessageAdapter.java | 300 ++++++++---------- .../ui/fragments/ConversationFragment.java | 16 +- .../conversation_message_currentuser_bg.xml | 14 + .../conversation_message_otheruser_bg.xml | 14 + ...nt_conversation_message_currentuser_bg.xml | 25 -- ...ment_conversation_message_otheruser_bg.xml | 25 -- .../conversation_message_item_received.xml | 55 ++++ .../layout/conversation_message_item_sent.xml | 34 ++ .../main/res/layout/fragment_conversation.xml | 2 +- .../fragment_conversation_message_item.xml | 65 ---- 10 files changed, 262 insertions(+), 288 deletions(-) create mode 100644 app/src/main/res/drawable/conversation_message_currentuser_bg.xml create mode 100644 app/src/main/res/drawable/conversation_message_otheruser_bg.xml delete mode 100644 app/src/main/res/drawable/fragment_conversation_message_currentuser_bg.xml delete mode 100644 app/src/main/res/drawable/fragment_conversation_message_otheruser_bg.xml create mode 100644 app/src/main/res/layout/conversation_message_item_received.xml create mode 100644 app/src/main/res/layout/conversation_message_item_sent.xml delete mode 100644 app/src/main/res/layout/fragment_conversation_message_item.xml diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/ConversationMessageAdapter.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/ConversationMessageAdapter.java index 7077eac..50ffcc6 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/ConversationMessageAdapter.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/ConversationMessageAdapter.java @@ -1,24 +1,18 @@ package org.communiquons.android.comunic.client.ui.adapters; import android.content.Context; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; import android.util.ArrayMap; -import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import org.communiquons.android.comunic.client.R; -import org.communiquons.android.comunic.client.data.helpers.ImageLoadHelper; import org.communiquons.android.comunic.client.data.models.UserInfo; import org.communiquons.android.comunic.client.data.models.ConversationMessage; -import org.communiquons.android.comunic.client.ui.utils.UiUtils; -import org.communiquons.android.comunic.client.ui.views.WebImageView; import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage; import java.util.ArrayList; @@ -30,12 +24,18 @@ import java.util.ArrayList; * Created by pierre on 12/18/17. */ -public class ConversationMessageAdapter extends ArrayAdapter { +public class ConversationMessageAdapter extends RecyclerView.Adapter { + + /** + * View messages types + */ + private static final int VIEW_TYPE_MESSAGE_SENT = 1; + private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2; /** * Debug tag */ - private static final String TAG = "ConversationMessageAdap"; + private static final String TAG = ConversationMessageAdapter.class.getCanonicalName(); /** * The ID of the current user @@ -47,6 +47,16 @@ public class ConversationMessageAdapter extends ArrayAdapter usersInfo; + /** + * Activity context + */ + private Context mContext; + + /** + * Conversation messages + */ + private ArrayList mList; + /** * Public class constructor * @@ -56,177 +66,137 @@ public class ConversationMessageAdapter extends ArrayAdapter list, int userID, ArrayMap usersInfo){ - super(context, 0, list); + super(); - //Set user ID + //Set values this.userID = userID; - - //Set user information list this.usersInfo = usersInfo; + this.mContext = context; + this.mList = list; } + @Override + public int getItemCount() { + return mList.size(); + } + + public ConversationMessage getAt(int pos){ + return mList.get(pos); + } + + @Override + public int getItemViewType(int position) { + return mList.get(position).getUser_id() == userID ? VIEW_TYPE_MESSAGE_SENT + : VIEW_TYPE_MESSAGE_RECEIVED; + } @NonNull @Override - public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) { + View view; - //Inflate view if required - if(convertView == null) - convertView = LayoutInflater.from(getContext()). - inflate(R.layout.fragment_conversation_message_item, parent, false); - - - //Get the content of the message - ConversationMessage message = getItem(position); - assert message != null; - - //Get the previous message - ConversationMessage previousMessage = null; - if(position > 0){ - previousMessage = getItem(position-1); + if(type == VIEW_TYPE_MESSAGE_SENT){ + view = LayoutInflater.from(mContext).inflate(R.layout.conversation_message_item_sent, + viewGroup, false); + return new SentMessageHolder(view); } - /* - Get the view of the messages - - Update the general layout of the message - */ - //Get the views - LinearLayout containerView = convertView - .findViewById(R.id.fragment_conversation_message_item_container); - TextView contentView = convertView. - findViewById(R.id.fragment_conversation_message_item_content); - WebImageView messageImageView = convertView. - findViewById(R.id.fragment_conversation_message_item_messageimage); - WebUserAccountImage accountImageView; - TextView userNameView = convertView. - findViewById(R.id.fragment_conversation_message_item_username); - - //Adapt the layout depending of user of the message - if(message.getUser_id() == userID){ - - //Message appears on the right - ((LinearLayout)convertView).setGravity(Gravity.END); - - //Message appears in blue - containerView.setBackground(getContext(). - getDrawable(R.drawable.fragment_conversation_message_currentuser_bg)); - - //User account image appears on the right - accountImageView = convertView. - findViewById(R.id.fragment_conversation_message_item_right_account_image); - accountImageView.setVisibility(View.VISIBLE); - - //Hide left image - convertView - .findViewById(R.id.fragment_conversation_message_item_left_account_image) - .setVisibility(View.GONE); - - //Align text on the right - contentView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END); - - } - else { - - - - //Message appears on the right - ((LinearLayout)convertView).setGravity(Gravity.START); - - //Message appears in blue - containerView.setBackground(getContext(). - getDrawable(R.drawable.fragment_conversation_message_otheruser_bg)); - - //User account image appears on the left - accountImageView = convertView. - findViewById(R.id.fragment_conversation_message_item_left_account_image); - accountImageView.setVisibility(View.VISIBLE); - - //Hide right image - convertView - .findViewById(R.id.fragment_conversation_message_item_right_account_image) - .setVisibility(View.GONE); - - //Align text on the left - contentView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START); + else if(type == VIEW_TYPE_MESSAGE_RECEIVED){ + view = LayoutInflater.from(mContext).inflate(R.layout.conversation_message_item_received, + viewGroup, false); + return new ReceivedMessageHolder(view); } - /* - Check for user information - */ - UserInfo user = null; - if(usersInfo.containsKey(message.getUser_id())){ - user = usersInfo.get(message.getUser_id()); - } - - - /* - Update message content - */ - //Set the text of the message - contentView.setText(message.getContent()); - - //Change the color of the text - if(message.getUser_id() == userID){ - contentView.setTextColor(UiUtils.getColor(getContext(), - R.color.conversation_user_messages_textColor)); - } - else { - contentView.setTextColor(UiUtils.getColor(getContext(), - R.color.conversation_otheruser_messages_textColor)); - } - - /* - Update message image - */ - if(message.hasImage()){ - //Load the image - messageImageView.loadURL(message.getImage_path()); - - //Make the image visible - messageImageView.setVisibility(View.VISIBLE); - } - else { - messageImageView.setVisibility(View.GONE); - } - - /* - Update user name - */ - if(userNameView != null){ - - //Hide user name by default - userNameView.setVisibility(View.GONE); - - if(user != null){ - if(userID != user.getId()) { - //Set the name of the user - userNameView.setText(user.getFullName()); - userNameView.setVisibility(View.VISIBLE); - } - } - - if(previousMessage != null){ - if (message.getUser_id() == previousMessage.getUser_id()){ - userNameView.setVisibility(View.GONE); - } - } - - } - - /* - Update account image - */ - - //Check if we can load a specific image - if(user != null) { - accountImageView.setUser(user); - } else - accountImageView.removeUser(); + throw new RuntimeException("Could not determine view type!"); + } + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { + switch (viewHolder.getItemViewType()){ + case VIEW_TYPE_MESSAGE_SENT: + ((SentMessageHolder) viewHolder).bind(position); + break; - return convertView; + case VIEW_TYPE_MESSAGE_RECEIVED: + ((ReceivedMessageHolder) viewHolder).bind(position); + break; + } + } + + /** + * Base messages holder + */ + private class BaseMessageHolder extends RecyclerView.ViewHolder { + + private TextView mMessage; + + BaseMessageHolder(@NonNull View itemView) { + super(itemView); + + mMessage = itemView.findViewById(R.id.message_body); + } + + /** + * Bind view for a conversation message + * + * @param pos The message to bind + */ + @CallSuper + void bind(int pos){ + mMessage.setText(getAt(pos).getContent()); + } + } + + /** + * Sent messages holder + */ + private class SentMessageHolder extends BaseMessageHolder { + + SentMessageHolder(@NonNull View itemView) { + super(itemView); + } + } + + /** + * Received messages holder + */ + private class ReceivedMessageHolder extends BaseMessageHolder { + + WebUserAccountImage mUserAccountImage; + TextView mUserName; + + ReceivedMessageHolder(@NonNull View itemView) { + super(itemView); + + mUserAccountImage = itemView.findViewById(R.id.account_image); + mUserName = itemView.findViewById(R.id.user_name); + } + + void setUserInfoVisibility(boolean visible){ + mUserAccountImage.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); + mUserName.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + void bind(int pos) { + super.bind(pos); + + //Apply user information + mUserAccountImage.removeUser(); + mUserName.setText(""); + + if(usersInfo.containsKey(getAt(pos).getUser_id())){ + UserInfo info = usersInfo.get(getAt(pos).getUser_id()); + mUserAccountImage.setUser(info); + mUserName.setText(info.getDisplayFullName()); + } + + if(pos < 2) + setUserInfoVisibility(true); + else + if(getAt(pos).getUser_id() == getAt(pos-1).getUser_id()) + setUserInfoVisibility(false); + } } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/ConversationFragment.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/ConversationFragment.java index 3891d9d..5d2a9d6 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/ConversationFragment.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/fragments/ConversationFragment.java @@ -9,6 +9,8 @@ import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.util.ArrayMap; import android.util.Log; import android.view.KeyEvent; @@ -31,7 +33,6 @@ import org.communiquons.android.comunic.client.data.models.ConversationsInfo; import org.communiquons.android.comunic.client.data.models.UserInfo; import org.communiquons.android.comunic.client.data.runnables.ConversationRefreshRunnable; import org.communiquons.android.comunic.client.data.utils.AccountUtils; -import org.communiquons.android.comunic.client.ui.activities.MainActivity; import org.communiquons.android.comunic.client.ui.adapters.ConversationMessageAdapter; import org.communiquons.android.comunic.client.ui.listeners.OnScrollChangeDetectListener; import org.communiquons.android.comunic.client.ui.utils.BitmapUtils; @@ -114,7 +115,7 @@ public class ConversationFragment extends Fragment /** * Conversation message listView */ - private ScrollListView convMessListView; + private RecyclerView convMessRecyclerView; /** * Conversation messages helper @@ -224,7 +225,7 @@ public class ConversationFragment extends Fragment display_not_msg_notice(false); //Conversation messages listView - convMessListView = view.findViewById(R.id.fragment_conversation_messageslist); + convMessRecyclerView = view.findViewById(R.id.fragment_conversation_messageslist); //Need user ID int userID = new AccountUtils(getActivity()).get_current_user_id(); @@ -234,7 +235,8 @@ public class ConversationFragment extends Fragment messagesList, userID, users); //Apply adapter - convMessListView.setAdapter(convMessAdapter); + convMessRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + convMessRecyclerView.setAdapter(convMessAdapter); //Get new messages input fields new_message_content = view.findViewById(R.id.fragment_conversation_newmessage_content); @@ -285,7 +287,7 @@ public class ConversationFragment extends Fragment //Set a listener to detect when the user reaches the top of the conversation - convMessListView.setOnScrollChangeDetectListener(this); + //convMessRecyclerView.setOnScrollChangeDetectListener(this); } @Override @@ -407,9 +409,9 @@ public class ConversationFragment extends Fragment } /** - * This method is called when we get informations about users + * This method is called when we get information about users * - * @param info Informations about the user + * @param info Information about the user */ public void onGotUserInfo(@Nullable ArrayMap info ){ diff --git a/app/src/main/res/drawable/conversation_message_currentuser_bg.xml b/app/src/main/res/drawable/conversation_message_currentuser_bg.xml new file mode 100644 index 0000000..28f0679 --- /dev/null +++ b/app/src/main/res/drawable/conversation_message_currentuser_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/conversation_message_otheruser_bg.xml b/app/src/main/res/drawable/conversation_message_otheruser_bg.xml new file mode 100644 index 0000000..a62f887 --- /dev/null +++ b/app/src/main/res/drawable/conversation_message_otheruser_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/fragment_conversation_message_currentuser_bg.xml b/app/src/main/res/drawable/fragment_conversation_message_currentuser_bg.xml deleted file mode 100644 index a4577fa..0000000 --- a/app/src/main/res/drawable/fragment_conversation_message_currentuser_bg.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/fragment_conversation_message_otheruser_bg.xml b/app/src/main/res/drawable/fragment_conversation_message_otheruser_bg.xml deleted file mode 100644 index b4b91da..0000000 --- a/app/src/main/res/drawable/fragment_conversation_message_otheruser_bg.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_message_item_received.xml b/app/src/main/res/layout/conversation_message_item_received.xml new file mode 100644 index 0000000..23fdc22 --- /dev/null +++ b/app/src/main/res/layout/conversation_message_item_received.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_message_item_sent.xml b/app/src/main/res/layout/conversation_message_item_sent.xml new file mode 100644 index 0000000..2446096 --- /dev/null +++ b/app/src/main/res/layout/conversation_message_item_sent.xml @@ -0,0 +1,34 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_conversation.xml b/app/src/main/res/layout/fragment_conversation.xml index 1b19a43..7ac3ae0 100644 --- a/app/src/main/res/layout/fragment_conversation.xml +++ b/app/src/main/res/layout/fragment_conversation.xml @@ -27,7 +27,7 @@ android:layout_height="match_parent"> - - - - - - - - - - - - - - - -