diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 25437944268018098ab7ba77ac68f0d62322b8c6..21f18eb159812b0ce656574ecd9170d0b8a82542 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -93,7 +93,7 @@
 			android:label="@string/app_name"
 			android:theme="@style/BriarThemeNoActionBar.Default"
 			android:parentActivityName=".android.NavDrawerActivity"
-			android:windowSoftInputMode="stateHidden">
+			android:windowSoftInputMode="stateHidden|adjustResize">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
 				android:value=".android.NavDrawerActivity"
@@ -145,7 +145,8 @@
 		<activity
 			android:name=".android.sharing.ShareForumActivity"
 			android:label="@string/activity_share_toolbar_header"
-			android:parentActivityName=".android.forum.ForumActivity">
+			android:parentActivityName=".android.forum.ForumActivity"
+			android:windowSoftInputMode="adjustResize|stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
 				android:value=".android.forum.ForumActivity"
@@ -155,7 +156,8 @@
 		<activity
 			android:name=".android.sharing.ShareBlogActivity"
 			android:label="@string/activity_share_toolbar_header"
-			android:parentActivityName=".android.blogs.BlogActivity">
+			android:parentActivityName=".android.blogs.BlogActivity"
+			android:windowSoftInputMode="adjustResize|stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
 				android:value=".android.blogs.BlogActivity"
diff --git a/briar-android/res/layout/activity_conversation.xml b/briar-android/res/layout/activity_conversation.xml
index cfd7cd4d27cd249b541dd1c0e7618adc9f300008..acf9bd653bbfce2202dd71026aad10e4098f5ed9 100644
--- a/briar-android/res/layout/activity_conversation.xml
+++ b/briar-android/res/layout/activity_conversation.xml
@@ -24,7 +24,7 @@
 
 			<include layout="@layout/contact_avatar_status"/>
 
-			<TextView
+			<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 				android:id="@+id/contactName"
 				style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
 				android:layout_width="wrap_content"
@@ -50,6 +50,7 @@
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
 		android:background="@color/button_bar_background"
-		android:elevation="@dimen/margin_tiny"/>
+		android:elevation="@dimen/margin_tiny"
+		app:hint="@string/message_hint"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/activity_forum.xml b/briar-android/res/layout/activity_forum.xml
index f8e1b609ce4c0084c6b8bd6586e375c24289a1c5..823ae7c3a9d2fbd73eaaa606efb5c608e4ed62f0 100644
--- a/briar-android/res/layout/activity_forum.xml
+++ b/briar-android/res/layout/activity_forum.xml
@@ -18,6 +18,7 @@
 		android:layout_width="match_parent"
 		android:layout_height="wrap_content"
 		android:background="@color/button_bar_background"
-		android:elevation="@dimen/margin_tiny"/>
+		android:elevation="@dimen/margin_tiny"
+		app:hint="@string/forum_new_message_hint"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/activity_write_blog_post.xml b/briar-android/res/layout/activity_write_blog_post.xml
index 5c3bcf3804982874598a6f63f4f28f47e9ae3607..b8e5fe64068efe4a4bc39d5a37b8603c10fb8030 100644
--- a/briar-android/res/layout/activity_write_blog_post.xml
+++ b/briar-android/res/layout/activity_write_blog_post.xml
@@ -1,56 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
+<FrameLayout
 	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:padding="@dimen/margin_small"
 	tools:context=".android.blogs.WriteBlogPostActivity">
 
-	<android.support.design.widget.TextInputLayout
-		android:id="@+id/titleLayout"
-		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-		android:visibility="gone"
-		app:counterEnabled="true"
-		app:counterOverflowTextAppearance="@style/BriarTextCounter.Overflow">
-
-		<android.support.design.widget.TextInputEditText
-			android:id="@+id/titleInput"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:hint="@string/blogs_write_blog_post_title_hint"
-			android:inputType="textCapWords|textCapSentences|textAutoCorrect"/>
-
-	</android.support.design.widget.TextInputLayout>
-
-	<EditText
+	<org.briarproject.android.view.LargeTextInputView
 		android:id="@+id/bodyInput"
 		android:layout_width="match_parent"
-		android:layout_height="0dp"
-		android:layout_weight="1"
+		android:layout_height="match_parent"
 		android:gravity="bottom"
-		android:hint="@string/blogs_write_blog_post_body_hint"
-		android:inputType="textMultiLine|textLongMessage|textCapSentences|textAutoCorrect">
-
-		<requestFocus/>
-
-	</EditText>
-
-	<Button
-		android:id="@+id/publishButton"
-		style="@style/BriarButton"
-		android:enabled="false"
-		android:text="@string/blogs_publish_blog_post"/>
+		app:buttonText="@string/blogs_publish_blog_post"
+		app:hint="@string/blogs_write_blog_post_body_hint"
+		app:fillHeight="true"/>
 
 	<ProgressBar
 		android:id="@+id/progressBar"
-		style="?android:attr/progressBarStyle"
+		style="?android:attr/progressBarStyleLarge"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
 		android:layout_gravity="center"
-		android:visibility="gone"/>
+		android:visibility="invisible"/>
 
-</LinearLayout>
+</FrameLayout>
diff --git a/briar-android/res/layout/author_view.xml b/briar-android/res/layout/author_view.xml
index 42a5655a5062b11ebff29ef6bfd4b28a74438e90..48892daf258b52dd9e311e73a24787f743d1d928 100644
--- a/briar-android/res/layout/author_view.xml
+++ b/briar-android/res/layout/author_view.xml
@@ -26,7 +26,7 @@
 		android:visibility="invisible"
 		tools:ignore="ContentDescription"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/authorName"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/fragment_reblog.xml b/briar-android/res/layout/fragment_reblog.xml
index b17143b35193564ad3b2c503e15f83f0d6bb0a9e..e6f8237cf6b3ad0c0dcd94a0d00a334d1789ba5e 100644
--- a/briar-android/res/layout/fragment_reblog.xml
+++ b/briar-android/res/layout/fragment_reblog.xml
@@ -1,46 +1,47 @@
 <?xml version="1.0" encoding="utf-8"?>
-<ScrollView
-	android:id="@+id/scrollView"
+<LinearLayout
 	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"
-	android:background="@color/window_background">
+	android:layout_height="match_parent"
+	android:orientation="vertical">
 
-	<RelativeLayout
+	<ScrollView
+		android:id="@+id/scrollView"
 		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-		android:padding="@dimen/margin_small">
+		android:layout_height="0dp"
+		android:layout_weight="1"
+		android:background="@color/window_background">
 
-		<include
-			android:id="@+id/postLayout"
-			layout="@layout/list_item_blog_post"
+		<RelativeLayout
 			android:layout_width="match_parent"
-			android:layout_height="wrap_content"/>
+			android:layout_height="wrap_content">
 
-		<ProgressBar
-			android:id="@+id/progressBar"
-			style="?android:attr/progressBarStyleLarge"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_centerInParent="true"/>
+			<include
+				android:id="@+id/postLayout"
+				layout="@layout/list_item_blog_post"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:layout_margin="@dimen/margin_small"/>
 
-		<EditText
-			android:id="@+id/inputText"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:layout_below="@+id/postLayout"
-			android:layout_margin="@dimen/listitem_vertical_margin"
-			android:gravity="bottom"
-			android:hint="@string/blogs_reblog_comment_hint"
-			android:inputType="textShortMessage|textMultiLine|textCapSentences|textAutoCorrect"/>
-
-		<Button
-			android:id="@+id/publishButton"
-			style="@style/BriarButton"
-			android:layout_below="@+id/inputText"
-			android:enabled="false"
-			android:text="@string/blogs_reblog_button"/>
-
-	</RelativeLayout>
-
-</ScrollView>
+			<ProgressBar
+				android:id="@+id/progressBar"
+				style="?android:attr/progressBarStyleLarge"
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:layout_centerInParent="true"/>
+
+		</RelativeLayout>
+
+	</ScrollView>
+
+	<org.briarproject.android.view.LargeTextInputView
+		android:id="@+id/inputText"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:gravity="bottom"
+		app:buttonText="@string/blogs_reblog_button"
+		app:maxLines="5"
+		app:hint="@string/blogs_reblog_comment_hint"/>
+
+</LinearLayout>
diff --git a/briar-android/res/layout/fragment_share_message.xml b/briar-android/res/layout/fragment_share_message.xml
index 33863fc13d0a3c9d1f5f08aea1c9a8ac058a50b3..45b33c0bac6aceb5c534f4847f2ac8afadcc6c30 100644
--- a/briar-android/res/layout/fragment_share_message.xml
+++ b/briar-android/res/layout/fragment_share_message.xml
@@ -1,41 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.v4.widget.NestedScrollView
+<LinearLayout
 	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:fillViewport="true">
+	android:orientation="vertical">
 
-	<LinearLayout
+	<TextView
+		android:id="@+id/introductionText"
 		android:layout_width="match_parent"
-		android:layout_height="match_parent"
+		android:layout_height="wrap_content"
 		android:padding="@dimen/margin_activity_horizontal"
