Some UI fixes

pull/1/head
Koitharu 6 years ago
parent faf8e57619
commit 315aea8b5c

@ -32,7 +32,9 @@ class LocalMangaRepository(loaderContext: MangaLoaderContext) : BaseMangaReposit
return files.mapNotNull { x -> safe { getDetails(x) } } return files.mapNotNull { x -> safe { getDetails(x) } }
} }
override suspend fun getDetails(manga: Manga) = manga override suspend fun getDetails(manga: Manga) = if (manga.chapters == null) {
getDetails(Uri.parse(manga.url).toFile())
} else manga
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> { override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val file = Uri.parse(chapter.url).toFile() val file = Uri.parse(chapter.url).toFile()
@ -44,7 +46,7 @@ class LocalMangaRepository(loaderContext: MangaLoaderContext) : BaseMangaReposit
.filter { x -> !x.isDirectory && x.name.substringBefore('.').matches(pattern) } .filter { x -> !x.isDirectory && x.name.substringBefore('.').matches(pattern) }
} else { } else {
zip.entries().asSequence().filter { x -> !x.isDirectory } zip.entries().asSequence().filter { x -> !x.isDirectory }
}.toList().sortedWith(compareBy(AlphanumComparator()) { x -> x.name}) }.toList().sortedWith(compareBy(AlphanumComparator()) { x -> x.name })
return entries.map { x -> return entries.map { x ->
val uri = zipUri(file, x.name) val uri = zipUri(file, x.name)
MangaPage( MangaPage(

@ -1,5 +1,7 @@
package org.koitharu.kotatsu.domain.favourites package org.koitharu.kotatsu.domain.favourites
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
import org.koin.core.inject import org.koin.core.inject
import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.MangaDatabase
@ -9,6 +11,7 @@ import org.koitharu.kotatsu.core.db.entity.MangaEntity
import org.koitharu.kotatsu.core.db.entity.TagEntity import org.koitharu.kotatsu.core.db.entity.TagEntity
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import java.util.*
class FavouritesRepository : KoinComponent { class FavouritesRepository : KoinComponent {
@ -49,9 +52,30 @@ class FavouritesRepository : KoinComponent {
db.mangaDao().upsert(MangaEntity.from(manga), tags) db.mangaDao().upsert(MangaEntity.from(manga), tags)
val entity = FavouriteEntity(manga.id, categoryId, System.currentTimeMillis()) val entity = FavouriteEntity(manga.id, categoryId, System.currentTimeMillis())
db.favouritesDao().add(entity) db.favouritesDao().add(entity)
notifyFavouritesChanged(manga.id)
} }
suspend fun removeFromCategory(manga: Manga, categoryId: Long) { suspend fun removeFromCategory(manga: Manga, categoryId: Long) {
db.favouritesDao().delete(categoryId, manga.id) db.favouritesDao().delete(categoryId, manga.id)
notifyFavouritesChanged(manga.id)
}
companion object {
private val listeners = HashSet<OnFavouritesChangeListener>()
fun subscribe(listener: OnFavouritesChangeListener) {
listeners += listener
}
fun unsubscribe(listener: OnFavouritesChangeListener) {
listeners += listener
}
private suspend fun notifyFavouritesChanged(mangaId: Long) {
withContext(Dispatchers.Main) {
listeners.forEach { x -> x.onFavouritesChanged(mangaId) }
}
}
} }
} }

@ -0,0 +1,6 @@
package org.koitharu.kotatsu.domain.favourites
interface OnFavouritesChangeListener {
fun onFavouritesChanged(mangaId: Long)
}

@ -1,24 +1,21 @@
package org.koitharu.kotatsu.ui.common package org.koitharu.kotatsu.ui.common
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.WindowManager
abstract class BaseFullscreenActivity : BaseActivity() { abstract class BaseFullscreenActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
window.decorView.setOnSystemUiVisibilityChangeListener { visibility -> with(window) {
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) { addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
onSystemUiShown() statusBarColor = Color.TRANSPARENT
} else { navigationBarColor = Color.TRANSPARENT
onSystemUiHidden()
}
} }
} showSystemUI()
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) hideSystemUI()
} }
protected fun hideSystemUI() { protected fun hideSystemUI() {
@ -28,6 +25,7 @@ abstract class BaseFullscreenActivity : BaseActivity() {
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN) or View.SYSTEM_UI_FLAG_FULLSCREEN)
} }
protected fun showSystemUI() { protected fun showSystemUI() {
@ -35,8 +33,4 @@ abstract class BaseFullscreenActivity : BaseActivity() {
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
} }
protected open fun onSystemUiShown() = Unit
protected open fun onSystemUiHidden() = Unit
} }

