diff --git a/briar-android/res/layout/activity_conversation.xml b/briar-android/res/layout/activity_conversation.xml
index 673dd14f9fe1585eb2862fdeea703a48fc5f628d..88066e9956e58f39b0f99d1b5730e5eb36b71490 100644
--- a/briar-android/res/layout/activity_conversation.xml
+++ b/briar-android/res/layout/activity_conversation.xml
@@ -1,45 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout
 	xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:tools="http://schemas.android.com/tools"
-	android:id="@+id/layout"
 	android:orientation="vertical"
 	android:layout_width="match_parent"
 	android:layout_height="match_parent">
 
-	<android.support.v7.widget.RecyclerView
+	<org.briarproject.android.util.BriarRecyclerView
 		android:id="@+id/conversationView"
 		android:layout_width="match_parent"
 		android:layout_height="0dp"
-		android:layout_weight="1"
-		android:scrollbars="vertical"/>
+		android:layout_weight="1"/>
 
-	<ProgressBar
-		android:id="@+id/listLoadingProgressBar"
-		android:layout_width="wrap_content"
-		android:layout_height="0dp"
-		android:layout_gravity="center"
-		android:gravity="center"
-		android:layout_weight="1"
-		android:indeterminate="true"
-		android:visibility="gone"/>
-
-	<TextView
-		android:id="@+id/emptyView"
-		android:layout_width="wrap_content"
-		android:layout_height="0dp"
-		android:layout_weight="1"
-		android:layout_gravity="center"
-		android:gravity="center"
-		android:padding="@dimen/margin_large"
-		android:textSize="@dimen/text_size_large"
-		android:text="@string/no_private_messages"
-		android:visibility="gone"/>
-
-	<View
-		android:layout_width="match_parent"
-		android:layout_height="1px"
-	    android:background="@color/horizontal_border"/>
+	<View style="@style/Divider.Horizontal"/>
 
 	<LinearLayout
 		android:orientation="horizontal"
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index f00647318a05c7b4252ef4c90ac6278f5a5db27b..585778ed554584b6f026c86c99f6106f4ab51942 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -3,26 +3,22 @@ package org.briarproject.android.contact;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.PorterDuff;
-import android.os.Build;
 import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
 import android.widget.EditText;
 import android.widget.ImageButton;
-import android.widget.ProgressBar;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.BriarActivity;
+import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.android.AndroidNotificationManager;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
@@ -68,8 +64,6 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
@@ -88,10 +82,8 @@ public class ConversationActivity extends BriarActivity
 	@Inject private ConnectionRegistry connectionRegistry;
 	@Inject @CryptoExecutor private Executor cryptoExecutor;
 	private Map<MessageId, byte[]> bodyCache = new HashMap<MessageId, byte[]>();
-	private TextView empty = null;
-	private ProgressBar loading = null;
 	private ConversationAdapter adapter = null;
-	private RecyclerView list = null;
+	private BriarRecyclerView list = null;
 	private EditText content = null;
 	private ImageButton sendButton = null;
 
@@ -121,37 +113,12 @@ public class ConversationActivity extends BriarActivity
 		setResult(RESULT_OK, data);
 
 		setContentView(R.layout.activity_conversation);
-		ViewGroup layout = (ViewGroup) findViewById(R.id.layout);
-		empty = (TextView) findViewById(R.id.emptyView);
-		empty.setVisibility(GONE);
-		// Show a progress bar while the list is loading
-		loading = (ProgressBar) findViewById(R.id.listLoadingProgressBar);
-		loading.setVisibility(VISIBLE);
 
 		adapter = new ConversationAdapter(this);
-		list = (RecyclerView) findViewById(R.id.conversationView);
+		list = (BriarRecyclerView) findViewById(R.id.conversationView);
 		list.setLayoutManager(new LinearLayoutManager(this));
 		list.setAdapter(adapter);
-		list.setVisibility(GONE);
-		// scroll down when opening keyboard
-		if (Build.VERSION.SDK_INT >= 11) {
-			list.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-				@Override
-				public void onLayoutChange(View v,
-						int left, int top, int right, int bottom,
-						int oldLeft, int oldTop, int oldRight, int oldBottom) {
-					if (bottom < oldBottom) {
-						list.postDelayed(new Runnable() {
-							@Override
-							public void run() {
-								list.scrollToPosition(
-										adapter.getItemCount() - 1);
-							}
-						}, 100);
-					}
-				}
-			});
-		}
+		list.setEmptyText(getString(R.string.no_private_messages));
 
 		content = (EditText) findViewById(R.id.contentView);
 		sendButton = (ImageButton) findViewById(R.id.sendButton);