-		android:orientation="vertical">
+		android:text="@string/forum_share_message"
+		android:textColor="@color/briar_text_primary"
+		android:textSize="@dimen/text_size_medium"/>
 
-		<TextView
-			android:id="@+id/introductionText"
-			android:layout_width="match_parent"
-			android:layout_height="0dp"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:layout_weight="1"
-			android:gravity="top"
-			android:textSize="@dimen/text_size_medium"
-			android:textColor="@color/briar_text_primary"
-			android:text="@string/forum_share_message"/>
-
-		<EditText
-			android:id="@+id/invitationMessageView"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:gravity="bottom"
-			android:hint="@string/introduction_message_hint"
-			android:inputType="text|textMultiLine|textCapSentences"/>
-
-		<Button
-			android:id="@+id/shareForumButton"
-			style="@style/BriarButton"
-			android:text="@string/forum_share_button"/>
-
-	</LinearLayout>
+	<org.briarproject.android.view.LargeTextInputView
+		android:id="@+id/invitationMessageView"
+		android:layout_width="match_parent"
+		android:layout_height="0dp"
+		android:layout_weight="1"
+		android:gravity="bottom"
+		app:buttonText="@string/forum_share_button"
+		app:fillHeight="true"
+		app:hint="@string/introduction_message_hint"/>
 
-</android.support.v4.widget.NestedScrollView>
\ No newline at end of file
+</LinearLayout>
diff --git a/briar-android/res/layout/introduction_message.xml b/briar-android/res/layout/introduction_message.xml
index 3982cbcd37a74815c147593dfa5804fb0bc61d0f..3240557289461b5623987a530e6a9aebf787887e 100644
--- a/briar-android/res/layout/introduction_message.xml
+++ b/briar-android/res/layout/introduction_message.xml
@@ -1,128 +1,126 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.v4.widget.NestedScrollView
+<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:fillViewport="true">
+	android:orientation="vertical">
 
-	<LinearLayout
+	<ScrollView
 		android:layout_width="match_parent"
-		android:layout_height="match_parent"
-		android:orientation="vertical"
-		android:padding="@dimen/margin_activity_horizontal">
+		android:layout_height="0dp"
+		android:layout_weight="1">
 
-		<RelativeLayout
+		<LinearLayout
 			android:layout_width="match_parent"
-			android:layout_height="wrap_content">
+			android:layout_height="wrap_content"
+			android:layout_margin="@dimen/margin_activity_horizontal"
+			android:orientation="vertical">
 
-			<LinearLayout
-				android:layout_width="wrap_content"
-				android:layout_height="wrap_content"
-				android:layout_toLeftOf="@+id/introductionIcon"
-				android:gravity="top|center_horizontal"
-				android:orientation="vertical">
+			<RelativeLayout
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content">
 
-				<de.hdodenhof.circleimageview.CircleImageView
-					android:id="@+id/avatarContact1"
-					style="@style/BriarAvatar"
-					android:layout_width="@dimen/listitem_picture_size"
-					android:layout_height="@dimen/listitem_picture_size"
-					android:layout_marginEnd="@dimen/listitem_horizontal_margin"
-					android:layout_marginLeft="@dimen/listitem_horizontal_margin"
-					android:layout_marginRight="@dimen/listitem_horizontal_margin"
-					android:layout_marginStart="@dimen/listitem_horizontal_margin"
-					tools:src="@drawable/ic_launcher"/>
-
-				<TextView
-					android:id="@+id/nameContact1"
+				<LinearLayout
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:layout_marginTop="@dimen/margin_small"
-					android:gravity="center"
-					android:textColor="@color/briar_text_primary"
-					android:textSize="@dimen/text_size_tiny"
-					tools:text="Contact 1"/>
-
-			</LinearLayout>
-
-			<ImageView
-				android:id="@+id/introductionIcon"
-				android:layout_width="@dimen/listitem_picture_size"
-				android:layout_height="@dimen/listitem_picture_size"
-				android:layout_centerHorizontal="true"
-				android:src="@drawable/ic_contact_introduction"
-				tools:ignore="ContentDescription"/>
-
-			<LinearLayout
-				android:layout_width="wrap_content"
-				android:layout_height="wrap_content"
-				android:layout_toEndOf="@+id/introductionIcon"
-				android:layout_toRightOf="@+id/introductionIcon"
-				android:gravity="top|center_horizontal"
-				android:orientation="vertical">
-
-				<de.hdodenhof.circleimageview.CircleImageView
-					android:id="@+id/avatarContact2"
-					style="@style/BriarAvatar"
+					android:layout_toLeftOf="@+id/introductionIcon"
+					android:gravity="top|center_horizontal"
+					android:orientation="vertical">
+
+					<de.hdodenhof.circleimageview.CircleImageView
+						android:id="@+id/avatarContact1"
+						style="@style/BriarAvatar"
+						android:layout_width="@dimen/listitem_picture_size"
+						android:layout_height="@dimen/listitem_picture_size"
+						android:layout_marginEnd="@dimen/listitem_horizontal_margin"
+						android:layout_marginLeft="@dimen/listitem_horizontal_margin"
+						android:layout_marginRight="@dimen/listitem_horizontal_margin"
+						android:layout_marginStart="@dimen/listitem_horizontal_margin"
+						tools:src="@drawable/ic_launcher"/>
+
+					<org.thoughtcrime.securesms.components.emoji.EmojiTextView
+						android:id="@+id/nameContact1"
+						android:layout_width="wrap_content"
+						android:layout_height="wrap_content"
+						android:layout_marginTop="@dimen/margin_small"
+						android:gravity="center"
+						android:textColor="@color/briar_text_primary"
+						android:textSize="@dimen/text_size_tiny"
+						tools:text="Contact 1"/>
+
+				</LinearLayout>
+
+				<ImageView
+					android:id="@+id/introductionIcon"
 					android:layout_width="@dimen/listitem_picture_size"
 					android:layout_height="@dimen/listitem_picture_size"
-					android:layout_marginEnd="@dimen/listitem_horizontal_margin"
-					android:layout_marginLeft="@dimen/listitem_horizontal_margin"
-					android:layout_marginRight="@dimen/listitem_horizontal_margin"
-					android:layout_marginStart="@dimen/listitem_horizontal_margin"
-					android:transitionName="avatar"
-					tools:src="@drawable/ic_launcher"/>
-
-				<TextView
-					android:id="@+id/nameContact2"
+					android:layout_centerHorizontal="true"
+					android:src="@drawable/ic_contact_introduction"
+					tools:ignore="ContentDescription"/>
+
+				<LinearLayout
 					android:layout_width="wrap_content"
 					android:layout_height="wrap_content"
-					android:layout_marginTop="@dimen/margin_small"
-					android:gravity="center"
-					android:textColor="@color/briar_text_primary"
-					android:textSize="@dimen/text_size_tiny"
-					tools:text="Contact 2"/>
-
-			</LinearLayout>
+					android:layout_toEndOf="@+id/introductionIcon"
+					android:layout_toRightOf="@+id/introductionIcon"
+					android:gravity="top|center_horizontal"
+					android:orientation="vertical">
+
+					<de.hdodenhof.circleimageview.CircleImageView
+						android:id="@+id/avatarContact2"
+						style="@style/BriarAvatar"
+						android:layout_width="@dimen/listitem_picture_size"
+						android:layout_height="@dimen/listitem_picture_size"
+						android:layout_marginEnd="@dimen/listitem_horizontal_margin"
+						android:layout_marginLeft="@dimen/listitem_horizontal_margin"
+						android:layout_marginRight="@dimen/listitem_horizontal_margin"
+						android:layout_marginStart="@dimen/listitem_horizontal_margin"
+						android:transitionName="avatar"
+						tools:src="@drawable/ic_launcher"/>
+
+					<org.thoughtcrime.securesms.components.emoji.EmojiTextView
+						android:id="@+id/nameContact2"
+						android:layout_width="wrap_content"
+						android:layout_height="wrap_content"
+						android:layout_marginTop="@dimen/margin_small"
+						android:gravity="center"
+						android:textColor="@color/briar_text_primary"
+						android:textSize="@dimen/text_size_tiny"
+						tools:text="Contact 2"/>
+
+				</LinearLayout>
+
+			</RelativeLayout>
+
+			<ProgressBar
+				android:id="@+id/progressBar"
+				style="?android:attr/progressBarStyleLarge"
+				android:layout_width="wrap_content"
+				android:layout_height="wrap_content"
+				android:layout_gravity="center"
+				tools:visibility="gone"/>
 
-		</RelativeLayout>
+			<org.thoughtcrime.securesms.components.emoji.EmojiTextView
+				android:id="@+id/introductionText"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:layout_marginTop="@dimen/margin_activity_horizontal"
+				android:textColor="@color/briar_text_secondary"
+				android:textSize="@dimen/text_size_medium"
+				tools:text="@string/introduction_message_text"/>
 