@ -4,11 +4,12 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.dialog_input.view.* import kotlinx.android.synthetic.main.dialog_input.view.*
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.ext.hideKeyboard
import org.koitharu.kotatsu.utils.ext.showKeyboard import org.koitharu.kotatsu.utils.ext.showKeyboard
class TextInputDialog private constructor(private val delegate: AlertDialog) : class TextInputDialog private constructor(private val delegate: AlertDialog) :
@ -16,7 +17,11 @@ class TextInputDialog private constructor(private val delegate: AlertDialog) :
init { init {
delegate.setOnShowListener { delegate.setOnShowListener {
delegate.currentFocus?.showKeyboard() val view = delegate.findViewById<TextView>(R.id.inputEdit)?:return@setOnShowListener
view.post {
view.requestFocus()
view.showKeyboard()
}
} }
} }
@ -29,6 +34,10 @@ class TextInputDialog private constructor(private val delegate: AlertDialog) :
private val delegate = AlertDialog.Builder(context) private val delegate = AlertDialog.Builder(context)
.setView(view) .setView(view)
.setOnDismissListener {
val imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
}
fun setTitle(@StringRes titleResId: Int): Builder { fun setTitle(@StringRes titleResId: Int): Builder {
delegate.setTitle(titleResId) delegate.setTitle(titleResId)
@ -52,7 +61,6 @@ class TextInputDialog private constructor(private val delegate: AlertDialog) :
fun setPositiveButton(@StringRes textId: Int, listener: (DialogInterface, String) -> Unit): Builder { fun setPositiveButton(@StringRes textId: Int, listener: (DialogInterface, String) -> Unit): Builder {
delegate.setPositiveButton(textId) { dialog, _ -> delegate.setPositiveButton(textId) { dialog, _ ->
view.hideKeyboard()
listener(dialog, view.inputEdit.text?.toString().orEmpty()) listener(dialog, view.inputEdit.text?.toString().orEmpty())
} }
return this return this

@ -8,6 +8,7 @@ import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_chapters.* import kotlinx.android.synthetic.main.fragment_chapters.*
import moxy.ktx.moxyPresenter import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaChapter import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaHistory
@ -56,6 +57,8 @@ class ChaptersFragment : BaseFragment(R.layout.fragment_chapters), MangaDetailsV
adapter.currentChapterId = history?.chapterId adapter.currentChapterId = history?.chapterId
} }
override fun onFavouriteChanged(categories: List<FavouriteCategory>) = Unit
override fun onItemClick(item: MangaChapter, position: Int, view: View) { override fun onItemClick(item: MangaChapter, position: Int, view: View) {
startActivity( startActivity(
ReaderActivity.newIntent( ReaderActivity.newIntent(

@ -11,6 +11,7 @@ import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_details.* import kotlinx.android.synthetic.main.activity_details.*
import moxy.ktx.moxyPresenter import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.model.MangaSource
@ -44,6 +45,8 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
override fun onHistoryChanged(history: MangaHistory?) = Unit override fun onHistoryChanged(history: MangaHistory?) = Unit
override fun onFavouriteChanged(categories: List<FavouriteCategory>) = Unit
override fun onLoadingStateChanged(isLoading: Boolean) = Unit override fun onLoadingStateChanged(isLoading: Boolean) = Unit
override fun onError(e: Exception) { override fun onError(e: Exception) {

@ -6,6 +6,7 @@ import coil.api.load
import kotlinx.android.synthetic.main.fragment_details.* import kotlinx.android.synthetic.main.fragment_details.*
import moxy.ktx.moxyPresenter import moxy.ktx.moxyPresenter
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.ui.common.BaseFragment import org.koitharu.kotatsu.ui.common.BaseFragment
@ -52,6 +53,16 @@ class MangaDetailsFragment : BaseFragment(R.layout.fragment_details), MangaDetai
updateReadButton() updateReadButton()
} }
override fun onFavouriteChanged(categories: List<FavouriteCategory>) {
imageView_favourite.setImageResource(
if (categories.isEmpty()) {
R.drawable.ic_tag_heart_outline
} else {
R.drawable.ic_tag_heart
}
)
}
override fun onLoadingStateChanged(isLoading: Boolean) { override fun onLoadingStateChanged(isLoading: Boolean) {
progressBar.isVisible = isLoading progressBar.isVisible = isLoading
} }

@ -7,21 +7,27 @@ import moxy.InjectViewState
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.domain.MangaProviderFactory import org.koitharu.kotatsu.domain.MangaProviderFactory
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
import org.koitharu.kotatsu.domain.history.HistoryRepository import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener
import org.koitharu.kotatsu.ui.common.BasePresenter import org.koitharu.kotatsu.ui.common.BasePresenter
@InjectViewState @InjectViewState
class MangaDetailsPresenter : BasePresenter<MangaDetailsView>(), OnHistoryChangeListener { class MangaDetailsPresenter : BasePresenter<MangaDetailsView>(), OnHistoryChangeListener,
OnFavouritesChangeListener {
private lateinit var historyRepository: HistoryRepository private lateinit var historyRepository: HistoryRepository
private lateinit var favouritesRepository: FavouritesRepository
private var manga: Manga? = null private var manga: Manga? = null
override fun onFirstViewAttach() { override fun onFirstViewAttach() {
historyRepository = HistoryRepository() historyRepository = HistoryRepository()
favouritesRepository = FavouritesRepository()
super.onFirstViewAttach() super.onFirstViewAttach()
HistoryRepository.subscribe(this) HistoryRepository.subscribe(this)
FavouritesRepository.subscribe(this)
} }
fun loadDetails(manga: Manga, force: Boolean = false) { fun loadDetails(manga: Manga, force: Boolean = false) {
@ -30,6 +36,7 @@ class MangaDetailsPresenter : BasePresenter<MangaDetailsView>(), OnHistoryChange
} }
loadHistory(manga) loadHistory(manga)
viewState.onMangaUpdated(manga) viewState.onMangaUpdated(manga)
loadFavourite(manga)
launch { launch {
try { try {
viewState.onLoadingStateChanged(true) viewState.onLoadingStateChanged(true)
@ -64,12 +71,34 @@ class MangaDetailsPresenter : BasePresenter<MangaDetailsView>(), OnHistoryChange
} }
} }
private fun loadFavourite(manga: Manga) {
launch {
try {
val categories = withContext(Dispatchers.IO) {
favouritesRepository.getCategories(manga.id)
}
viewState.onFavouriteChanged(categories)
} catch (e: Exception) {
if (BuildConfig.DEBUG) {
e.printStackTrace()
}
}
}
}
override fun onHistoryChanged() { override fun onHistoryChanged() {
loadHistory(manga ?: return) loadHistory(manga ?: return)
} }
override fun onFavouritesChanged(mangaId: Long) {
if (mangaId == manga?.id) {
loadFavourite(manga!!)
}
}
override fun onDestroy() { override fun onDestroy() {
HistoryRepository.unsubscribe(this) HistoryRepository.unsubscribe(this)
FavouritesRepository.unsubscribe(this)
super.onDestroy() super.onDestroy()
} }
} }

@ -4,6 +4,7 @@ import moxy.MvpView
import moxy.viewstate.strategy.AddToEndSingleStrategy import moxy.viewstate.strategy.AddToEndSingleStrategy
import moxy.viewstate.strategy.OneExecutionStateStrategy import moxy.viewstate.strategy.OneExecutionStateStrategy
import moxy.viewstate.strategy.StateStrategyType import moxy.viewstate.strategy.StateStrategyType
import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaHistory import org.koitharu.kotatsu.core.model.MangaHistory
@ -20,4 +21,7 @@ interface MangaDetailsView : MvpView {
@StateStrategyType(AddToEndSingleStrategy::class) @StateStrategyType(AddToEndSingleStrategy::class)
fun onHistoryChanged(history: MangaHistory?) fun onHistoryChanged(history: MangaHistory?)
@StateStrategyType(AddToEndSingleStrategy::class)
fun onFavouriteChanged(categories: List<FavouriteCategory>)
} }

@ -6,8 +6,8 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.MotionEvent import android.view.MotionEvent
import android.widget.Button
import android.widget.Toast import android.widget.Toast
import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.*
@ -18,6 +18,8 @@ import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.ui.common.BaseFullscreenActivity import org.koitharu.kotatsu.ui.common.BaseFullscreenActivity
import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.GridTouchHelper
import org.koitharu.kotatsu.utils.ext.hasGlobalPoint
import org.koitharu.kotatsu.utils.ext.hitTest
import org.koitharu.kotatsu.utils.ext.showDialog import org.koitharu.kotatsu.utils.ext.showDialog
class ReaderActivity : BaseFullscreenActivity(), ReaderView, GridTouchHelper.OnGridTouchListener { class ReaderActivity : BaseFullscreenActivity(), ReaderView, GridTouchHelper.OnGridTouchListener {
@ -107,25 +109,17 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, GridTouchHelper.OnG
} }
} }
override fun onSystemUiShown() {
appbar_top.isGone = true
appbar_bottom.isGone = true
}
override fun onSystemUiHidden() {
appbar_top.isGone = false
appbar_bottom.isGone = false
}
override fun onGridTouch(area: Int) { override fun onGridTouch(area: Int) {
when (area) { when (area) {
GridTouchHelper.AREA_CENTER -> { GridTouchHelper.AREA_CENTER -> {
if (appbar_top.isVisible) { if (appbar_top.isVisible) {
appbar_top.isVisible = false appbar_top.isVisible = false
appbar_bottom.isVisible = false appbar_bottom.isVisible = false
hideSystemUI()
} else { } else {
appbar_top.isVisible = true appbar_top.isVisible = true
appbar_bottom.isVisible = true appbar_bottom.isVisible = true
showSystemUI()
} }
} }
GridTouchHelper.AREA_TOP, GridTouchHelper.AREA_TOP,
@ -139,6 +133,15 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, GridTouchHelper.OnG
} }
} }
override fun onProcessTouch(rawX: Int, rawY: Int): Boolean {
return if (appbar_top.hasGlobalPoint(rawX, rawY) || appbar_bottom.hasGlobalPoint(rawX, rawY)) {
false
} else {
val target = rootLayout.hitTest(rawX, rawY)
target !is Button
}
}
override fun dispatchTouchEvent(ev: MotionEvent): Boolean { override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
touchHelper.dispatchTouchEvent(ev) touchHelper.dispatchTouchEvent(ev)
return super.dispatchTouchEvent(ev) return super.dispatchTouchEvent(ev)

@ -22,6 +22,9 @@ class GridTouchHelper(context: Context, private val listener: OnGridTouchListene
} }
override fun onSingleTapConfirmed(event: MotionEvent): Boolean { override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
if (!listener.onProcessTouch(event.rawX.toInt(), event.rawY.toInt())) {
return false
}
val xIndex = (event.rawX * 2f / width).roundToInt() val xIndex = (event.rawX * 2f / width).roundToInt()
val yIndex = (event.rawY * 2f / height).roundToInt() val yIndex = (event.rawY * 2f / height).roundToInt()
listener.onGridTouch( listener.onGridTouch(
@ -54,5 +57,7 @@ class GridTouchHelper(context: Context, private val listener: OnGridTouchListene
interface OnGridTouchListener { interface OnGridTouchListener {
fun onGridTouch(area: Int) fun onGridTouch(area: Int)
fun onProcessTouch(rawX: Int, rawY: Int): Boolean
} }
} }

@ -1,17 +1,16 @@
package org.koitharu.kotatsu.utils.ext package org.koitharu.kotatsu.utils.ext
import android.app.Activity import android.app.Activity
import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.LayoutInflater import android.view.*
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.EditText import android.widget.EditText
import android.widget.TextView import android.widget.TextView
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.annotation.MenuRes import androidx.annotation.MenuRes
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.view.children
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@ -101,9 +100,35 @@ fun View.disableFor(timeInMillis: Long) {
} }
} }
fun View.showPopupMenu(@MenuRes menuRes: Int, onItemClick: (MenuItem) -> Boolean) { fun View.showPopupMenu(@MenuRes menuRes: Int, onPrepare:((Menu) -> Unit)? = null, onItemClick: (MenuItem) -> Boolean) {
val menu = PopupMenu(context, this) val menu = PopupMenu(context, this)
menu.inflate(menuRes) menu.inflate(menuRes)
menu.setOnMenuItemClickListener(onItemClick) menu.setOnMenuItemClickListener(onItemClick)
onPrepare?.invoke(menu.menu)
menu.show() menu.show()
} }
fun ViewGroup.hitTest(x: Int, y: Int): View? {
val rect = Rect()
for (child in children) {
if (child.getGlobalVisibleRect(rect)) {
if (rect.contains(x, y)) {
return if (child is ViewGroup) {
child.hitTest(x, y)
} else {
child
}
}
}
}
return null
}
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
if (visibility != View.VISIBLE) {
return false
}
val rect = Rect()
getGlobalVisibleRect(rect)
return rect.contains(x, y)
}

@ -0,0 +1,11 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<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="#000"
android:pathData="M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4A2,2 0 0,0 2,4V11C2,11.55 2.22,12.05 2.59,12.42L11.59,21.42C11.95,21.78 12.45,22 13,22C13.55,22 14.05,21.78 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.45 21.77,11.94 21.41,11.58M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M17.27,15.27L13,19.54L8.73,15.27C8.28,14.81 8,14.19 8,13.5A2.5,2.5 0 0,1 10.5,11C11.19,11 11.82,11.28 12.27,11.74L13,12.46L13.73,11.73C14.18,11.28 14.81,11 15.5,11A2.5,2.5 0 0,1 18,13.5C18,14.19 17.72,14.82 17.27,15.27Z" />
</vector>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<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="#000"
android:pathData="M4,2A2,2 0 0,0 2,4V11C2,11.55 2.22,12.05 2.59,12.42L11.59,21.42C11.95,21.78 12.45,22 13,22C13.55,22 14.05,21.78 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.45 21.77,11.94 21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4V2M11,4L20,13L13,20L4,11V4H11V4H11M6.5,5A1.5,1.5 0 0,0 5,6.5A1.5,1.5 0 0,0 6.5,8A1.5,1.5 0 0,0 8,6.5A1.5,1.5 0 0,0 6.5,5M10.95,10.5C9.82,10.5 8.9,11.42 8.9,12.55C8.9,13.12 9.13,13.62 9.5,14L13,17.5L16.5,14C16.87,13.63 17.1,13.11 17.1,12.55A2.05,2.05 0 0,0 15.05,10.5C14.5,10.5 13.97,10.73 13.6,11.1L13,11.7L12.4,11.11C12.03,10.73 11.5,10.5 10.95,10.5Z" />
</vector>

@ -3,18 +3,23 @@
xmlns:android="http://schemas.android.com/apk/res/android" 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingTop="12dp" android:paddingTop="12dp">
<View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="1dp"
android:background="?android:listDivider" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView_categories" android:id="@+id/recyclerView_categories"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:scrollbars="vertical" android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_caegory_checkable" /> tools:listitem="@layout/item_caegory_checkable" />
<View <View
@ -27,11 +32,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall" android:layout_height="?android:listPreferredItemHeightSmall"
android:background="?android:selectableItemBackground" android:background="?android:selectableItemBackground"
android:drawableEnd="@drawable/ic_add"
android:gravity="start|center_vertical" android:gravity="start|center_vertical"
android:paddingStart="?android:listPreferredItemPaddingStart" android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd" android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:text="@string/add_new_category"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary" />
android:text="@string/add_new_category" />
</LinearLayout> </LinearLayout>

@ -84,8 +84,8 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/add_to_favourites" android:contentDescription="@string/add_to_favourites"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_favourites" android:src="@drawable/ic_tag_heart_outline"
android:tint="?colorAccent" app:tint="?colorAccent"
app:layout_constraintBottom_toBottomOf="@id/button_read" app:layout_constraintBottom_toBottomOf="@id/button_read"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@id/button_read" app:layout_constraintEnd_toStartOf="@id/button_read"

Loading…
Cancel
Save