@@ -167,6 +134,23 @@ public class ConversationActivity extends BriarActivity
 		loadHeaders();
 	}
 
+	@Override
+	public void onPause() {
+		super.onPause();
+		eventBus.removeListener(this);
+		if (isFinishing()) markMessagesRead();
+	}
+
+	@Override
+	protected void onActivityResult(int request, int result, Intent data) {
+		super.onActivityResult(request, result, data);
+		if (request == REQUEST_READ && result == RESULT_PREV_NEXT) {
+			int position = data.getIntExtra("briar.POSITION", -1);
+			if (position >= 0 && position < adapter.getItemCount())
+				displayMessage(position);
+		}
+	}
+
 	@Override
 	public boolean onCreateOptionsMenu(Menu menu) {
 		// Inflate the menu items for use in the action bar
@@ -264,11 +248,8 @@ public class ConversationActivity extends BriarActivity
 			final Collection<PrivateMessageHeader> headers) {
 		runOnUiThread(new Runnable() {
 			public void run() {
-				loading.setVisibility(GONE);
 				sendButton.setEnabled(true);
 				if (!headers.isEmpty()) {
-					list.setVisibility(VISIBLE);
-					empty.setVisibility(GONE);
 					for (PrivateMessageHeader h : headers) {
 						ConversationItem item = new ConversationItem(h);
 						byte[] body = bodyCache.get(h.getId());
@@ -279,8 +260,9 @@ public class ConversationActivity extends BriarActivity
 					// Scroll to the bottom
 					list.scrollToPosition(adapter.getItemCount() - 1);
 				} else {
-					empty.setVisibility(VISIBLE);
-					list.setVisibility(GONE);
+					// we have no messages,
+					// so let the list know to hide progress bar
+					list.showData();
 				}
 			}
 		});
@@ -329,23 +311,6 @@ public class ConversationActivity extends BriarActivity
 		});
 	}
 
-	@Override
-	protected void onActivityResult(int request, int result, Intent data) {
-		super.onActivityResult(request, result, data);
-		if (request == REQUEST_READ && result == RESULT_PREV_NEXT) {
-			int position = data.getIntExtra("briar.POSITION", -1);
-			if (position >= 0 && position < adapter.getItemCount())
-				displayMessage(position);
-		}
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-		if (isFinishing()) markMessagesRead();
-	}
-
 	private void markMessagesRead() {
 		notificationManager.clearPrivateMessageNotification(contactId);
 		List<MessageId> unread = new ArrayList<MessageId>();
diff --git a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
index 4e50c1d5d53a55ff8cca34f58cf66d02200ecab9..89c213502405727bf4d733038253fc2d309831c4 100644
--- a/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
+++ b/briar-android/src/org/briarproject/android/util/BriarRecyclerView.java
@@ -1,6 +1,7 @@
 package org.briarproject.android.util;
 
 import android.content.Context;
+import android.os.Build;
 import android.support.v7.widget.RecyclerView;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -51,6 +52,26 @@ public class BriarRecyclerView extends FrameLayout {
 
 		showProgressBar();
 
+		// scroll down when opening keyboard
+		if (Build.VERSION.SDK_INT >= 11) {
+			recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+				@Override
+				public void onLayoutChange(View v,
+						int left, int top, int right, int bottom,
+						int oldLeft, int oldTop, int oldRight, int oldBottom) {
+					if (bottom < oldBottom) {
+						recyclerView.postDelayed(new Runnable() {
+							@Override
+							public void run() {
+								scrollToPosition(
+										recyclerView.getAdapter().getItemCount() - 1);
+							}
+						}, 100);
+					}
+				}
+			});
+		}
+
 		emptyObserver = new RecyclerView.AdapterDataObserver() {
 			@Override
 			public void onChanged() {
@@ -112,6 +133,10 @@ public class BriarRecyclerView extends FrameLayout {
 		}
 	}
 
+	public void scrollToPosition(int position) {
+		recyclerView.scrollToPosition(position);
+	}
+
 	public RecyclerView getRecyclerView() {
 		return recyclerView;
 	}