Show message time and date (fixes #32).

This commit is contained in:
Felix Ableitner 2015-07-28 16:19:02 +02:00
parent 122bf7f167
commit 547f4ff0cb
6 changed files with 99 additions and 23 deletions

View file

@ -17,6 +17,7 @@ dependencies {
{ exclude module: "multidex" }
compile "org.scala-lang:scala-library:2.11.7"
compile 'com.google.guava:guava:18.0'
compile 'com.mobsandgeeks:adapter-kit:0.5.3'
}
// RtlHardcoded behaviour differs between target API versions. We only care about API 15.

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/date"
android:gravity="center"
android:padding="10dp"/>

View file

@ -1,17 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="horizontal">
android:layout_width="match_parent">
<TextView
android:id="@android:id/text1"
android:layout_width="wrap_content"
<LinearLayout
android:layout_height="wrap_content"
android:padding="5dip"
android:layout_width="wrap_content"
android:id="@+id/container"
android:minWidth="50dp"
android:orientation="vertical"
android:background="@drawable/message_background"
android:textAppearance="?android:attr/textAppearanceMedium"/>
android:padding="5dp">
</RelativeLayout>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="200dp"
android:textSize="18sp"
android:includeFontPadding="false" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:includeFontPadding="false"
android:textColor="@color/secondary_text"/>
</LinearLayout>
</LinearLayout>

View file

@ -1,7 +1,7 @@
package com.nutomic.ensichat.fragments
import android.app.ListFragment
import android.content.{IntentFilter, Intent, Context, BroadcastReceiver}
import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
import android.os.Bundle
import android.support.v4.content.LocalBroadcastManager
import android.view.View.OnClickListener
@ -12,9 +12,9 @@ import android.widget._
import com.nutomic.ensichat.R
import com.nutomic.ensichat.activities.EnsichatActivity
import com.nutomic.ensichat.protocol.body.Text
import com.nutomic.ensichat.protocol.{Message, Address, ChatService}
import com.nutomic.ensichat.protocol.{Address, ChatService, Message}
import com.nutomic.ensichat.util.Database
import com.nutomic.ensichat.views.MessagesAdapter
import com.nutomic.ensichat.views.{DatesAdapter, MessagesAdapter}
/**
* Represents a single chat with another specific device.
@ -41,7 +41,7 @@ class ChatFragment extends ListFragment with OnClickListener {
private var listView: ListView = _
private var adapter: MessagesAdapter = _
private var adapter: DatesAdapter = _
override def onActivityCreated(savedInstanceState: Bundle): Unit = {
super.onActivityCreated(savedInstanceState)
@ -52,8 +52,7 @@ class ChatFragment extends ListFragment with OnClickListener {
database.getContact(address).foreach(c => getActivity.setTitle(c.name))
// Read local device ID from service,
adapter = new MessagesAdapter(getActivity, address)
adapter = new DatesAdapter(getActivity, new MessagesAdapter(getActivity, address))
database.getMessages(address, 15).foreach(adapter.add)
if (listView != null) {

View file

@ -0,0 +1,35 @@
package com.nutomic.ensichat.views
import java.text.DateFormat
import android.content.Context
import com.mobsandgeeks.adapters.{Sectionizer, SimpleSectionAdapter}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.protocol.Message
import com.nutomic.ensichat.protocol.header.ContentHeader
object DatesAdapter {
private val Sectionizer = new Sectionizer[Message]() {
override def getSectionTitleForItem(item: Message): String = {
DateFormat
.getDateInstance(DateFormat.MEDIUM)
.format(item.header.asInstanceOf[ContentHeader].time)
}
}
}
/**
* Wraps [[MessagesAdapter]] and shows date between messages.
*/
class DatesAdapter(context: Context, messagesAdapter: MessagesAdapter)
extends SimpleSectionAdapter[Message](context, messagesAdapter, R.layout.item_date, R.id.date,
DatesAdapter.Sectionizer) {
def add(message: Message): Unit = {
messagesAdapter.add(message)
notifyDataSetChanged()
}
}

View file

@ -1,17 +1,20 @@
package com.nutomic.ensichat.views
import java.text.DateFormat
import android.content.Context
import android.view.{Gravity, View, ViewGroup}
import android.widget.{ArrayAdapter, RelativeLayout, TextView}
import android.view.{Gravity, LayoutInflater, View, ViewGroup}
import android.widget.{ArrayAdapter, LinearLayout, TextView}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.protocol.body.Text
import com.nutomic.ensichat.protocol.header.ContentHeader
import com.nutomic.ensichat.protocol.{Address, Message}
/**
* Displays [[Message]]s in ListView.
*/
class MessagesAdapter(context: Context, remoteAddress: Address) extends
ArrayAdapter[Message](context, R.layout.item_message, android.R.id.text1) {
ArrayAdapter[Message](context, 0, 0) {
/**
* Free space to the right/left to a message depending on who sent it, in dip.
@ -19,21 +22,34 @@ class MessagesAdapter(context: Context, remoteAddress: Address) extends
private val MessageMargin = 50
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
val view = super.getView(position, convertView, parent).asInstanceOf[RelativeLayout]
val tv = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
val view =
if (convertView != null)
convertView.asInstanceOf[LinearLayout]
else
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
.asInstanceOf[LayoutInflater]
.inflate(R.layout.item_message, parent, false)
.asInstanceOf[LinearLayout]
val text = view.findViewById(R.id.text).asInstanceOf[TextView]
val time = view.findViewById(R.id.time).asInstanceOf[TextView]
tv.setText(getItem(position).body.asInstanceOf[Text].text)
val msg = getItem(position)
text.setText(msg.body.asInstanceOf[Text].text)
time.setText(DateFormat.getTimeInstance(DateFormat.SHORT).format(msg.header.asInstanceOf[ContentHeader].time))
val lp = new RelativeLayout.LayoutParams(tv.getLayoutParams)
val lp = new LinearLayout.LayoutParams(view.getLayoutParams)
val margin = (MessageMargin * context.getResources.getDisplayMetrics.density).toInt
val container = view.findViewById(R.id.container).asInstanceOf[LinearLayout]
if (getItem(position).header.origin != remoteAddress) {
container.setGravity(Gravity.RIGHT)
view.setGravity(Gravity.RIGHT)
lp.setMargins(margin, 0, 0, 0)
} else {
container.setGravity(Gravity.LEFT)
view.setGravity(Gravity.LEFT)
lp.setMargins(0, 0, margin, 0)
}
tv.setLayoutParams(lp)
view.setLayoutParams(lp)
view
}