-		<ProgressBar
-			android:id="@+id/progressBar"
-			style="?android:attr/progressBarStyleLarge"
-			android:layout_width="wrap_content"
-			android:layout_height="wrap_content"
-			android:layout_gravity="center"
-			tools:visibility="gone"/>
+		</LinearLayout>
 
-		<TextView
-			android:id="@+id/introductionText"
-			android:layout_width="match_parent"
-			android:layout_height="0dp"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:layout_weight="1"
-			android:gravity="top"
-			android:textColor="@color/briar_text_secondary"
-			android:textSize="@dimen/text_size_medium"
-			tools:text="@string/introduction_message_text"/>
-
-		<EditText
-			android:id="@+id/introductionMessageView"
-			android:layout_width="match_parent"
-			android:layout_height="wrap_content"
-			android:layout_marginTop="@dimen/margin_medium"
-			android:gravity="bottom"
-			android:hint="@string/introduction_message_hint"
-			android:inputType="text|textMultiLine|textCapSentences"
-			android:textColor="@color/briar_text_primary"
-			android:textColorHint="@color/briar_text_tertiary"/>
+	</ScrollView>
 
-		<Button
-			android:id="@+id/makeIntroductionButton"
-			style="@style/BriarButton"
-			android:text="@string/introduction_button"/>
-
-	</LinearLayout>
+	<org.briarproject.android.view.LargeTextInputView
+		android:id="@+id/introductionMessageView"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		app:buttonText="@string/introduction_button"
+		app:hint="@string/introduction_message_hint"
+		app:maxLines="5"/>
 
-</android.support.v4.widget.NestedScrollView>
\ No newline at end of file
+</LinearLayout>
diff --git a/briar-android/res/layout/list_item_blog.xml b/briar-android/res/layout/list_item_blog.xml
index 24127ced5f70ac916727cc76d014aaff267fbb4f..a04a430373568d1e24ca173a6e122d52e28c534f 100644
--- a/briar-android/res/layout/list_item_blog.xml
+++ b/briar-android/res/layout/list_item_blog.xml
@@ -18,7 +18,7 @@
 		android:layout_marginRight="@dimen/listitem_horizontal_margin"
 		android:layout_marginTop="@dimen/margin_medium"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/nameView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_blog_comment.xml b/briar-android/res/layout/list_item_blog_comment.xml
index c6ff62916ed93058a1951af0010a87fe242242ce..4c521522a73ab23f9dfd5aa81078b0f4c2d77f66 100644
--- a/briar-android/res/layout/list_item_blog_comment.xml
+++ b/briar-android/res/layout/list_item_blog_comment.xml
@@ -20,7 +20,7 @@
 		android:padding="@dimen/listitem_vertical_margin"
 		app:persona="commenter"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/bodyView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_blog_post.xml b/briar-android/res/layout/list_item_blog_post.xml
index 0b6803eedb1a9cb792e133d6f76220d016ac8173..96c2033a3fb93ebc746f6ba820c71b585ee92201 100644
--- a/briar-android/res/layout/list_item_blog_post.xml
+++ b/briar-android/res/layout/list_item_blog_post.xml
@@ -50,7 +50,7 @@
 				android:padding="@dimen/margin_small"
 				android:src="@drawable/ic_repeat"/>
 
-			<TextView
+			<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 				android:id="@+id/bodyView"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_contact.xml b/briar-android/res/layout/list_item_contact.xml
index 9b00f7643035a3e1607af5a20b78dc5dd35213b9..624434e9a43a77ba7adc556422bc5a2165c5a983 100644
--- a/briar-android/res/layout/list_item_contact.xml
+++ b/briar-android/res/layout/list_item_contact.xml
@@ -59,7 +59,7 @@
 			android:layout_toRightOf="@+id/avatarFrameView"
 			android:orientation="vertical">
 
-			<TextView
+			<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 				android:id="@+id/nameView"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_contact_small.xml b/briar-android/res/layout/list_item_contact_small.xml
index c6cdd0e97f5ece8e4ecc940f01dfd11533cf82ba..66b4c44e38f493469ec224ff39c3363b85af2fb8 100644
--- a/briar-android/res/layout/list_item_contact_small.xml
+++ b/briar-android/res/layout/list_item_contact_small.xml
@@ -17,7 +17,7 @@
 		android:layout_marginStart="@dimen/listitem_horizontal_margin"
 		tools:src="@drawable/ic_launcher"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/nameView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_forum.xml b/briar-android/res/layout/list_item_forum.xml
index 3dc74083fe11a6aed64df05066e110193ce5ff27..c143b6a22ba0773ccb4fd3d4aa487d696d34a8e6 100644
--- a/briar-android/res/layout/list_item_forum.xml
+++ b/briar-android/res/layout/list_item_forum.xml
@@ -17,7 +17,7 @@
 		android:layout_centerVertical="true"
 		android:layout_marginRight="@dimen/listitem_horizontal_margin"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/forumNameView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_forum_post.xml b/briar-android/res/layout/list_item_forum_post.xml
index 23774f31a9bf8de5e3107add50c8876956b8f0cf..2fe00672178eab9dafc8e92dfd062626fec77260 100644
--- a/briar-android/res/layout/list_item_forum_post.xml
+++ b/briar-android/res/layout/list_item_forum_post.xml
@@ -63,7 +63,6 @@
 			android:visibility="gone"
 			/>
 
-
 	</RelativeLayout>
 
 	<RelativeLayout
diff --git a/briar-android/res/layout/list_item_introduction_in.xml b/briar-android/res/layout/list_item_introduction_in.xml
index de94d9d788c1a6e020a84cbad177c3ddde4ee573..9094a1fc3c53203cd07fbf153735c4cbb33c608d 100644
--- a/briar-android/res/layout/list_item_introduction_in.xml
+++ b/briar-android/res/layout/list_item_introduction_in.xml
@@ -26,7 +26,7 @@
 		android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
 		android:background="@drawable/notice_in_bottom">
 
-		<TextView
+		<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 			android:id="@+id/introductionText"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_invitations.xml b/briar-android/res/layout/list_item_invitations.xml
index 6cfa235b6bf06e6ecd475d5396cb955d102f3a1f..6419c14b351aa17fea3b0a7063e26085eeb790cb 100644
--- a/briar-android/res/layout/list_item_invitations.xml
+++ b/briar-android/res/layout/list_item_invitations.xml
@@ -18,7 +18,7 @@
 		android:layout_marginRight="@dimen/listitem_horizontal_margin"
 		/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/forumNameView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
@@ -31,7 +31,7 @@
 		android:textSize="@dimen/text_size_medium"
 		tools:text="This is a name of a forum that is available"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/sharedByView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_msg_notice_out.xml b/briar-android/res/layout/list_item_msg_notice_out.xml
index 6efb99c523316d9da267f1e44d9f2a9231a537a0..0d328fe5c02963444f80853a6bbe3d160e5632a8 100644
--- a/briar-android/res/layout/list_item_msg_notice_out.xml
+++ b/briar-android/res/layout/list_item_msg_notice_out.xml
@@ -26,7 +26,7 @@
 		android:layout_marginRight="@dimen/message_bubble_margin_tail"
 		android:background="@drawable/notice_out_bottom">
 
-		<TextView
+		<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 			android:id="@+id/introductionText"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_notice_in.xml b/briar-android/res/layout/list_item_notice_in.xml
index c7caebd52b08525e8c10e4ebecafbad981d314bb..13994b47422388050c8f289ea309b5982cee43b8 100644
--- a/briar-android/res/layout/list_item_notice_in.xml
+++ b/briar-android/res/layout/list_item_notice_in.xml
@@ -9,7 +9,7 @@
 	android:layout_marginLeft="@dimen/message_bubble_margin_tail"
 	android:layout_marginRight="@dimen/message_bubble_margin_non_tail">
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/noticeText"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_notice_out.xml b/briar-android/res/layout/list_item_notice_out.xml
index 4575f48fee206705574d861cdfe1e29dc1ac1bfc..ae327bb9959cdeea6e2e338ce17d1e5be5a092e5 100644
--- a/briar-android/res/layout/list_item_notice_out.xml
+++ b/briar-android/res/layout/list_item_notice_out.xml
@@ -14,7 +14,7 @@
 		android:layout_marginLeft="@dimen/message_bubble_margin_non_tail"
 		android:layout_marginRight="@dimen/message_bubble_margin_tail">
 
-		<TextView
+		<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 			android:id="@+id/noticeText"
 			android:layout_width="wrap_content"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_rss_feed.xml b/briar-android/res/layout/list_item_rss_feed.xml
index 809ce84477cfdb326e890bbee65a936ff695a73f..51061a331483abbc8fb676de8ca97dcf98090aae 100644
--- a/briar-android/res/layout/list_item_rss_feed.xml
+++ b/briar-android/res/layout/list_item_rss_feed.xml
@@ -9,7 +9,7 @@
 	android:layout_marginTop="@dimen/listitem_horizontal_margin"
 	android:background="?attr/selectableItemBackground">
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/titleView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
@@ -41,7 +41,7 @@
 		android:textColor="@color/briar_text_secondary"
 		android:textSize="@dimen/text_size_small"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/authorView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
