Configurable main navigation
parent
4c2197aa5d
commit
95547a8d03
@ -0,0 +1,33 @@
|
||||
package org.koitharu.kotatsu.core.prefs
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.StringRes
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
|
||||
enum class NavItem(
|
||||
@IdRes val id: Int,
|
||||
@StringRes val title: Int,
|
||||
@DrawableRes val icon: Int,
|
||||
) : ListModel {
|
||||
|
||||
HISTORY(R.id.nav_history, R.string.history, R.drawable.ic_history_selector),
|
||||
FAVORITES(R.id.nav_favorites, R.string.favourites, R.drawable.ic_favourites_selector),
|
||||
LOCAL(R.id.nav_local, R.string.on_device, R.drawable.ic_storage_selector),
|
||||
EXPLORE(R.id.nav_explore, R.string.explore, R.drawable.ic_explore_selector),
|
||||
SUGGESTIONS(R.id.nav_suggestions, R.string.suggestions, R.drawable.ic_suggestion_selector),
|
||||
FEED(R.id.nav_feed, R.string.feed, R.drawable.ic_feed_selector),
|
||||
BOOKMARKS(R.id.nav_bookmarks, R.string.bookmarks, R.drawable.ic_bookmark_selector),
|
||||
;
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is NavItem && ordinal == other.ordinal
|
||||
}
|
||||
|
||||
fun isAvailable(settings: AppSettings): Boolean = when (this) {
|
||||
SUGGESTIONS -> settings.isSuggestionsEnabled
|
||||
FEED -> settings.isTrackerEnabled
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
package org.koitharu.kotatsu.settings.nav
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.NavItem
|
||||
import org.koitharu.kotatsu.core.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
||||
import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
|
||||
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.settings.nav.adapter.navAddAD
|
||||
import org.koitharu.kotatsu.settings.nav.adapter.navAvailableAD
|
||||
import org.koitharu.kotatsu.settings.nav.adapter.navConfigAD
|
||||
|
||||
@AndroidEntryPoint
|
||||
class NavConfigFragment : BaseFragment<FragmentSettingsSourcesBinding>(), RecyclerViewOwner,
|
||||
OnListItemClickListener<NavItem>, View.OnClickListener {
|
||||
|
||||
private var reorderHelper: ItemTouchHelper? = null
|
||||
private val viewModel by viewModels<NavConfigViewModel>()
|
||||
|
||||
override val recyclerView: RecyclerView
|
||||
get() = requireViewBinding().recyclerView
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
): FragmentSettingsSourcesBinding {
|
||||
return FragmentSettingsSourcesBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun onViewBindingCreated(
|
||||
binding: FragmentSettingsSourcesBinding,
|
||||
savedInstanceState: Bundle?,
|
||||
) {
|
||||
super.onViewBindingCreated(binding, savedInstanceState)
|
||||
val navConfigAdapter = BaseListAdapter<ListModel>()
|
||||
.addDelegate(ListItemType.NAV_ITEM, navConfigAD(this))
|
||||
.addDelegate(ListItemType.FOOTER_LOADING, navAddAD(this))
|
||||
with(binding.recyclerView) {
|
||||
setHasFixedSize(true)
|
||||
adapter = navConfigAdapter
|
||||
reorderHelper = ItemTouchHelper(ReorderCallback()).also {
|
||||
it.attachToRecyclerView(this)
|
||||
}
|
||||
}
|
||||
viewModel.content.observe(viewLifecycleOwner, navConfigAdapter)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
activity?.setTitle(R.string.main_screen_sections)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
reorderHelper = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onWindowInsetsChanged(insets: Insets) {
|
||||
requireViewBinding().recyclerView.updatePadding(
|
||||
bottom = insets.bottom,
|
||||
left = insets.left,
|
||||
right = insets.right,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
var dialog: DialogInterface? = null
|
||||
val listener = OnListItemClickListener<NavItem> { item, _ ->
|
||||
viewModel.addItem(item)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
dialog = RecyclerViewAlertDialog.Builder<NavItem>(v.context)
|
||||
.setTitle(R.string.add)
|
||||
.addAdapterDelegate(navAvailableAD(listener))
|
||||
.setCancelable(true)
|
||||
.setItems(viewModel.availableItems)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.apply { show() }
|
||||
}
|
||||
|
||||
override fun onItemClick(item: NavItem, view: View) {
|
||||
viewModel.removeItem(item)
|
||||
}
|
||||
|
||||
override fun onItemLongClick(item: NavItem, view: View): Boolean {
|
||||
val holder = viewBinding?.recyclerView?.findContainingViewHolder(view) ?: return false
|
||||
reorderHelper?.startDrag(holder)
|
||||
return true
|
||||
}
|
||||
|
||||
private inner class ReorderCallback : ItemTouchHelper.SimpleCallback(
|
||||
ItemTouchHelper.DOWN or ItemTouchHelper.UP,
|
||||
0,
|
||||
) {
|
||||
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder,
|
||||
): Boolean = true
|
||||
|
||||
override fun onMoved(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
fromPos: Int,
|
||||
target: RecyclerView.ViewHolder,
|
||||
toPos: Int,
|
||||
x: Int,
|
||||
y: Int,
|
||||
) {
|
||||
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
|
||||
viewModel.reorder(fromPos, toPos)
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit
|
||||
|
||||
override fun isLongPressDragEnabled() = false
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package org.koitharu.kotatsu.settings.nav
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.plus
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.prefs.NavItem
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.ui.util.ActivityRecreationHandle
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.main.ui.MainActivity
|
||||
import org.koitharu.kotatsu.parsers.util.move
|
||||
import org.koitharu.kotatsu.settings.nav.model.NavItemAddModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class NavConfigViewModel @Inject constructor(
|
||||
private val settings: AppSettings,
|
||||
private val activityRecreationHandle: ActivityRecreationHandle,
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val items = MutableStateFlow(settings.mainNavItems)
|
||||
|
||||
val content: StateFlow<List<ListModel>> = items.map { snapshot ->
|
||||
if (snapshot.size < NavItem.entries.size) {
|
||||
snapshot + NavItemAddModel(snapshot.size < 5)
|
||||
} else {
|
||||
snapshot
|
||||
}
|
||||
}.stateIn(
|
||||
viewModelScope + Dispatchers.Default,
|
||||
SharingStarted.WhileSubscribed(5000),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
private var commitJob: Job? = null
|
||||
|
||||
val availableItems
|
||||
get() = items.value.let { snapshot ->
|
||||
NavItem.entries.filterNot { x -> x in snapshot }
|
||||
}
|
||||
|
||||
fun reorder(fromPos: Int, toPos: Int) {
|
||||
items.value = items.value.toMutableList().apply {
|
||||
move(fromPos, toPos)
|
||||
commit(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun addItem(item: NavItem) {
|
||||
items.value = items.value.plus(item).also {
|
||||
commit(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeItem(item: NavItem) {
|
||||
items.value = items.value.minus(item).also {
|
||||
commit(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun commit(value: List<NavItem>) {
|
||||
val prevJob = commitJob
|
||||
commitJob = launchJob {
|
||||
prevJob?.cancelAndJoin()
|
||||
delay(500)
|
||||
settings.mainNavItems = value
|
||||
activityRecreationHandle.recreate(MainActivity::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package org.koitharu.kotatsu.settings.nav.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.NavItem
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.databinding.ItemNavAvailableBinding
|
||||
import org.koitharu.kotatsu.databinding.ItemNavConfigBinding
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.settings.nav.model.NavItemAddModel
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
fun navConfigAD(
|
||||
clickListener: OnListItemClickListener<NavItem>,
|
||||
) = adapterDelegateViewBinding<NavItem, ListModel, ItemNavConfigBinding>(
|
||||
{ layoutInflater, parent -> ItemNavConfigBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
val eventListener = object : View.OnClickListener, View.OnTouchListener {
|
||||
override fun onClick(v: View) = clickListener.onItemClick(item, v)
|
||||
|
||||
override fun onTouch(v: View?, event: MotionEvent): Boolean =
|
||||
event.actionMasked == MotionEvent.ACTION_DOWN &&
|
||||
clickListener.onItemLongClick(item, itemView)
|
||||
}
|
||||
binding.imageViewRemove.setOnClickListener(eventListener)
|
||||
binding.imageViewReorder.setOnTouchListener(eventListener)
|
||||
|
||||
bind {
|
||||
with(binding.textViewTitle) {
|
||||
setText(item.title)
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun navAvailableAD(
|
||||
clickListener: OnListItemClickListener<NavItem>,
|
||||
) = adapterDelegateViewBinding<NavItem, NavItem, ItemNavAvailableBinding>(
|
||||
{ layoutInflater, parent -> ItemNavAvailableBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
binding.root.setOnClickListener { v ->
|
||||
clickListener.onItemClick(item, v)
|
||||
}
|
||||
|
||||
bind {
|
||||
with(binding.root) {
|
||||
setText(item.title)
|
||||
setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun navAddAD(
|
||||
clickListener: View.OnClickListener,
|
||||
) = adapterDelegateViewBinding<NavItemAddModel, ListModel, ItemNavAvailableBinding>(
|
||||
{ layoutInflater, parent -> ItemNavAvailableBinding.inflate(layoutInflater, parent, false) },
|
||||
) {
|
||||
|
||||
binding.root.setOnClickListener(clickListener)
|
||||
binding.root.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_add, 0, 0, 0)
|
||||
|
||||
bind {
|
||||
with(binding.root) {
|
||||
setText(if (item.canAdd) R.string.add else R.string.items_limit_exceeded)
|
||||
isEnabled = item.canAdd
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.settings.nav.model
|
||||
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
|
||||
data class NavItemAddModel(
|
||||
val canAdd: Boolean,
|
||||
) : ListModel {
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean = other is NavItemAddModel
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- drawable/bookmark.xml -->
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M17,3H7A2,2 0 0,0 5,5V21L12,18L19,21V5C19,3.89 18.1,3 17,3Z" />
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/normal"
|
||||
android:drawable="@drawable/ic_bookmark"
|
||||
android:state_checked="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/checked"
|
||||
android:drawable="@drawable/ic_bookmark_checked"
|
||||
android:state_checked="true" />
|
||||
</selector>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- drawable/sd.xml -->
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M18,8H16V4H18M15,8H13V4H15M12,8H10V4H12M18,2H10L4,8V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V4A2,2 0 0,0 18,2Z" />
|
||||
</vector>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/normal"
|
||||
android:drawable="@drawable/ic_storage"
|
||||
android:state_checked="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/checked"
|
||||
android:drawable="@drawable/ic_storage_checked"
|
||||
android:state_checked="true" />
|
||||
</selector>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- drawable/lightbulb.xml -->
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M12,2A7,7 0 0,0 5,9C5,11.38 6.19,13.47 8,14.74V17A1,1 0 0,0 9,18H15A1,1 0 0,0 16,17V14.74C17.81,13.47 19,11.38 19,9A7,7 0 0,0 12,2M9,21A1,1 0 0,0 10,22H14A1,1 0 0,0 15,21V20H9V21Z" />
|
||||
</vector>
|
||||
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/normal"
|
||||
android:drawable="@drawable/ic_suggestion"
|
||||
android:state_checked="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/checked"
|
||||
android:drawable="@drawable/ic_suggestion_checked"
|
||||
android:state_checked="true" />
|
||||
</selector>
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView
|
||||
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"
|
||||
android:background="?selectableItemBackground"
|
||||
android:drawablePadding="?listPreferredItemPaddingStart"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:listPreferredItemHeightSmall"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="@dimen/margin_small"
|
||||
android:paddingStart="?listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
tools:drawableStartCompat="@drawable/ic_feed"
|
||||
tools:text="@string/feed" />
|
||||
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:windowBackground"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="@dimen/margin_small"
|
||||
android:paddingStart="?listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?listPreferredItemPaddingEnd">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="?listPreferredItemPaddingStart"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
tools:drawableStart="@drawable/ic_explore_selector"
|
||||
tools:text="@string/explore" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView_remove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/remove"
|
||||
android:padding="@dimen/margin_small"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_delete" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView_reorder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/reorder"
|
||||
android:padding="@dimen/margin_small"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_reorder_handle" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_history"
|
||||
android:icon="@drawable/ic_history_selector"
|
||||
android:title="@string/history" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_favourites"
|
||||
android:icon="@drawable/ic_favourites_selector"
|
||||
android:title="@string/favourites" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_explore"
|
||||
android:icon="@drawable/ic_explore_selector"
|
||||
android:title="@string/explore" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_feed"
|
||||
android:icon="@drawable/ic_feed_selector"
|
||||
android:title="@string/feed" />
|
||||
|
||||
</menu>
|
||||
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_favourites"
|
||||
android:icon="@drawable/ic_favourites_selector"
|
||||
android:title="@string/favourites" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_history"
|
||||
android:icon="@drawable/ic_history_selector"
|
||||
android:title="@string/history" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_explore"
|
||||
android:icon="@drawable/ic_explore_selector"
|
||||
android:title="@string/explore" />
|
||||
|
||||
<item
|
||||
android:id="@+id/nav_feed"
|
||||
android:icon="@drawable/ic_feed_selector"
|
||||
android:title="@string/feed" />
|
||||
|
||||
</menu>
|
||||
Loading…
Reference in New Issue