diff --git a/briar-android/res/layout/activity_contact_list.xml b/briar-android/res/layout/activity_contact_list.xml
index 02faeff9b..333dac203 100644
--- a/briar-android/res/layout/activity_contact_list.xml
+++ b/briar-android/res/layout/activity_contact_list.xml
@@ -1,54 +1,28 @@
-
+ android:layout_height="match_parent">
-
+ android:layout_height="match_parent"/>
-
-
-
-
-
-
-
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/margin_activity_horizontal"
+ android:src="@drawable/ic_add_white"
+ app:fabSize="normal"
+ app:elevation="4dp"
+ app:layout_anchor="@id/contactList"
+ app:layout_anchorGravity="bottom|right|end"
+ app:layout_behavior="org.briarproject.android.util.HideFabOnScrollBehavior"/>
-
-
-
\ No newline at end of file
+
diff --git a/briar-android/res/layout/briar_recycler_view.xml b/briar-android/res/layout/briar_recycler_view.xml
new file mode 100644
index 000000000..d84769f3e
--- /dev/null
+++ b/briar-android/res/layout/briar_recycler_view.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 0a7c7b1f0..db7f2bfc4 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -128,4 +128,5 @@
Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ?
Confirm Contact Deletion
Are you sure that you want to remove this contact and all messages exchanged with this contact?
+ No data
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
index b3fec8962..791883254 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
@@ -4,15 +4,12 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.view.View;
-import android.view.View.OnCreateContextMenuListener;
-import android.widget.ProgressBar;
-import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.invitation.AddContactActivity;
+import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;
@@ -38,22 +35,18 @@ import java.util.logging.Logger;
import javax.inject.Inject;
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
public class ContactListActivity extends BriarActivity
- implements OnCreateContextMenuListener, EventListener {
+ implements EventListener {
private static final Logger LOG =
Logger.getLogger(ContactListActivity.class.getName());
@Inject private ConnectionRegistry connectionRegistry;
- private TextView empty = null;
private ContactListAdapter adapter = null;
- private RecyclerView list = null;
- private ProgressBar loading = null;
+ private BriarRecyclerView list = null;
// Fields that are accessed from background threads must be volatile
@Inject private volatile ContactManager contactManager;
@@ -67,18 +60,10 @@ public class ContactListActivity extends BriarActivity
setContentView(R.layout.activity_contact_list);
adapter = new ContactListAdapter(this);
- list = (RecyclerView) findViewById(R.id.contactList);
+ list = (BriarRecyclerView) findViewById(R.id.contactList);
list.setLayoutManager(new LinearLayoutManager(this));
list.setAdapter(adapter);
- list.setOnCreateContextMenuListener(this);
- list.setVisibility(GONE);
-
- // Show a notice when there are no contacts
- empty = (TextView) findViewById(R.id.emptyView);
-
- // Show a progress bar while the list is loading
- loading = (ProgressBar) findViewById(R.id.progressBar);
- loading.setVisibility(VISIBLE);
+ list.setEmptyText(getString(R.string.no_contacts));
// Show a floating action button
FloatingActionButton fab = (FloatingActionButton) findViewById(
@@ -104,18 +89,12 @@ public class ContactListActivity extends BriarActivity
public void onResume() {
super.onResume();
eventBus.addListener(this);
+
loadContacts();
}
private void loadContacts() {
- runOnUiThread(new Runnable() {
- public void run() {
- empty.setVisibility(GONE);
- list.setVisibility(GONE);
- loading.setVisibility(VISIBLE);
- }
- });
runOnDbThread(new Runnable() {
public void run() {
try {
@@ -155,15 +134,11 @@ public class ContactListActivity extends BriarActivity
runOnUiThread(new Runnable() {
public void run() {
if (contacts.size() > 0) {
- list.setVisibility(VISIBLE);
- empty.setVisibility(GONE);
+ adapter.addAll(contacts);
} else {
- list.setVisibility(GONE);
- empty.setVisibility(VISIBLE);
+ // no contacts to display, make sure progress bar is hidden
+ list.showData();
}
- loading.setVisibility(GONE);
-
- adapter.addAll(contacts);
}
});
}
@@ -228,11 +203,6 @@ public class ContactListActivity extends BriarActivity
ContactListItem item = adapter.findItem(c);
if (item != null) {
adapter.remove(item);
-
- if (adapter.isEmpty()) {
- empty.setVisibility(VISIBLE);
- list.setVisibility(GONE);
- }
}
}
});
diff --git a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
new file mode 100644
index 000000000..4e50c1d5d
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
@@ -0,0 +1,119 @@
+package org.briarproject.android.util;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import org.briarproject.R;
+
+public class BriarRecyclerView extends FrameLayout {
+
+ private RecyclerView recyclerView;
+ private TextView emptyView;
+ private ProgressBar progressBar;
+ private RecyclerView.AdapterDataObserver emptyObserver;
+
+ public BriarRecyclerView(Context context) {
+ super(context);
+
+ initViews();
+ }
+
+ public BriarRecyclerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ initViews();
+ }
+
+ public BriarRecyclerView(Context context, AttributeSet attrs,
+ int defStyle) {
+ super(context, attrs, defStyle);
+
+ initViews();
+ }
+
+ private void initViews() {
+ if (isInEditMode()) {
+ return;
+ }
+
+ View v = LayoutInflater.from(getContext()).inflate(
+ R.layout.briar_recycler_view, this, true);
+
+ recyclerView = (RecyclerView) v.findViewById(R.id.recyclerView);
+ emptyView = (TextView) v.findViewById(R.id.emptyView);
+ progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
+
+ showProgressBar();
+
+ emptyObserver = new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ showData();
+ }
+
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ super.onItemRangeInserted(positionStart, itemCount);
+ onChanged();
+ }
+ };
+ }
+
+ public void setLayoutManager(RecyclerView.LayoutManager layout) {
+ recyclerView.setLayoutManager(layout);
+ }
+
+ public void setAdapter(RecyclerView.Adapter adapter) {
+ RecyclerView.Adapter oldAdapter = recyclerView.getAdapter();
+ if (oldAdapter != null) {
+ oldAdapter.unregisterAdapterDataObserver(emptyObserver);
+ }
+
+ recyclerView.setAdapter(adapter);
+
+ if (adapter != null) {
+ adapter.registerAdapterDataObserver(emptyObserver);
+
+ if (adapter.getItemCount() > 0) {
+ // only show data if adapter has data already
+ // otherwise progress bar is shown
+ emptyObserver.onChanged();
+ }
+ }
+ }
+
+ public void setEmptyText(String text) {
+ emptyView.setText(text);
+ }
+
+ public void showProgressBar() {
+ recyclerView.setVisibility(View.INVISIBLE);
+ emptyView.setVisibility(View.INVISIBLE);
+ progressBar.setVisibility(View.VISIBLE);
+ }
+
+ public void showData() {
+ RecyclerView.Adapter> adapter = recyclerView.getAdapter();
+ if (adapter != null) {
+ if (adapter.getItemCount() == 0) {
+ emptyView.setVisibility(View.VISIBLE);
+ recyclerView.setVisibility(View.INVISIBLE);
+ } else {
+ emptyView.setVisibility(View.INVISIBLE);
+ recyclerView.setVisibility(View.VISIBLE);
+ }
+ progressBar.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ public RecyclerView getRecyclerView() {
+ return recyclerView;
+ }
+
+}