@@ -100,7 +100,7 @@
 		android:textSize="@dimen/text_size_small"
 		tools:text="5 min. ago"/>
 
-	<TextView
+	<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 		android:id="@+id/descriptionView"
 		android:layout_width="wrap_content"
 		android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_selectable_contact.xml b/briar-android/res/layout/list_item_selectable_contact.xml
index a1054b8913cd864d08669084fb0430cb5201b201..e04315adedbf762654830ebeac8c58b0c3d5b1c0 100644
--- a/briar-android/res/layout/list_item_selectable_contact.xml
+++ b/briar-android/res/layout/list_item_selectable_contact.xml
@@ -34,7 +34,7 @@
 			android:layout_toRightOf="@+id/avatarView"
 			android:orientation="vertical">
 
-			<TextView
+			<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 				android:id="@+id/nameView"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/list_item_shareable_invitation_in.xml b/briar-android/res/layout/list_item_shareable_invitation_in.xml
index f70ac34a0e89570d675c862a7f72c03c2fa83b21..b7cc1bb36655ec47bffc0306847ca1f341ec3c5b 100644
--- a/briar-android/res/layout/list_item_shareable_invitation_in.xml
+++ b/briar-android/res/layout/list_item_shareable_invitation_in.xml
@@ -27,7 +27,7 @@
 		android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
 		android:background="@drawable/notice_in_bottom">
 
-		<TextView
+		<org.thoughtcrime.securesms.components.emoji.EmojiTextView
 			android:id="@+id/introductionText"
 			android:layout_width="match_parent"
 			android:layout_height="wrap_content"
diff --git a/briar-android/res/layout/text_input_view.xml b/briar-android/res/layout/text_input_view.xml
index 6b1aeba51528e188c326dbc208ba59b8868e9aef..04bc0ccc76bd9d0ddeaf6f2db355011e03774ca4 100644
--- a/briar-android/res/layout/text_input_view.xml
+++ b/briar-android/res/layout/text_input_view.xml
@@ -10,41 +10,43 @@
 		style="@style/Divider.Horizontal"
 		android:layout_alignParentTop="true"/>
 
-	<org.thoughtcrime.securesms.components.emoji.EmojiToggle
-		android:id="@+id/emoji_toggle"
-		android:layout_width="42dp"
-		android:layout_height="42dp"
-		android:layout_above="@+id/emoji_drawer"
-		android:layout_alignBottom="@+id/input_text"
-		android:layout_alignParentLeft="true"
-		android:background="?attr/selectableItemBackground"
-		android:padding="@dimen/margin_small"
-		android:scaleType="center"/>
-
-	<org.thoughtcrime.securesms.components.emoji.EmojiEditText
-		android:id="@+id/input_text"
-		android:layout_width="wrap_content"
-		android:layout_height="wrap_content"
-		android:layout_toLeftOf="@+id/btn_send"
-		android:layout_toRightOf="@+id/emoji_toggle"
-		android:inputType="textMultiLine|textCapSentences"
-		android:maxLines="5"
-		android:minHeight="42dp"/>
-
-	<ImageButton
-		android:id="@+id/btn_send"
-		android:layout_width="wrap_content"
-		android:layout_height="42dp"
-		android:layout_above="@+id/emoji_drawer"
-		android:layout_alignBottom="@+id/input_text"
-		android:layout_alignParentRight="true"
-		android:background="?attr/selectableItemBackground"
-		android:clickable="true"
-		android:contentDescription="@string/send"
-		android:enabled="false"
-		android:padding="@dimen/margin_small"
-		android:src="@drawable/social_send_now_white"
-		android:tint="@color/briar_primary"/>
+	<LinearLayout
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content">
+
+		<org.thoughtcrime.securesms.components.emoji.EmojiToggle
+			android:id="@+id/emoji_toggle"
+			android:layout_width="@dimen/text_input_height"
+			android:layout_height="@dimen/text_input_height"
+			android:background="?attr/selectableItemBackground"
+			android:padding="@dimen/margin_small"
+			android:scaleType="center"/>
+
+		<org.thoughtcrime.securesms.components.emoji.EmojiEditText
+			android:id="@+id/input_text"
+			android:layout_width="0dp"
+			android:layout_height="match_parent"
+			android:layout_weight="1"
+			android:background="@android:color/transparent"
+			android:inputType="textMultiLine|textCapSentences"
+			android:maxLines="5"
+			android:minHeight="@dimen/text_input_height"
+			android:textColor="@color/briar_text_primary"
+			android:textColorHint="@color/briar_text_tertiary"/>
+
+		<ImageButton
+			android:id="@+id/btn_send"
+			android:layout_width="@dimen/text_input_height"
+			android:layout_height="@dimen/text_input_height"
+			android:background="?attr/selectableItemBackground"
+			android:clickable="true"
+			android:contentDescription="@string/send"
+			android:enabled="false"
+			android:padding="@dimen/margin_small"
+			android:src="@drawable/social_send_now_white"
+			android:tint="@color/briar_primary"/>
+
+	</LinearLayout>
 
 	<org.thoughtcrime.securesms.components.emoji.EmojiDrawer
 		android:id="@+id/emoji_drawer"
diff --git a/briar-android/res/layout/text_input_view_large.xml b/briar-android/res/layout/text_input_view_large.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b01d2a82a90ee4d41c20f1df2de28b1f1dd6a858
--- /dev/null
+++ b/briar-android/res/layout/text_input_view_large.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:tools="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	tools:showIn="@layout/fragment_reblog">
+
+	<LinearLayout
+		android:id="@+id/input_layout"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginEnd="@dimen/margin_medium"
+		android:layout_marginLeft="@dimen/margin_medium"
+		android:layout_marginRight="@dimen/margin_medium"
+		android:layout_marginStart="@dimen/margin_medium"
+		android:layout_marginTop="@dimen/margin_medium"
+		android:background="@android:color/white"
+		android:elevation="@dimen/cardview_default_elevation"
+		android:minHeight="@dimen/text_input_height"
+		android:orientation="horizontal">
+
+		<org.thoughtcrime.securesms.components.emoji.EmojiToggle
+			android:id="@+id/emoji_toggle"
+			android:layout_width="@dimen/text_input_height"
+			android:layout_height="@dimen/text_input_height"
+			android:layout_gravity="bottom"
+			android:background="?attr/selectableItemBackground"
+			android:padding="@dimen/margin_small"
+			android:scaleType="center"/>
+
+		<org.thoughtcrime.securesms.components.emoji.EmojiEditText
+			android:id="@+id/input_text"
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:background="@android:color/transparent"
+			android:gravity="bottom"
+			android:inputType="textMultiLine|textLongMessage|textCapSentences|textAutoCorrect"
+			android:minHeight="@dimen/text_input_height"
+			android:paddingBottom="10dp"
+			android:paddingEnd="@dimen/margin_small"
+			android:paddingRight="@dimen/margin_small"
+			android:paddingTop="@dimen/margin_small"
+			android:textColor="@color/briar_text_primary"
+			android:textColorHint="@color/briar_text_tertiary"
+			tools:ignore="RtlSymmetry"/>
+
+	</LinearLayout>
+
+	<Button
+		android:id="@+id/btn_send"
+		style="@style/BriarButton"
+		android:layout_marginEnd="@dimen/margin_small"
+		android:layout_marginLeft="@dimen/margin_small"
+		android:layout_marginRight="@dimen/margin_small"
+		android:layout_marginStart="@dimen/margin_small"/>
+
+	<org.thoughtcrime.securesms.components.emoji.EmojiDrawer
+		android:id="@+id/emoji_drawer"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:visibility="gone"/>
+
+</merge>
diff --git a/briar-android/res/menu/blogs_blog_actions.xml b/briar-android/res/menu/blogs_blog_actions.xml
index 64b42ac867a44016de994bb5508ab065f4b33de2..c422489b3854c5cf6a62388bfd1a55227f3cb4f1 100644
--- a/briar-android/res/menu/blogs_blog_actions.xml
+++ b/briar-android/res/menu/blogs_blog_actions.xml
@@ -27,8 +27,7 @@
 		android:id="@+id/action_blog_delete"
 		android:icon="@drawable/action_delete_white"
 		android:title="@string/blogs_remove_blog"
-		android:visible="false"
-		app:showAsAction="never"
-		tools:visible="true"/>
+		android:enabled="false"
+		app:showAsAction="never"/>
 
 </menu>
\ No newline at end of file
diff --git a/briar-android/res/menu/conversation_actions.xml b/briar-android/res/menu/conversation_actions.xml
index c2beb5c2a2b4611767ff9756e79d43bb9f0ab003..afaf674bda8b71e4cff122bf95dbb4a2b3604cc1 100644
--- a/briar-android/res/menu/conversation_actions.xml
+++ b/briar-android/res/menu/conversation_actions.xml
@@ -1,16 +1,14 @@
 <?xml version="1.0" encoding="utf-8"?>
 <menu
 	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">
+	xmlns:app="http://schemas.android.com/apk/res-auto">
 
 	<item
 		android:id="@+id/action_introduction"
 		android:icon="@drawable/introduction_white"
 		android:title="@string/introduction_button"
