As you can see, it's interface look like a floating action button. This UI design you also can see at another apps like 9GAG, LinkedIn. Today, in this post, I will provide a simple way to create it: using an third-party library. But I will talk a bit about
FloatingActionButton
widget (in Design Support library) first.
Weakness of Floating Action Button
FloatingActionButton
always need CoordinatorLayout
, we can not put it into place as we would like (here is the top/center of screen) so with this design, FloatingActionButton
cannot solve our problem. Of course, you can make it yourself but like a lazy programmer like me, I'll use a simple library called PopupBubble, with attaching the
PopupBubble
button with a RecyclerView
, you will done this work easily.
Setting up the library
build.gradle
:
compile 'com.webianks.library:popup-bubble:1.0.2'
Important Note
: your project min-sdk must be 14 or higher to use this library.
Usages
PopupBubble
. Some important xml attributes are following:
<!--Change background Color-->
app:backgroundColor="?attr/colorPrimary"
<!--Change text -->
app:text="New Stories"
<!--Change text color-->
app:textColor="#ffffff"
<!--Show/Hide Icon inside the button. By default its true.-->
app:showIcon="false"
<!--Change icon color-->
app:iconColor="#ffffff"
<!--Set Different Icons-->
app:setIcon="@drawable/ic_new.png"
In Java code, it has some prominent methods:
- attaching it with
RecyclerView
by callsetRecyclerView()
method - By default, it is invisible, show/hide it with call
show()
/hide()
- Add listener if you want to know when the bubble is clicked:
popupBubble.setPopupBubbleListener(new PopupBubble.PopupBubbleClickListener() {
@Override
public void bubbleClicked(Context context) {
//popup_bubble is clicked
}
});
Sample project code
RecyclerView
data will be updated after 10 seconds (add new items) from a background thread (by using Handler
). At this moment, the bubble button will appear and if you click on it, you will be redirected to the top (like Facebook app).
Source code for
RecyclerView
adapter, a simple adapter based on RecyclerView.Adapter
:
RecyclerViewAdapter.java
And this is the main activity code:
package info.devexchanges.bubblebutton;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.CustomViewHolder> {
private List<DummyData> list;
private Context context;
public RecyclerViewAdapter(Context context, List<DummyData> list) {
this.list = list;
this.context = context;
}
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_view, parent, false);
return new CustomViewHolder(itemView);
}
@Override
public void onBindViewHolder(CustomViewHolder holder, @SuppressLint("RecyclerView") final int position) {
holder.title.setText(list.get(position).getName());
holder.title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(context, "item " + (position + 1) + " clicked!", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return list.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
private TextView title;
public CustomViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.text);
}
}
}
MainActivity.java
The main activity layout:
package info.devexchanges.bubblebutton;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;
import com.webianks.library.PopupBubble;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List list = new ArrayList<>();
private RecyclerView recyclerView;
private PopupBubble popupBubble;
private RecyclerViewAdapter recyclerViewAdapter;
private LinearLayoutManager layoutManager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
setDummyData();
popupBubble = (PopupBubble) findViewById(R.id.popup_bubble);
//handling onclick bubble button
popupBubble.setPopupBubbleListener(new PopupBubble.PopupBubbleClickListener() {
@Override
public void bubbleClicked(Context context) {
Toast.makeText(MainActivity.this, "ListView updated!", Toast.LENGTH_SHORT).show();
}
});
//attaching bubble button with recyclerview
popupBubble.setRecyclerView(recyclerView);
//add new items from a background thread after 8 seconds
addNewContent();
}
private void setDummyData() {
DummyData dummyData;
for (int i = 0; i < 20; i++) {
dummyData = new DummyData();
dummyData.setName("RecyclerView item " + (i + 1));
list.add(dummyData);
}
recyclerViewAdapter = new RecyclerViewAdapter(this, list);
recyclerView.setAdapter(recyclerViewAdapter);
}
private void addNewContent() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
DummyData data;
for (int i = 10; i > 0; i--) {
data = new DummyData();
data.setName("New RecyclerView item " + i);
list.add(0, data);
}
recyclerViewAdapter.notifyItemRangeInserted(0, 10);
popupBubble.updateText("10 new items");
popupBubble.activate();
}
}, 10000); //update data after 10 seconds
}
}
activity_main.xml
Layout for each list view row:
<?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="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<com.webianks.library.PopupBubble
android:id="@+id/popup_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
app:backgroundColor="@color/colorPrimary"
app:iconColor="#ffffff"
app:textColor="#ffffff" />
</RelativeLayout>
item_recycler_view.xml
The POJO class of this project:
<?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"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text=" Name"
android:textSize="15sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_below="@id/text"
android:background="#dddddd" />
</RelativeLayout>
DummyData.java
Running this application, we'll have this output:package info.devexchanges.bubblebutton;
public class DummyData {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Final thoughts
RecyclerView
, so this is a weakness of this library, too! At the next post, I will provide another solution (customizing it myself) to make this design, coming soon!