In this post, I will present a library called BubbleLayout to make a simple Bubble View for Android app with custom stroke width and color, arrow size, position and direction.
Setting up the library
build.gradle:
dependencies {
    compile 'com.daasuu:BubbleLayout:1.1.1'
}
Some important attributes
<com.daasuu.bl.BubbleLayout, it has some notable attributes:bl_arrowWidth: Width of the arrow, default value is 8dpbl_arrowHeight:Height of the arrow, default value is 8dpbl_arrowPosition: Position of the arrow, default value is 12dpbl_cornersRadius: Corner radius of theBubbleLayout, default value is 0dpbl_bubbleColor: Color of theBubbleLayout, default color is whitebl_arrowDirection: Drawing position of the arrow :leftortoporrightorbottom, default position isleft.
activity_example.xml
    Running this activity, we'll have this output:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.daasuu.bubblelayout.MainActivity">
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="8dp"
        app:bl_arrowDirection="left"
        app:bl_arrowHeight="8dp"
        app:bl_arrowPosition="16dp"
        app:bl_arrowWidth="8dp"
        app:bl_strokeWidth="1dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="4dp"
            android:text="BubbleLayout"
            android:textColor="@android:color/holo_red_dark" />
    </com.daasuu.bl.BubbleLayout>
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:padding="8dp"
        app:bl_arrowDirection="top"
        app:bl_arrowHeight="8dp"
        app:bl_arrowPosition="12dp"
        app:bl_arrowWidth="8dp"
        app:bl_bubbleColor="@android:color/holo_blue_light"
        app:bl_cornersRadius="8dp">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <ImageView
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:src="@mipmap/ic_launcher" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="4dp"
                android:text="BubbleLayout"
                android:textColor="@android:color/holo_red_dark" />
        </LinearLayout>
    </com.daasuu.bl.BubbleLayout>
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:padding="8dp"
        app:bl_arrowDirection="right"
        app:bl_arrowHeight="8dp"
        app:bl_arrowPosition="16dp"
        app:bl_arrowWidth="8dp"
        app:bl_cornersRadius="6dp"
        app:bl_strokeWidth="1dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="4dp"
            android:text="BubbleLayout"
            android:textColor="@android:color/holo_red_dark" />
    </com.daasuu.bl.BubbleLayout>
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:padding="8dp"
        app:bl_arrowDirection="bottom"
        app:bl_arrowHeight="8dp"
        app:bl_arrowPosition="16dp"
        app:bl_arrowWidth="8dp"
        app:bl_bubbleColor="@android:color/holo_green_light"
        app:bl_cornersRadius="6dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="4dp"
            android:text="BubbleLayout"
            android:textColor="@android:color/white" />
    </com.daasuu.bl.BubbleLayout>
    <Button
        android:id="@+id/btn_popup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Bubble Popup" />
</LinearLayout>
Buidling a instant message application UI
ListView like this:
activitiy_main.xml
Create a POJO for the project:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.devexchanges.bubblechatui.MainActivity">
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:paddingBottom="20dp"
        android:divider="@null"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.1"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">
        <EditText
            android:id="@+id/msg_type"
            android:layout_width="0dp"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:layout_height="match_parent"
            android:layout_weight="0.7"
            android:hint="Input message" />
        <Button
            android:id="@+id/btn_chat_send"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:background="@color/background_floating_material_dark"
            android:text="Send"
            android:textColor="@color/background_material_light" />
    </LinearLayout>
</RelativeLayout>
ChatMessage.java
    And the package info.devexchanges.bubblechatui;