-		android:visible="false"
-		app:showAsAction="never"
-		tools:visible="true"/>
+		android:enabled="false"
+		app:showAsAction="never"/>
 
 	<item
 		android:id="@+id/action_social_remove_person"
diff --git a/briar-android/res/values/attrs.xml b/briar-android/res/values/attrs.xml
index a09b80b32c17ba83878d2ae6e79a7ad6e33cb695..83533880478a3ed4af9245804a72596f3c6f1911 100644
--- a/briar-android/res/values/attrs.xml
+++ b/briar-android/res/values/attrs.xml
@@ -14,4 +14,14 @@
 		</attr>
 	</declare-styleable>
 
+	<declare-styleable name="TextInputView">
+		<attr name="hint" format="string"/>
+	</declare-styleable>
+
+	<declare-styleable name="LargeTextInputView">
+		<attr name="buttonText" format="string"/>
+		<attr name="maxLines" format="integer"/>
+		<attr name="fillHeight" format="boolean"/>
+	</declare-styleable>
+
 </resources>
\ No newline at end of file
diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml
index f09530cc4b1300b0e72b533f7e3177196ed7a571..5239b500dbe9429b3e143fe6625f01c0ba99395f 100644
--- a/briar-android/res/values/dimens.xml
+++ b/briar-android/res/values/dimens.xml
@@ -47,6 +47,7 @@
 	<dimen name="blogs_avatar_comment_size">20dp</dimen>
 
 	<!-- Emoji -->
+	<dimen name="text_input_height">42dp</dimen>
 	<dimen name="conversation_item_body_text_size">16sp</dimen>
 	<dimen name="emoji_drawer_size">32sp</dimen>
 	<dimen name="emoji_drawer_indicator_height">2dp</dimen>
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index c0a570c89c0c79312c502fdf36c4e7df5bd1ab30..48e3e1f778980382099fad974b3c204369a698e9 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -79,6 +79,7 @@
 	<string name="no_contacts">It seems that you are new here and have no contacts yet.\n\nTap the + icon at the top and follow the instructions to add some friends to your list.\n\nPlease remember: You can only add new contacts face-to-face to prevent anyone from impersonating you or reading your messages in the future.</string>
 	<string name="date_no_private_messages">No messages.</string>
 	<string name="no_private_messages">This is the conversation view.\n\nThere seems to be a lack of conversation.\n\nJust tap the input field at the bottom to start a conversation.</string>
+	<string name="message_hint">Type message</string>
 	<string name="delete_contact">Delete contact</string>
 	<string name="dialog_title_delete_contact">Confirm Contact Deletion</string>
 	<string name="dialog_message_delete_contact">Are you sure that you want to remove this contact and all messages exchanged with this contact?</string>
diff --git a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
index c2bb93fbb6dbfb49c02e3c4fd19b434b8ac5c9f4..4d5c1f5ce433f6b6c69c3ce66f6c1a636f2422a6 100644
--- a/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/BlogFragment.java
@@ -144,7 +144,7 @@ public class BlogFragment extends BaseFragment implements
 		writeButton = menu.findItem(R.id.action_write_blog_post);
 		if (isMyBlog) writeButton.setVisible(true);
 		deleteButton = menu.findItem(R.id.action_blog_delete);
-		if (canDeleteBlog) deleteButton.setVisible(true);
+		if (canDeleteBlog) deleteButton.setEnabled(true);
 
 		super.onCreateOptionsMenu(menu, inflater);
 	}
@@ -196,7 +196,7 @@ public class BlogFragment extends BaseFragment implements
 			displaySnackbar(R.string.blogs_blog_post_created, true);
 			loadBlogPosts(true);
 		} else if (request == REQUEST_SHARE && result == RESULT_OK) {
-			displaySnackbar(R.string.blogs_sharing_snackbar, true);
+			displaySnackbar(R.string.blogs_sharing_snackbar, false);
 		}
 	}
 
@@ -261,7 +261,7 @@ public class BlogFragment extends BaseFragment implements
 						if (blog.isOurs())
 							showWriteButton();
 						if (blog.canBeRemoved())
-							showDeleteButton();
+							enableDeleteButton();
 					}
 
 					@Override
@@ -287,10 +287,10 @@ public class BlogFragment extends BaseFragment implements
 			writeButton.setVisible(true);
 	}
 
