Add timeline empty state and date control buttons
This commit is contained in:
parent
474e620bf3
commit
3788f5183c
4 changed files with 129 additions and 31 deletions
40
OsmAnd-telegram/res/layout/empty_state_timeline.xml
Normal file
40
OsmAnd-telegram/res/layout/empty_state_timeline.xml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/empty_state_background_image"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/content_padding_big"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/img_timeline_no_data"
|
||||||
|
android:tint="@color/icon_light" />
|
||||||
|
|
||||||
|
<net.osmand.telegram.ui.views.TextViewEx
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding_half"
|
||||||
|
android:background="@null"
|
||||||
|
android:text="@string/timeline_no_data"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
osmand:typeface="@string/font_roboto_medium" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/empty_state_descr_margin"
|
||||||
|
android:layout_marginRight="@dimen/empty_state_descr_margin"
|
||||||
|
android:background="@null"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timeline_no_data_descr"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
@ -20,11 +21,11 @@
|
||||||
android:letterSpacing="@dimen/title_letter_spacing"
|
android:letterSpacing="@dimen/title_letter_spacing"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingLeft="@dimen/content_padding_standard"
|
android:paddingLeft="@dimen/content_padding_standard"
|
||||||
|
android:paddingTop="@dimen/content_padding_standard"
|
||||||
android:paddingRight="@dimen/content_padding_standard"
|
android:paddingRight="@dimen/content_padding_standard"
|
||||||
|
android:paddingBottom="12dp"
|
||||||
android:text="@string/timeline"
|
android:text="@string/timeline"
|
||||||
android:textColor="@color/app_bar_title_light"
|
android:textColor="@color/app_bar_title_light"
|
||||||
android:paddingTop="@dimen/content_padding_standard"
|
|
||||||
android:paddingBottom="12dp"
|
|
||||||
android:textSize="@dimen/title_text_size"
|
android:textSize="@dimen/title_text_size"
|
||||||
app:typeface="@string/font_roboto_mono_bold" />
|
app:typeface="@string/font_roboto_mono_bold" />
|
||||||
|
|
||||||
|
@ -84,6 +85,19 @@
|
||||||
android:paddingLeft="@dimen/content_padding_standard"
|
android:paddingLeft="@dimen/content_padding_standard"
|
||||||
android:paddingRight="@dimen/content_padding_standard">
|
android:paddingRight="@dimen/content_padding_standard">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/date_btn_previous"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/dialog_button_height"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:background="@drawable/btn_round_border"
|
||||||
|
android:paddingStart="@dimen/content_padding_half"
|
||||||
|
android:paddingLeft="@dimen/content_padding_half"
|
||||||
|
android:paddingEnd="@dimen/content_padding_big"
|
||||||
|
android:paddingRight="@dimen/content_padding_big"
|
||||||
|
android:src="@drawable/ic_arrow_back"
|
||||||
|
tools:tint="?attr/ctrl_active_color" />
|
||||||
|
|
||||||
<net.osmand.telegram.ui.views.TextViewEx
|
<net.osmand.telegram.ui.views.TextViewEx
|
||||||
android:id="@+id/date_btn"
|
android:id="@+id/date_btn"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -103,6 +117,20 @@
|
||||||
android:textSize="@dimen/text_button_text_size"
|
android:textSize="@dimen/text_button_text_size"
|
||||||
app:typeface="@string/font_roboto_medium" />
|
app:typeface="@string/font_roboto_medium" />
|
||||||
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/date_btn_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/dialog_button_height"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:background="@drawable/btn_round_border"
|
||||||
|
android:paddingStart="@dimen/content_padding_big"
|
||||||
|
android:paddingLeft="@dimen/content_padding_big"
|
||||||
|
android:paddingEnd="@dimen/content_padding_half"
|
||||||
|
android:paddingRight="@dimen/content_padding_half"
|
||||||
|
android:src="@drawable/ic_arrow_forward"
|
||||||
|
tools:tint="?attr/ctrl_active_color" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
@ -112,13 +140,23 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<FrameLayout
|
||||||
android:id="@+id/recycler_view"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:clipToPadding="false"
|
|
||||||
android:paddingBottom="@dimen/list_item_content_margin"
|
<net.osmand.telegram.ui.views.EmptyStateRecyclerView
|
||||||
android:scrollbars="vertical" />
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="@dimen/list_item_content_margin"
|
||||||
|
android:scrollbars="vertical" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/empty_view"
|
||||||
|
layout="@layout/empty_state_timeline" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="timeline_no_data_descr">We don`t have collected data for the selected day</string>
|
||||||
|
<string name="timeline_no_data">No data</string>
|
||||||
<string name="shared_string_select">Select</string>
|
<string name="shared_string_select">Select</string>
|
||||||
<string name="min_logging_distance">Minimum logging distance</string>
|
<string name="min_logging_distance">Minimum logging distance</string>
|
||||||
<string name="min_logging_distance_descr">Filter: minimum distance to log a new point</string>
|
<string name="min_logging_distance_descr">Filter: minimum distance to log a new point</string>
|
||||||
|
|
|
@ -16,15 +16,16 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.Switch
|
import android.widget.Switch
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import net.osmand.PlatformUtil
|
|
||||||
import net.osmand.telegram.R
|
import net.osmand.telegram.R
|
||||||
import net.osmand.telegram.TelegramApplication
|
import net.osmand.telegram.TelegramApplication
|
||||||
import net.osmand.telegram.helpers.LocationMessages
|
import net.osmand.telegram.helpers.LocationMessages
|
||||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||||
import net.osmand.telegram.helpers.TelegramUiHelper.ListItem
|
import net.osmand.telegram.helpers.TelegramUiHelper.ListItem
|
||||||
import net.osmand.telegram.ui.TimelineTabFragment.LiveNowListAdapter.BaseViewHolder
|
import net.osmand.telegram.ui.TimelineTabFragment.LiveNowListAdapter.BaseViewHolder
|
||||||
|
import net.osmand.telegram.ui.views.EmptyStateRecyclerView
|
||||||
import net.osmand.telegram.utils.AndroidUtils
|
import net.osmand.telegram.utils.AndroidUtils
|
||||||
import net.osmand.telegram.utils.OsmandFormatter
|
import net.osmand.telegram.utils.OsmandFormatter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -32,8 +33,6 @@ import java.util.*
|
||||||
|
|
||||||
class TimelineTabFragment : Fragment() {
|
class TimelineTabFragment : Fragment() {
|
||||||
|
|
||||||
private val log = PlatformUtil.getLog(TimelineTabFragment::class.java)
|
|
||||||
|
|
||||||
private val app: TelegramApplication
|
private val app: TelegramApplication
|
||||||
get() = activity?.application as TelegramApplication
|
get() = activity?.application as TelegramApplication
|
||||||
|
|
||||||
|
@ -43,11 +42,12 @@ class TimelineTabFragment : Fragment() {
|
||||||
private lateinit var adapter: LiveNowListAdapter
|
private lateinit var adapter: LiveNowListAdapter
|
||||||
|
|
||||||
private lateinit var dateBtn: TextView
|
private lateinit var dateBtn: TextView
|
||||||
|
private lateinit var previousDateBtn: ImageView
|
||||||
|
private lateinit var nextDateBtn: ImageView
|
||||||
private lateinit var mainView: View
|
private lateinit var mainView: View
|
||||||
private lateinit var switcher: Switch
|
private lateinit var switcher: Switch
|
||||||
|
|
||||||
private var start = 0L
|
private lateinit var calendar: Calendar
|
||||||
private var end = 0L
|
|
||||||
|
|
||||||
private var updateEnable: Boolean = false
|
private var updateEnable: Boolean = false
|
||||||
|
|
||||||
|
@ -59,15 +59,16 @@ class TimelineTabFragment : Fragment() {
|
||||||
mainView = inflater.inflate(R.layout.fragment_timeline_tab, container, false)
|
mainView = inflater.inflate(R.layout.fragment_timeline_tab, container, false)
|
||||||
val appBarLayout = mainView.findViewById<View>(R.id.app_bar_layout)
|
val appBarLayout = mainView.findViewById<View>(R.id.app_bar_layout)
|
||||||
|
|
||||||
val calendar = Calendar.getInstance()
|
calendar = Calendar.getInstance()
|
||||||
start = getStartOfDay(calendar)
|
|
||||||
end = getEndOfDay(calendar)
|
|
||||||
|
|
||||||
AndroidUtils.addStatusBarPadding19v(context!!, appBarLayout)
|
AndroidUtils.addStatusBarPadding19v(context!!, appBarLayout)
|
||||||
adapter = LiveNowListAdapter()
|
adapter = LiveNowListAdapter()
|
||||||
mainView.findViewById<RecyclerView>(R.id.recycler_view).apply {
|
|
||||||
|
val emptyView = mainView.findViewById<LinearLayout>(R.id.empty_view)
|
||||||
|
mainView.findViewById<EmptyStateRecyclerView>(R.id.recycler_view).apply {
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
adapter = this@TimelineTabFragment.adapter
|
adapter = this@TimelineTabFragment.adapter
|
||||||
|
setEmptyView(emptyView)
|
||||||
}
|
}
|
||||||
|
|
||||||
switcher = mainView.findViewById<Switch>(R.id.monitoring_switcher)
|
switcher = mainView.findViewById<Switch>(R.id.monitoring_switcher)
|
||||||
|
@ -88,7 +89,25 @@ class TimelineTabFragment : Fragment() {
|
||||||
}
|
}
|
||||||
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_start), null, null, null)
|
setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_start), null, null, null)
|
||||||
setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||||
text = OsmandFormatter.getFormattedDate(start / 1000)
|
}
|
||||||
|
updateDateButton()
|
||||||
|
|
||||||
|
previousDateBtn = mainView.findViewById<ImageView>(R.id.date_btn_previous).apply {
|
||||||
|
setImageDrawable(getPressedStateIcon(R.drawable.ic_arrow_back))
|
||||||
|
setOnClickListener {
|
||||||
|
calendar.add(Calendar.DAY_OF_MONTH, -1)
|
||||||
|
updateList()
|
||||||
|
updateDateButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextDateBtn = mainView.findViewById<ImageView>(R.id.date_btn_next).apply {
|
||||||
|
setImageDrawable(getPressedStateIcon(R.drawable.ic_arrow_forward))
|
||||||
|
setOnClickListener {
|
||||||
|
calendar.add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
updateList()
|
||||||
|
updateDateButton()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mainView.findViewById<SwipeRefreshLayout>(R.id.swipe_refresh).apply {
|
mainView.findViewById<SwipeRefreshLayout>(R.id.swipe_refresh).apply {
|
||||||
|
@ -122,25 +141,21 @@ class TimelineTabFragment : Fragment() {
|
||||||
fun tabClosed() {}
|
fun tabClosed() {}
|
||||||
|
|
||||||
private fun selectDate() {
|
private fun selectDate() {
|
||||||
val dateFromDialog =
|
val dateSetListener =
|
||||||
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
|
||||||
val calendar = Calendar.getInstance()
|
calendar = Calendar.getInstance()
|
||||||
calendar.set(Calendar.YEAR, year)
|
calendar.set(Calendar.YEAR, year)
|
||||||
calendar.set(Calendar.MONTH, monthOfYear)
|
calendar.set(Calendar.MONTH, monthOfYear)
|
||||||
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth)
|
||||||
|
|
||||||
start = getStartOfDay(calendar)
|
|
||||||
end = getEndOfDay(calendar)
|
|
||||||
|
|
||||||
updateList()
|
updateList()
|
||||||
updateDateButton()
|
updateDateButton()
|
||||||
}
|
}
|
||||||
val startCalendar = Calendar.getInstance()
|
DatePickerDialog(
|
||||||
startCalendar.timeInMillis = start
|
context, dateSetListener,
|
||||||
DatePickerDialog(context, dateFromDialog,
|
calendar.get(Calendar.YEAR),
|
||||||
startCalendar.get(Calendar.YEAR),
|
calendar.get(Calendar.MONTH),
|
||||||
startCalendar.get(Calendar.MONTH),
|
calendar.get(Calendar.DAY_OF_MONTH)
|
||||||
startCalendar.get(Calendar.DAY_OF_MONTH)
|
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +176,7 @@ class TimelineTabFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDateButton() {
|
private fun updateDateButton() {
|
||||||
dateBtn.text = OsmandFormatter.getFormattedDate(start / 1000)
|
dateBtn.text = OsmandFormatter.getFormattedDate(getStartOfDay(calendar) / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPressedStateIcon(@DrawableRes iconId: Int): Drawable? {
|
private fun getPressedStateIcon(@DrawableRes iconId: Int): Drawable? {
|
||||||
|
@ -187,6 +202,8 @@ class TimelineTabFragment : Fragment() {
|
||||||
|
|
||||||
private fun updateList() {
|
private fun updateList() {
|
||||||
val res = mutableListOf<ListItem>()
|
val res = mutableListOf<ListItem>()
|
||||||
|
val start = getStartOfDay(calendar)
|
||||||
|
val end = getEndOfDay(calendar)
|
||||||
app.locationMessages.getIngoingUserLocations(start, end).forEach {
|
app.locationMessages.getIngoingUserLocations(start, end).forEach {
|
||||||
TelegramUiHelper.userLocationsToChatItem(telegramHelper, it)?.also { chatItem ->
|
TelegramUiHelper.userLocationsToChatItem(telegramHelper, it)?.also { chatItem ->
|
||||||
res.add(chatItem)
|
res.add(chatItem)
|
||||||
|
@ -303,12 +320,13 @@ class TimelineTabFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UITrackData (
|
data class UITrackData(
|
||||||
var dist: Float,
|
var dist: Float,
|
||||||
var points: Int,
|
var points: Int,
|
||||||
var minTime: Long,
|
var minTime: Long,
|
||||||
var maxTime: Long
|
var maxTime: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ADAPTER_UPDATE_INTERVAL_MIL = 15 * 1000L // 15 sec
|
private const val ADAPTER_UPDATE_INTERVAL_MIL = 15 * 1000L // 15 sec
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue