I write a chat application using Firebase.
In ChatActivity, there are a recycler view to display chatting information. The following image is the first loading is correct.
When enter the message send to others, the layout of some messages become different.
THE CODE in MessageAdapter
public MessageAdapter(List<YeMessage> mMessageList){
this.mMsgList = mMessageList;
}
@Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message, parent, false);
mContext = parent.getContext();
ref = FirebaseDatabase.getInstance().getReference();
return new MessageViewHolder(view);
}
public class MessageViewHolder extends RecyclerView.ViewHolder{
@BindView(R.id.msg_message)
TextView messageText;
@BindView(R.id.msg_imageView)
ImageView image;
public MessageViewHolder(View view){
super(view);
ButterKnife.bind(this, view);
}
}
@Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
mAuth = FirebaseAuth.getInstance();
current_user_id = mAuth.getCurrentUser().getUid();
YeMessage c = mMsgList.get(position);
String from_user = c.getFrom();
ref.child("Users").child(from_user).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
RelativeLayout.LayoutParams rp_msg = (RelativeLayout.LayoutParams)holder.messageText.getLayoutParams();
RelativeLayout.LayoutParams rp_img = (RelativeLayout.LayoutParams)holder.image.getLayoutParams();
image = dataSnapshot.child("imageUrl").getValue().toString();
if(from_user.equals(current_user_id)){
//lp.gravity = Gravity.END;
//end
rp_img.addRule(RelativeLayout.ALIGN_PARENT_END);
//rp_img.addRule(RelativeLayout.ALIGN_PARENT_TOP);
holder.image.setLayoutParams(rp_img);
//rp_msg.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.msg_imageView);
rp_msg.addRule(RelativeLayout.START_OF, R.id.msg_imageView);
holder.messageText.setLayoutParams(rp_msg);
Glide.with(mContext)
.load(image)
.into(holder.image);
}else {
//lp.gravity = Gravity.START;
rp_img.addRule(RelativeLayout.ALIGN_PARENT_START);
rp_img.addRule(RelativeLayout.ALIGN_PARENT_TOP);
holder.image.setLayoutParams(rp_img);
rp_msg.addRule(RelativeLayout.ALIGN_PARENT_TOP);
rp_msg.addRule(RelativeLayout.END_OF, R.id.msg_imageView);
holder.messageText.setLayoutParams(rp_msg);
Glide.with(mContext)
.load(image)
.into(holder.image);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
YeMessage msg = mMsgList.get(position);
holder.messageText.setText(msg.getMessage());
}
@Override
public int getItemCount() {
return mMsgList.size();
}
I think the reason is that I have too little knowledge about the lifecycle of recycler view.
And I find if I want to change gravity in onBindViewHolder(), it can't be successful every time. Because it will be layout correctly when it calls the onCreateViewHolder().
How can to ensure that onCreateViewHolder() is called each time, so that finish to create layout programmatically?
Add item_message.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:id="@+id/message_single_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation = "horizontal"
android:padding="15dp">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/msg_imageView"
android:layout_width="45sp"
android:layout_height="45sp" />
<TextView
android:id="@+id/msg_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/message_background"
android:padding="10dp"
android:textColor="#ffffff"
/>
</RelativeLayout>
I think you can have two different layouts for incoming and outgoing messages. It will be useful to you in future when you are changing the design.
You can customize your RecyclerView according to your need. You can refer to http://www.codexpedia.com/android/android-recyclerview-with-multiple-different-layouts/ for a detailed answer.
As far as your layout is concerned.
For incoming messages-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#000000"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="askjjnads dma dm"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
/>
</LinearLayout>
for out going messages-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="askjjnads dma dm"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
/>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#000000"/>
</LinearLayout>