-	private void showDeleteButton() {
+	private void enableDeleteButton() {
 		canDeleteBlog = true;
 		if (deleteButton != null)
-			deleteButton.setVisible(true);
+			deleteButton.setEnabled(true);
 	}
 
 	private void displaySnackbar(int stringId, boolean scroll) {
diff --git a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
index 305273ba8d78e77c34a2b93398a2436fcf07a0d1..d5d799692e2f2ae9aafec0292a0c47aef90bcdf6 100644
--- a/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
+++ b/briar-android/src/org/briarproject/android/blogs/ReblogFragment.java
@@ -5,10 +5,7 @@ import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
 import android.widget.ProgressBar;
 import android.widget.ScrollView;
 
@@ -16,6 +13,8 @@ import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.view.TextInputView;
+import org.briarproject.android.view.TextInputView.TextInputListener;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
@@ -29,7 +28,7 @@ import static android.view.View.VISIBLE;
 import static org.briarproject.android.BriarActivity.GROUP_ID;
 import static org.briarproject.android.blogs.BasePostPagerFragment.POST_ID;
 
-public class ReblogFragment extends BaseFragment {
+public class ReblogFragment extends BaseFragment implements TextInputListener {
 
 	public static final String TAG = ReblogFragment.class.getName();
 
@@ -88,6 +87,7 @@ public class ReblogFragment extends BaseFragment {
 				false);
 		ui = new ViewHolder(v);
 		ui.post.setTransitionName(postId);
+		ui.input.setSendButtonEnabled(false);
 		showProgressBar();
 
 		return v;
@@ -129,14 +129,8 @@ public class ReblogFragment extends BaseFragment {
 		ui.post.bindItem(item);
 		ui.post.hideReblogButton();
 
-		ui.publish.setOnClickListener(new OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				send();
-				finish();
-			}
-		});
-		ui.publish.setEnabled(true);
+		ui.input.setListener(this);
+		ui.input.setSendButtonEnabled(true);
 		ui.scrollView.post(new Runnable() {
 			@Override
 			public void run() {
@@ -145,7 +139,8 @@ public class ReblogFragment extends BaseFragment {
 		});
 	}
 
-	private void send() {
+	@Override
+	public void onSendClick(String text) {
 		String comment = getComment();
 		feedController.repeatPost(item, comment,
 				new UiResultExceptionHandler<Void, DbException>(listener) {
@@ -159,6 +154,7 @@ public class ReblogFragment extends BaseFragment {
 						// do nothing, this fragment is gone already
 					}
 				});
+		finish();
 	}
 
 	@Nullable
@@ -170,13 +166,11 @@ public class ReblogFragment extends BaseFragment {
 	private void showProgressBar() {
 		ui.progressBar.setVisibility(VISIBLE);
 		ui.input.setVisibility(GONE);
-		ui.publish.setVisibility(GONE);
 	}
 
 	private void hideProgressBar() {
 		ui.progressBar.setVisibility(INVISIBLE);
 		ui.input.setVisibility(VISIBLE);
-		ui.publish.setVisibility(VISIBLE);
 	}
 
 	private static class ViewHolder {
@@ -184,15 +178,13 @@ public class ReblogFragment extends BaseFragment {
 		private final ScrollView scrollView;
 		private final ProgressBar progressBar;
 		private final BlogPostViewHolder post;
-		private final EditText input;
-		private final Button publish;
+		private final TextInputView input;
 
 		private ViewHolder(View v) {
 			scrollView = (ScrollView) v.findViewById(R.id.scrollView);
 			progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
 			post = new BlogPostViewHolder(v.findViewById(R.id.postLayout));
-			input = (EditText) v.findViewById(R.id.inputText);
-			publish = (Button) v.findViewById(R.id.publishButton);
+			input = (TextInputView) v.findViewById(R.id.inputText);
 		}
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java b/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java
index dc462331c764a6a04c4e9a5c39ab9892de342c9f..d657fe913b96e7b5467a409161b2afe5e0a20797 100644
--- a/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java
+++ b/briar-android/src/org/briarproject/android/blogs/WriteBlogPostActivity.java
@@ -6,9 +6,6 @@ import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.KeyEvent;
 import android.view.MenuItem;
-import android.view.View;
-import android.widget.Button;
-import android.widget.EditText;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
@@ -17,6 +14,8 @@ import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.api.AndroidNotificationManager;
+import org.briarproject.android.view.TextInputView;
+import org.briarproject.android.view.TextInputView.TextInputListener;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.blogs.BlogManager;
 import org.briarproject.api.blogs.BlogPost;
@@ -39,7 +38,7 @@ import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.blogs.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
 
 public class WriteBlogPostActivity extends BriarActivity
-		implements OnEditorActionListener {
+		implements OnEditorActionListener, TextInputListener {
 
 	private static final Logger LOG =
 			Logger.getLogger(WriteBlogPostActivity.class.getName());
@@ -47,8 +46,7 @@ public class WriteBlogPostActivity extends BriarActivity
 	@Inject
 	protected AndroidNotificationManager notificationManager;
 
-	private EditText bodyInput;
-	private Button publishButton;
+	private TextInputView input;
 	private ProgressBar progressBar;
 
 	// Fields that are accessed from background threads must be volatile
@@ -60,6 +58,7 @@ public class WriteBlogPostActivity extends BriarActivity
 	@Inject
 	volatile BlogManager blogManager;
 
+	@SuppressWarnings("ConstantConditions")
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
@@ -71,8 +70,9 @@ public class WriteBlogPostActivity extends BriarActivity
 
 		setContentView(R.layout.activity_write_blog_post);
 
-		bodyInput = (EditText) findViewById(R.id.bodyInput);
-		bodyInput.addTextChangedListener(new TextWatcher() {
+		input = (TextInputView) findViewById(R.id.bodyInput);
+		input.setSendButtonEnabled(false);
+		input.addTextChangedListener(new TextWatcher() {
 			@Override
 			public void beforeTextChanged(CharSequence s, int start, int count,
 					int after) {
@@ -88,14 +88,7 @@ public class WriteBlogPostActivity extends BriarActivity
 				enableOrDisablePublishButton();
 			}
 		});
-
-		publishButton = (Button) findViewById(R.id.publishButton);
-		publishButton.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				publish();
-			}
-		});
+		input.setListener(this);
 
 		progressBar = (ProgressBar) findViewById(R.id.progressBar);
 	}
@@ -130,25 +123,23 @@ public class WriteBlogPostActivity extends BriarActivity
 
 	@Override
 	public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
-		bodyInput.requestFocus();
+		input.requestFocus();
 		return true;
 	}
 
 	private void enableOrDisablePublishButton() {
 		int bodyLength =
-				StringUtils.toUtf8(bodyInput.getText().toString()).length;
+				StringUtils.toUtf8(input.getText().toString()).length;
 		if (bodyLength > 0 && bodyLength <= MAX_BLOG_POST_BODY_LENGTH)
-			publishButton.setEnabled(true);
+			input.setSendButtonEnabled(true);
 		else
-			publishButton.setEnabled(false);
+			input.setSendButtonEnabled(false);
 	}
 
-	private void publish() {
-		// body
-		String body = bodyInput.getText().toString();
-
+	@Override
+	public void onSendClick(String body) {
 		// hide publish button, show progress bar
-		publishButton.setVisibility(GONE);
+		input.setVisibility(GONE);
 		progressBar.setVisibility(VISIBLE);
 
 		storePost(body);
@@ -192,10 +183,9 @@ public class WriteBlogPostActivity extends BriarActivity
 			public void run() {
 				// hide progress bar, show publish button
 				progressBar.setVisibility(GONE);
-				publishButton.setVisibility(VISIBLE);
+				input.setVisibility(VISIBLE);
 				// TODO show error
 			}
 		});
 	}
-
 }
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index 64e3eb09aa8b18ba01cbfa74c8133859688ba5f4..7ec442b5b1aead70c6bdf6d5131e72f3bcc2901b 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -235,7 +235,7 @@ public class ConversationActivity extends BriarActivity
 		MenuInflater inflater = getMenuInflater();
 		inflater.inflate(R.menu.conversation_actions, menu);
 
-		showIntroductionActionIfAvailable(
+		enableIntroductionActionIfAvailable(
 				menu.findItem(R.id.action_introduction));
 
 		return super.onCreateOptionsMenu(menu);
@@ -269,10 +269,6 @@ public class ConversationActivity extends BriarActivity
 
 	@Override
 	public void onBackPressed() {
-		if (textInputView.isEmojiDrawerOpen()) {
-			textInputView.hideEmojiDrawer();
-			return;
-		}
 		// FIXME disabled exit transition, because it doesn't work for some reason #318
 		//supportFinishAfterTransition();
 		finish();
@@ -755,13 +751,13 @@ public class ConversationActivity extends BriarActivity
 		});
 	}
 
-	private void showIntroductionActionIfAvailable(final MenuItem item) {
+	private void enableIntroductionActionIfAvailable(final MenuItem item) {
 		runOnDbThread(new Runnable() {
 			@Override
 			public void run() {
 				try {
 					if (contactManager.getActiveContacts().size() > 1) {
-						showIntroductionAction(item);
+						enableIntroductionAction(item);
 						Settings settings =
 								settingsManager.getSettings(SETTINGS_NAMESPACE);
 						if (settings.getBoolean(SHOW_ONBOARDING_INTRODUCTION,
@@ -777,11 +773,11 @@ public class ConversationActivity extends BriarActivity
 		});
 	}
 
-	private void showIntroductionAction(final MenuItem item) {
+	private void enableIntroductionAction(final MenuItem item) {
 		runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
-				item.setVisible(true);
+				item.setEnabled(true);
 			}
 		});
 	}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index 2ed6ccbfb859ba74b579276a829e02f6e9dc8b0d..5660bcd23b761e54978fac87623adaed7e9dc898 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -174,9 +174,7 @@ public class ForumActivity extends BriarActivity implements
 
 	@Override
 	public void onBackPressed() {
-		if (textInput.isEmojiDrawerOpen()) {
-			textInput.hideEmojiDrawer();
-		} else if (textInput.getVisibility() == VISIBLE) {
+		if (textInput.getVisibility() == VISIBLE) {
 			textInput.setVisibility(GONE);
 			forumAdapter.setReplyEntry(null);
 		} else {
@@ -193,9 +191,9 @@ public class ForumActivity extends BriarActivity implements
 			textInput.setText("");
 		}
 		textInput.requestFocus();
+		textInput.showSoftKeyboard();
 		textInput.setHint(replyEntry == null ? R.string.forum_new_message_hint :
 				R.string.forum_message_reply_hint);
-		showSoftKeyboardForced(textInput);
 		forumAdapter.setReplyEntry(replyEntry);
 	}
 
@@ -273,7 +271,7 @@ public class ForumActivity extends BriarActivity implements
 					.createPost(StringUtils.toUtf8(text), replyEntry.getId(),
 							resultHandler);
 		}
-		hideSoftKeyboard(textInput);
+		textInput.hideSoftKeyboard();
 		textInput.setVisibility(GONE);
 		forumAdapter.setReplyEntry(null);
 	}
diff --git a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
index 50570a84bfec4a97ff7db04954903109702bae41..05996d5dac10ba74bc297729fb5bdbc30c999985 100644
--- a/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/introduction/IntroductionMessageFragment.java
@@ -6,8 +6,6 @@ import android.support.v7.app.ActionBar;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -15,6 +13,7 @@ import android.widget.Toast;
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.view.TextInputView;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
@@ -35,7 +34,8 @@ import static android.view.View.VISIBLE;
 import static android.widget.Toast.LENGTH_SHORT;
 import static java.util.logging.Level.WARNING;
 
-public class IntroductionMessageFragment extends BaseFragment {
+public class IntroductionMessageFragment extends BaseFragment
+		implements TextInputView.TextInputListener {
 
 	public final static String TAG = "IntroductionMessageFragment";
 
@@ -46,6 +46,7 @@ public class IntroductionMessageFragment extends BaseFragment {
 
 	private IntroductionActivity introductionActivity;
 	private ViewHolder ui;
+	private Contact contact1, contact2;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject
@@ -96,7 +97,7 @@ public class IntroductionMessageFragment extends BaseFragment {
 		// show progress bar until contacts have been loaded
 		ui = new ViewHolder(v);
 		ui.text.setVisibility(GONE);
-		ui.button.setEnabled(false);
+		ui.message.setSendButtonEnabled(false);
 
 		return v;
 	}
@@ -144,6 +145,9 @@ public class IntroductionMessageFragment extends BaseFragment {
 		introductionActivity.runOnUiThread(new Runnable() {
 			@Override
 			public void run() {
+				contact1 = c1;
+				contact2 = c2;
+
 				// set avatars
 				ui.avatar1.setImageDrawable(new IdenticonDrawable(
 						c1.getAuthor().getId().getBytes()));
@@ -160,27 +164,24 @@ public class IntroductionMessageFragment extends BaseFragment {
 						c1.getAuthor().getName(), c2.getAuthor().getName()));
 
 				// set button action
-				ui.button.setOnClickListener(new View.OnClickListener() {
-					@Override
-					public void onClick(View v) {
-						onButtonClick(c1, c2);
-					}
-				});
+				ui.message.setListener(IntroductionMessageFragment.this);
 
 				// hide progress bar and show views
 				ui.progressBar.setVisibility(GONE);
 				ui.text.setVisibility(VISIBLE);
-				ui.button.setEnabled(true);
+				ui.message.setSendButtonEnabled(true);
+				ui.message.showSoftKeyboard();
 			}
 		});
 	}
 
-	private void onButtonClick(final Contact c1, final Contact c2) {
+	@Override
+	public void onSendClick(String text) {
 		// disable button to prevent accidental double invitations
-		ui.button.setEnabled(false);
+		ui.message.setSendButtonEnabled(false);
 
 		String msg = ui.message.getText().toString();
-		makeIntroduction(c1, c2, msg);
+		makeIntroduction(contact1, contact2, msg);
 
 		// don't wait for the introduction to be made before finishing activity
 		introductionActivity.hideSoftKeyboard(ui.message);
@@ -223,18 +224,17 @@ public class IntroductionMessageFragment extends BaseFragment {
 		private final CircleImageView avatar1, avatar2;
 		private final TextView contactName1, contactName2;
 		private final TextView text;
-		private final EditText message;
-		private final Button button;
+		private final TextInputView message;
 
-		ViewHolder(View v) {
+		private ViewHolder(View v) {
 			progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
 			avatar1 = (CircleImageView) v.findViewById(R.id.avatarContact1);
 			avatar2 = (CircleImageView) v.findViewById(R.id.avatarContact2);
 			contactName1 = (TextView) v.findViewById(R.id.nameContact1);
 			contactName2 = (TextView) v.findViewById(R.id.nameContact2);
 			text = (TextView) v.findViewById(R.id.introductionText);
-			message = (EditText) v.findViewById(R.id.introductionMessageView);
-			button = (Button) v.findViewById(R.id.makeIntroductionButton);
+			message = (TextInputView) v
+					.findViewById(R.id.introductionMessageView);
 		}
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java b/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java
index 9b562424c043a9c5660e3bba48985cd61c471304..f981602996fd24a138b4e48b5e6e0ceece55625f 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareBlogMessageFragment.java
@@ -43,7 +43,7 @@ public class ShareBlogMessageFragment extends ShareMessageFragment {
 		setTitle(R.string.blogs_sharing_share);
 
 		View v = super.onCreateView(inflater, container, savedInstanceState);
-		ui.button.setText(getString(R.string.blogs_sharing_button));
+		ui.message.setButtonText(getString(R.string.blogs_sharing_button));
 		return v;
 	}
 
diff --git a/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java b/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
index 3d87df3785831d4477775694114fd7d569fc5a58..0df394e1f807a0aa4c51e4e358efca7249dc405d 100644
--- a/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
+++ b/briar-android/src/org/briarproject/android/sharing/ShareMessageFragment.java
@@ -6,11 +6,11 @@ import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
 
 import org.briarproject.R;
 import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.view.LargeTextInputView;
+import org.briarproject.android.view.TextInputView.TextInputListener;
 import org.briarproject.api.blogs.BlogSharingManager;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.forum.ForumSharingManager;
@@ -26,7 +26,8 @@ import static org.briarproject.android.sharing.ShareActivity.CONTACTS;
 import static org.briarproject.android.sharing.ShareActivity.getContactsFromIds;
 import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
 
-abstract class ShareMessageFragment extends BaseFragment {
+abstract class ShareMessageFragment extends BaseFragment
+		implements TextInputListener {
 
 	public final static String TAG = ShareMessageFragment.class.getName();
 
@@ -81,16 +82,17 @@ abstract class ShareMessageFragment extends BaseFragment {
 		View v = inflater.inflate(R.layout.fragment_share_message, container,
 				false);
 		ui = new ViewHolder(v);
-		ui.button.setOnClickListener(new View.OnClickListener() {
-			@Override
-			public void onClick(View v) {
-				onButtonClick();
-			}
-		});
+		ui.message.setListener(this);
 
 		return v;
 	}
 
+	@Override
+	public void onStart() {
+		super.onStart();
+		ui.message.showSoftKeyboard();
+	}
+
 	@Override
 	public boolean onOptionsItemSelected(final MenuItem item) {
 		switch (item.getItemId()) {
@@ -111,11 +113,11 @@ abstract class ShareMessageFragment extends BaseFragment {
 		shareActivity.setTitle(res);
 	}
 
-	private void onButtonClick() {
+	@Override
+	public void onSendClick(String msg) {
 		// disable button to prevent accidental double invitations
-		ui.button.setEnabled(false);
+		ui.message.setSendButtonEnabled(false);
 
-		String msg = ui.message.getText().toString();
 		share(msg);
 
 		// don't wait for the invitation to be made before finishing activity
@@ -139,12 +141,11 @@ abstract class ShareMessageFragment extends BaseFragment {
 	}
 
 	protected static class ViewHolder {
-		protected final EditText message;
-		protected final Button button;
+		protected final LargeTextInputView message;
 
-		ViewHolder(View v) {
-			message = (EditText) v.findViewById(R.id.invitationMessageView);
-			button = (Button) v.findViewById(R.id.shareForumButton);
+		private ViewHolder(View v) {
+			message = (LargeTextInputView) v
+					.findViewById(R.id.invitationMessageView);
 		}
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/view/LargeTextInputView.java b/briar-android/src/org/briarproject/android/view/LargeTextInputView.java
new file mode 100644
index 0000000000000000000000000000000000000000..124361158bf96c77c589859f997054e3a1b5828d
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/view/LargeTextInputView.java
@@ -0,0 +1,77 @@
+package org.briarproject.android.view;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import org.briarproject.R;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
+@UiThread
+public class LargeTextInputView extends TextInputView {
+
+	public LargeTextInputView(Context context) {
+		this(context, null);
+	}
+
+	public LargeTextInputView(Context context, @Nullable AttributeSet attrs) {
+		this(context, attrs, 0);
+	}
+
+	public LargeTextInputView(Context context, @Nullable AttributeSet attrs,
+			int defStyleAttr) {
+		super(context, attrs, defStyleAttr);
+	}
+
+	@Override
+	protected void inflateLayout(Context context) {
+		LayoutInflater inflater = (LayoutInflater) context
+				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+		inflater.inflate(R.layout.text_input_view_large, this, true);
+	}
+
+	@Override
+	protected void setUpViews(Context context, @Nullable AttributeSet attrs) {
+		super.setUpViews(context, attrs);
+
+		// get attributes
+		TypedArray attributes = context.obtainStyledAttributes(attrs,
+				R.styleable.LargeTextInputView);
+		String buttonText =
+				attributes.getString(R.styleable.LargeTextInputView_buttonText);
+		int maxLines =
+				attributes
+						.getInteger(R.styleable.LargeTextInputView_maxLines, 0);
+		boolean fillHeight = attributes
+				.getBoolean(R.styleable.LargeTextInputView_fillHeight,
+						false);
+		attributes.recycle();
+
+		if (buttonText != null) setButtonText(buttonText);
+		if (maxLines > 0) ui.editText.setMaxLines(maxLines);
+		if (fillHeight) {
+			LinearLayout layout =
+					(LinearLayout) findViewById(R.id.input_layout);
+			LayoutParams params = (LayoutParams) layout.getLayoutParams();
+			params.height = 0;
+			params.weight = 1;
+			layout.setLayoutParams(params);
+			ViewGroup.LayoutParams editParams = ui.editText.getLayoutParams();
+			editParams.height = MATCH_PARENT;
+			ui.editText.setLayoutParams(editParams);
+		}
+	}
+
+	public void setButtonText(String text) {
+		((Button) ui.sendButton).setText(text);
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/view/TextInputView.java b/briar-android/src/org/briarproject/android/view/TextInputView.java
index e257a1915efe96a9272023a6ba2ebefa1256003e..e65c519ab9ddf4eb979d15f34b18799759a378b6 100644
--- a/briar-android/src/org/briarproject/android/view/TextInputView.java
+++ b/briar-android/src/org/briarproject/android/view/TextInputView.java
@@ -1,18 +1,29 @@
 package org.briarproject.android.view;
 
+import android.animation.LayoutTransition;
 import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
 import android.os.IBinder;
+import android.support.annotation.CallSuper;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.annotation.UiThread;
+import android.support.v7.widget.AppCompatImageButton;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
 
 import org.briarproject.R;
-import org.thoughtcrime.securesms.components.KeyboardAwareRelativeLayout;
+import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout;
 import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
 import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener;
 import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
@@ -21,19 +32,17 @@ import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
 import java.util.logging.Logger;
 
 import static android.content.Context.INPUT_METHOD_SERVICE;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
 @UiThread
-public class TextInputView extends KeyboardAwareRelativeLayout
+public class TextInputView extends KeyboardAwareLinearLayout
 		implements EmojiEventListener {
 
 	private static final String TAG = TextInputView.class.getName();
 	private static final Logger LOG = Logger.getLogger(TAG);
 
-	private EmojiEditText editText;
-	private View sendButton;
-	private EmojiDrawer emojiDrawer;
-
-	private TextInputListener listener;
+	protected final ViewHolder ui;
+	protected TextInputListener listener;
 
 	public TextInputView(Context context) {
 		this(context, null);
@@ -46,50 +55,80 @@ public class TextInputView extends KeyboardAwareRelativeLayout
 	public TextInputView(Context context, @Nullable AttributeSet attrs,
 			int defStyleAttr) {
 		super(context, attrs, defStyleAttr);
+		setOrientation(VERTICAL);
+		setLayoutTransition(new LayoutTransition());
+
+		inflateLayout(context);
+		ui = new ViewHolder();
+		setUpViews(context, attrs);
+	}
 
+	protected void inflateLayout(Context context) {
 		LayoutInflater inflater = (LayoutInflater) context
 				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 		inflater.inflate(R.layout.text_input_view, this, true);
+	}
 
-		// find views
-		EmojiToggle emojiToggle = (EmojiToggle) findViewById(R.id.emoji_toggle);
-		editText = (EmojiEditText) findViewById(R.id.input_text);
-		emojiDrawer = (EmojiDrawer) findViewById(R.id.emoji_drawer);
-		sendButton = findViewById(R.id.btn_send);
+	@CallSuper
+	protected void setUpViews(Context context, @Nullable AttributeSet attrs) {
+		// get attributes
+		TypedArray attributes = context.obtainStyledAttributes(attrs,
+				R.styleable.TextInputView);
+		String hint = attributes.getString(R.styleable.TextInputView_hint);
+		attributes.recycle();
 
-		emojiToggle.attach(emojiDrawer);
-		emojiToggle.setOnClickListener(new OnClickListener() {
+		if (hint != null) {
+			ui.editText.setHint(hint);
+		}
+
+		ui.emojiToggle.attach(ui.emojiDrawer);
+		ui.emojiToggle.setOnClickListener(new OnClickListener() {
 			@Override
 			public void onClick(View v) {
 				onEmojiToggleClicked();
 			}
 		});
-		editText.setOnClickListener(new OnClickListener() {
+		ui.editText.setOnClickListener(new OnClickListener() {
 			@Override
 			public void onClick(View v) {
 				showSoftKeyboard();
 			}
 		});
-		sendButton.setOnClickListener(new OnClickListener() {
+		ui.editText.setOnKeyListener(new OnKeyListener() {
+			@Override
+			public boolean onKey(View v, int keyCode, KeyEvent event) {
+				if (keyCode == KeyEvent.KEYCODE_BACK && isEmojiDrawerOpen()) {
+					hideEmojiDrawer();
+					return true;
+				}
+				return false;
+			}
+		});
+		ui.sendButton.setOnClickListener(new OnClickListener() {
 			@Override
 			public void onClick(View v) {
 				if (listener != null) {
-					listener.onSendClick(editText.getText().toString());
-					editText.setText("");
+					listener.onSendClick(ui.editText.getText().toString());
+					ui.editText.setText("");
 				}
 			}
 		});
-		emojiDrawer.setEmojiEventListener(this);
+		ui.emojiDrawer.setEmojiEventListener(this);
 	}
 
 	@Override
 	public void onKeyEvent(KeyEvent keyEvent) {
-		editText.dispatchKeyEvent(keyEvent);
+		ui.editText.dispatchKeyEvent(keyEvent);
 	}
 
 	@Override
 	public void onEmojiSelected(String emoji) {
-		editText.insertEmoji(emoji);
+		ui.editText.insertEmoji(emoji);
+	}
+
+	@Override
+	public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+		return ui.editText.requestFocus(direction, previouslyFocusedRect);
 	}
 
 	private void onEmojiToggleClicked() {
@@ -101,29 +140,33 @@ public class TextInputView extends KeyboardAwareRelativeLayout
 	}
 
 	public void setText(String text) {
-		editText.setText(text);
+		ui.editText.setText(text);
+	}
+
+	public Editable getText() {
+		return ui.editText.getText();
 	}
 
 	public void setHint(@StringRes int res) {
-		editText.setHint(res);
+		ui.editText.setHint(res);
 	}
 
 	public void setSendButtonEnabled(boolean enabled) {
-		sendButton.setEnabled(enabled);
+		ui.sendButton.setEnabled(enabled);
 	}
 
-	public void setListener(TextInputListener listener) {
-		this.listener = listener;
+	public void addTextChangedListener(TextWatcher watcher) {
+		ui.editText.addTextChangedListener(watcher);
 	}
 
-	public interface TextInputListener {
-		void onSendClick(String text);
+	public void setListener(TextInputListener listener) {
+		this.listener = listener;
 	}
 
 	public void showSoftKeyboard() {
 		if (isKeyboardOpen()) return;
 
-		if (emojiDrawer.isShowing()) {
+		if (ui.emojiDrawer.isShowing()) {
 			postOnKeyboardOpen(new Runnable() {
 				@Override
 				public void run() {
@@ -131,18 +174,18 @@ public class TextInputView extends KeyboardAwareRelativeLayout
 				}
 			});
 		}
-		editText.post(new Runnable() {
+		ui.editText.post(new Runnable() {
 			@Override
 			public void run() {
-				editText.requestFocus();
+				ui.editText.requestFocus();
 				Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
-				((InputMethodManager) o).showSoftInput(editText, 0);
+				((InputMethodManager) o).showSoftInput(ui.editText, 0);
 			}
 		});
 	}
 
 	public void hideSoftKeyboard() {
-		IBinder token = editText.getWindowToken();
+		IBinder token = ui.editText.getWindowToken();
 		Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
 		((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
 	}
@@ -151,21 +194,40 @@ public class TextInputView extends KeyboardAwareRelativeLayout
 		if (isKeyboardOpen()) {
 			postOnKeyboardClose(new Runnable() {
 				@Override public void run() {
-					emojiDrawer.show(getKeyboardHeight());
+					ui.emojiDrawer.show(getKeyboardHeight());
 				}
 			});
 			hideSoftKeyboard();
 		} else {
-			emojiDrawer.show(getKeyboardHeight());
+			ui.emojiDrawer.show(getKeyboardHeight());
+			ui.editText.requestFocus();
 		}
 	}
 
 	public void hideEmojiDrawer() {
-		emojiDrawer.hide();
+		ui.emojiDrawer.hide();
 	}
 
 	public boolean isEmojiDrawerOpen() {
-		return emojiDrawer.isShowing();
+		return ui.emojiDrawer.isShowing();
+	}
+
+	protected class ViewHolder {
+		private final EmojiToggle emojiToggle;
+		protected final EmojiEditText editText;
+		protected final View sendButton;
+		protected final EmojiDrawer emojiDrawer;
+
+		private ViewHolder() {
+			emojiToggle = (EmojiToggle) findViewById(R.id.emoji_toggle);
+			editText = (EmojiEditText) findViewById(R.id.input_text);
+			emojiDrawer = (EmojiDrawer) findViewById(R.id.emoji_drawer);
+			sendButton = findViewById(R.id.btn_send);
+		}
+	}
+
+	public interface TextInputListener {
+		void onSendClick(String text);
 	}
 
 }
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareRelativeLayout.java b/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
similarity index 95%
rename from briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareRelativeLayout.java
rename to briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
index 5217078252324fab5d8e0ce730cbfca0e5ec25f3..1e1b5d50da776f712a15c31915653165b404c4b0 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareRelativeLayout.java
+++ b/briar-android/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java
@@ -11,7 +11,7 @@ import android.support.annotation.UiThread;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.WindowManager;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
 
 import org.briarproject.R;
 
@@ -31,10 +31,10 @@ import static java.util.logging.Level.WARNING;
  * a soft keyboard has been opened and what its height would be.
  */
 @UiThread
-public class KeyboardAwareRelativeLayout extends RelativeLayout {
+public class KeyboardAwareLinearLayout extends LinearLayout {
 
 	private static final Logger LOG =
-			Logger.getLogger(KeyboardAwareRelativeLayout.class.getName());
+			Logger.getLogger(KeyboardAwareLinearLayout.class.getName());
 
 	private final Rect rect = new Rect();
 	private final Set<OnKeyboardHiddenListener> hiddenListeners =
@@ -51,16 +51,16 @@ public class KeyboardAwareRelativeLayout extends RelativeLayout {
 	private boolean keyboardOpen = false;
 	private int rotation = -1;
 
-	public KeyboardAwareRelativeLayout(Context context) {
+	public KeyboardAwareLinearLayout(Context context) {
 		this(context, null);
 	}
 
-	public KeyboardAwareRelativeLayout(Context context,
+	public KeyboardAwareLinearLayout(Context context,
 			@Nullable AttributeSet attrs) {
 		this(context, attrs, 0);
 	}
 
-	public KeyboardAwareRelativeLayout(Context context,
+	public KeyboardAwareLinearLayout(Context context,
 			@Nullable AttributeSet attrs, int defStyle) {
 		super(context, attrs, defStyle);
 		final int statusBarRes = getResources()
diff --git a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java b/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
index 7d10a6393df448b2655151033c635c8e277a7f39..83f2e8cc9613832311a71c595560b4b15c649c05 100644
--- a/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
+++ b/briar-android/src/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java
@@ -41,6 +41,7 @@ public class EmojiTextView extends TextView {
 	@Override
 	public void setText(@Nullable CharSequence text, BufferType type) {
 		source = EmojiProvider.getInstance(getContext()).emojify(text, this);
+
 		setTextEllipsized(source);
 	}