public class ChatMessage {
    private boolean isMine;
    private String message;
    public ChatMessage(String message, boolean isMine) {
        this.isMine = isMine;
        this.message = message;
    }
    public boolean isMine() {
        return isMine;
    }
    public void setMine(boolean mine) {
        isMine = mine;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
ListView adapter, based on ArrayAdapter:
ChatListAdapter.java
    Code for our main activity, getting messages from an package info.devexchanges.bubblechatui;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class ChatListAdapter extends ArrayAdapter<ChatMessage>{
    private Activity activity;
    private ArrayList<ChatMessage> chatMessages;
    public ChatListAdapter(Activity context, int resource, ArrayList<ChatMessage> objects) {
        super(context, resource, objects);
        this.activity =context;
        this.chatMessages = objects;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        int layoutResource; // determined by view type
        ChatMessage chatMessage = getItem(position);
        if (chatMessage.isMine()) {
            layoutResource = R.layout.item_out;
        } else {
            layoutResource = R.layout.item_in;
        }
        if (convertView != null) {
            holder = (ViewHolder) convertView.getTag();
        } else {
            convertView = inflater.inflate(layoutResource, parent, false);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        }
        //set message content
        holder.message.setText(chatMessage.getMessage());
        return convertView;
    }
    @Override
    public int getViewTypeCount() {
        // return the total number of view types. this value should never change
        // at runtime
        return 2;
    }
    @Override
    public int getItemViewType(int position) {
        // return a value between 0 and (getViewTypeCount - 1)
        return position % 2;
    }
    static class ViewHolder {
        private TextView message;
        public ViewHolder(View v) {
            message = (TextView)v.findViewById(R.id.text);
        }
    }
}
EditText:
MainActivity.java
    As you can see, I use 2 layouts for message items, based on it's in or out message, this is these layout file:
package info.devexchanges.bubblechatui;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private View btnSend;
    private EditText input;
    private ArrayList<ChatMessage> messages;
    private ChatListAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        messages = new ArrayList<>();
        listView = (ListView) findViewById(R.id.list_view);
        btnSend = findViewById(R.id.btn_chat_send);
        input = (EditText) findViewById(R.id.msg_type);
        //set ListView adapter first
        adapter = new ChatListAdapter(this, R.layout.item_out, messages);
        listView.setAdapter(adapter);
        //event for button SEND
        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (input.getText().toString().trim().equals("")) {
                    Toast.makeText(MainActivity.this, "Please input some text...", Toast.LENGTH_SHORT).show();
                } else {
                    //add message to list
                    ChatMessage chatMessage = new ChatMessage(input.getText().toString(), isMine());
                    messages.add(chatMessage);
                    adapter.notifyDataSetChanged();
                    listView.setSelection(adapter.getCount() - 1); //always scroll to bottom of list view
                    input.setText("");
                }
            }
        });
    }
    private boolean isMine() {
        Random random = new Random();
        Log.d("Main", "" + random.nextBoolean());
        return random.nextBoolean();
    }
}
item_in.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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:padding="8dp"
        app:bl_arrowDirection="left"
        app:bl_arrowHeight="10dp"
        app:bl_arrowPosition="50dp"
        android:layout_alignParentRight="true"
        app:bl_arrowWidth="15dp"
        app:bl_bubbleColor="@android:color/holo_blue_light"
        app:bl_cornersRadius="15dp">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:layout_width="wrap_content"
            android:contentDescription="@null"
            android:layout_height="wrap_content"
            android:src="@mipmap/out" />
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="5dp"
            android:textColor="@android:color/holo_red_dark" />
    </LinearLayout>
    </com.daasuu.bl.BubbleLayout>
</RelativeLayout>
item_out.xml
Running this application, you'll see this output:
<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.daasuu.bl.BubbleLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:padding="8dp"
        app:bl_arrowDirection="right"
        app:bl_arrowHeight="8dp"
        app:bl_arrowPosition="50dp"
        app:bl_arrowWidth="15dp"
        app:bl_bubbleColor="@android:color/holo_green_light"
        app:bl_cornersRadius="6dp">
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <ImageView
                android:contentDescription="@null"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/in" />
            <TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="4dp"
                android:textColor="@android:color/white" />
        </LinearLayout>
    </com.daasuu.bl.BubbleLayout>
</RelativeLayout>