1

In this Screenshot

That is when the sender from one device sends message,it should appear on the right hand side and when the other device gets the message it should appear on the left hand side.

My java class: This is the function I am calling

private void chatRowStyling(boolean isItMe, ViewHolder holder){

    if (isItMe){
        holder.layoutParams.gravity = Gravity.END;
        holder.chatBody.setTextColor(Color.BLUE);
        holder.senderName.setBackgroundResource(R.drawable.speech_bubble_green);

    }else{
        holder.layoutParams.gravity = Gravity.START;
        holder.chatBody.setTextColor(Color.GREEN);
        holder.senderName.setBackgroundResource(R.drawable.speech_bubble_orange);
    }
    Log.i("TAG","error :" + mySnapShot);

    holder.senderName.setLayoutParams(holder.layoutParams);
    holder.chatBody.setLayoutParams(holder.layoutParams);
}

In the Screenshot, all the messages appear on the right side, whereas I want one to be on right and another to be on left from different users.

This is my XML code :

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/singleMessageContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

<TextView
    android:id="@+id/author"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="start"
    android:paddingLeft="12dp"
    android:paddingRight="12dp"
    android:text="@string/sender"
    android:textColor="#2980b9"
    android:textSize="16sp"
    android:textStyle="bold" />


<TextView
    android:id="@+id/message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="start"
    android:layout_margin="5dip"
    android:padding="12dp"
    android:text="@string/author"
    android:textColor="#2c3e50" />



</LinearLayout>
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
Anas
  • 37
  • 6

2 Answers2

1

The best way to do it would be to implement RecyclerView with separate view types, that way you could adjust layout however you want without some shady workaround. Here is example to do it.

Reference : How to create RecyclerView with multiple view type?

EDIT: Convinced by comments I decided to add some more explanation.

You could create two separate layouts, one for your messages:

<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">

    <TextView
        android:id="@+id/tvAuthor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"/>

    <TextView
        android:id="@+id/tvMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tvAuthor"
        android:layout_alignParentRight="true"/>
</RelativeLayout>

and the other one for messages from friend:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tvAuthor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tvAuthor" />

</RelativeLayout>

Then you can create a class for your messages:

public class Message {

    private String message;
    private String author;

    public Message(String message, String author) {
        this.message = message;
        this.author = author;
    }

    public String getMessage() {
        return message;
    }

    public String getAuthor() {
        return author;
    }
}

Next step would be to create adapter for your RecyclerView that will use two seperate ViewHolders, one for your messages and the other for messages from your friend. Inside OnCreateViewHolder you can choose which layout you want to display for each message. Then in OnBindViewHolder, you can fill TextViews with correct message data.

public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private ArrayList<Message> messages;

    private final static int TYPE_FROM_FRIEND = 1;
    private final static int TYPE_TO_FRIEND = 2;

    public MessageAdapter(ArrayList<Message> messages) {
        this.messages = messages;
    }

    public int getItemViewType(int position) {
        if (messages.get(position).getAuthor().equals("Me")) {
            return TYPE_TO_FRIEND;
        } else {
            return TYPE_FROM_FRIEND;
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        int layout = 0;
        RecyclerView.ViewHolder viewHolder;

        switch (viewType){
            case TYPE_TO_FRIEND:
                layout = R.layout.view_message_to_friend;
                View toFriendView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder=new ToFriendViewHolder(toFriendView);
                break;
            case TYPE_FROM_FRIEND:
                layout = R.layout.view_message_from_friend;
                View fromFriendView = LayoutInflater
                        .from(parent.getContext())
                        .inflate(layout, parent, false);
                viewHolder = new FromFriendViewHolder(fromFriendView);
                break;
            default:
                viewHolder = null;
                break;
        }
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        int viewType=holder.getItemViewType();
        switch (viewType){
            case TYPE_TO_FRIEND:
                ((ToFriendViewHolder)holder).tvMessage.setText(messages.get(position).getMessage());
                ((ToFriendViewHolder)holder).tvAuthor.setText(messages.get(position).getAuthor());
                break;
            case TYPE_FROM_FRIEND:
                ((FromFriendViewHolder)holder).tvMessage.setText(messages.get(position).getMessage());
                ((FromFriendViewHolder)holder).tvAuthor.setText(messages.get(position).getAuthor());
                break;
        }
    }

    private class ToFriendViewHolder extends RecyclerView.ViewHolder {
        private TextView tvAuthor;
        private TextView tvMessage;

        public ToFriendViewHolder(View view) {
            super(view);
            tvAuthor = (TextView) view.findViewById(R.id.tvAuthor);
            tvMessage = (TextView) view.findViewById(R.id.tvMessage);
        }
    }

    private class FromFriendViewHolder extends RecyclerView.ViewHolder {
        private TextView tvAuthor;
        private TextView tvMessage;

        public FromFriendViewHolder(View view) {
            super(view);
            tvAuthor = (TextView) view.findViewById(R.id.tvAuthor);
            tvMessage = (TextView) view.findViewById(R.id.tvMessage);
        }
    }

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

Finally you can set RecyclerView's adapter in your activity:

public class MainActivity extends AppCompatActivity {

    private RecyclerView rvMain;
    private ArrayList<Message> messages = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        rvMain = (RecyclerView) findViewById(R.id.rvMain);
        rvMain.setLayoutManager(new LinearLayoutManager(this));
        messages.add(new Message("Hello", "Me"));
        messages.add(new Message("Hi", "Friend"));
        messages.add(new Message("How are you?", "Me"));
        messages.add(new Message("I'm fine and you?", "Friend"));
        MessageAdapter adapter = new MessageAdapter(messages);
        rvMain.setAdapter(adapter);
    }
}
Michał Witanowski
  • 602
  • 3
  • 8
  • 22
0

You can achieve it by setting the view gravity not the LayoutParams with something like this:

if(isIfMe) {
  holder.linearLayout.setGravity(Gravity.END);
  holder.tvAuthor.setGravity(Gravity.END);

} else {
  holder.linearLayout.setGravity(Gravity.END);
  holder.tvAuthor.setGravity(Gravity.END);
}
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96