更新界面
This commit is contained in:
@@ -5,6 +5,7 @@ import android.graphics.Canvas
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.graphics.Typeface
|
||||||
import android.text.TextPaint
|
import android.text.TextPaint
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@@ -28,10 +29,11 @@ class BookmarkDecoration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val textPaint = TextPaint().apply {
|
private val textPaint = TextPaint().apply {
|
||||||
textSize = 16f.spToPx()
|
textSize = 14f.spToPx()
|
||||||
color =
|
color =
|
||||||
MaterialColors.getColor(context, androidx.appcompat.R.attr.colorPrimary, Color.BLACK)
|
MaterialColors.getColor(context, androidx.appcompat.R.attr.colorPrimary, Color.BLACK)
|
||||||
isAntiAlias = true
|
isAntiAlias = true
|
||||||
|
typeface = Typeface.DEFAULT_BOLD
|
||||||
}
|
}
|
||||||
|
|
||||||
private val textRect = Rect()
|
private val textRect = Rect()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.net.Uri
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
|
import android.view.HapticFeedbackConstants
|
||||||
import android.view.InputDevice
|
import android.view.InputDevice
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
@@ -788,21 +789,25 @@ class ReadBookActivity : BaseReadBookActivity(),
|
|||||||
/**
|
/**
|
||||||
* 更新文字选择开始位置
|
* 更新文字选择开始位置
|
||||||
*/
|
*/
|
||||||
override fun upSelectedStart(x: Float, y: Float, top: Float) = binding.run {
|
override fun upSelectedStart(x: Float, y: Float, top: Float): Unit = binding.run {
|
||||||
cursorLeft.x = x - cursorLeft.width
|
cursorLeft.x = x - cursorLeft.width
|
||||||
cursorLeft.y = y
|
cursorLeft.y = y
|
||||||
cursorLeft.visible(true)
|
cursorLeft.visible(true)
|
||||||
textMenuPosition.x = x
|
textMenuPosition.x = x
|
||||||
textMenuPosition.y = top
|
textMenuPosition.y = top
|
||||||
|
|
||||||
|
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新文字选择结束位置
|
* 更新文字选择结束位置
|
||||||
*/
|
*/
|
||||||
override fun upSelectedEnd(x: Float, y: Float) = binding.run {
|
override fun upSelectedEnd(x: Float, y: Float): Unit = binding.run {
|
||||||
cursorRight.x = x
|
cursorRight.x = x
|
||||||
cursorRight.y = y
|
cursorRight.y = y
|
||||||
cursorRight.visible(true)
|
cursorRight.visible(true)
|
||||||
|
|
||||||
|
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ class BookmarkAdapter(context: Context, val callback: Callback) :
|
|||||||
override fun registerListener(holder: ItemViewHolder, binding: ItemBookmarkBinding) {
|
override fun registerListener(holder: ItemViewHolder, binding: ItemBookmarkBinding) {
|
||||||
binding.root.setOnClickListener {
|
binding.root.setOnClickListener {
|
||||||
getItem(holder.layoutPosition)?.let { bookmark ->
|
getItem(holder.layoutPosition)?.let { bookmark ->
|
||||||
callback.onClick(bookmark)
|
callback.onLongClick(bookmark, holder.layoutPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.root.onLongClick {
|
binding.root.onLongClick {
|
||||||
getItem(holder.layoutPosition)?.let { bookmark ->
|
getItem(holder.layoutPosition)?.let { bookmark ->
|
||||||
callback.onLongClick(bookmark, holder.layoutPosition)
|
callback.onClick(bookmark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import io.legato.kazusa.ui.widget.recycler.VerticalDivider
|
|||||||
import io.legato.kazusa.utils.applyNavigationBarPadding
|
import io.legato.kazusa.utils.applyNavigationBarPadding
|
||||||
import io.legato.kazusa.utils.showDialogFragment
|
import io.legato.kazusa.utils.showDialogFragment
|
||||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||||
|
import io.legato.kazusa.utils.visible
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
@@ -51,24 +52,27 @@ class BookmarkFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_bookmark
|
|||||||
binding.recyclerView.addItemDecoration(VerticalDivider(requireContext()))
|
binding.recyclerView.addItemDecoration(VerticalDivider(requireContext()))
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
binding.recyclerView.applyNavigationBarPadding()
|
binding.recyclerView.applyNavigationBarPadding()
|
||||||
|
|
||||||
|
binding.tvEmptyMsg.visible(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun upBookmark(searchKey: String?) {
|
override fun upBookmark(searchKey: String?) {
|
||||||
val book = viewModel.bookData.value ?: return
|
val book = viewModel.bookData.value ?: return
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
when {
|
val flow = when {
|
||||||
searchKey.isNullOrBlank() -> appDb.bookmarkDao.flowByBook(book.name, book.author)
|
searchKey.isNullOrBlank() -> appDb.bookmarkDao.flowByBook(book.name, book.author)
|
||||||
else -> appDb.bookmarkDao.flowSearch(book.name, book.author, searchKey)
|
else -> appDb.bookmarkDao.flowSearch(book.name, book.author, searchKey)
|
||||||
}.catch {
|
}
|
||||||
|
|
||||||
|
flow.catch {
|
||||||
AppLog.put("目录界面获取书签数据失败\n${it.localizedMessage}", it)
|
AppLog.put("目录界面获取书签数据失败\n${it.localizedMessage}", it)
|
||||||
}.flowOn(IO).collect {
|
}.flowOn(IO).collect { list ->
|
||||||
adapter.setItems(it)
|
adapter.setItems(list)
|
||||||
|
binding.tvEmptyMsg.visible(list.isEmpty())
|
||||||
var scrollPos = 0
|
var scrollPos = 0
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
adapter.getItems().forEachIndexed { index, bookmark ->
|
adapter.getItems().forEachIndexed { index, bookmark ->
|
||||||
if (bookmark.chapterIndex >= durChapterIndex) {
|
if (bookmark.chapterIndex >= durChapterIndex) return@withContext
|
||||||
return@withContext
|
|
||||||
}
|
|
||||||
scrollPos = index
|
scrollPos = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,17 @@ import io.legato.kazusa.data.entities.BookChapter
|
|||||||
import io.legato.kazusa.databinding.ItemChapterListBinding
|
import io.legato.kazusa.databinding.ItemChapterListBinding
|
||||||
import io.legato.kazusa.help.book.ContentProcessor
|
import io.legato.kazusa.help.book.ContentProcessor
|
||||||
import io.legato.kazusa.help.config.AppConfig
|
import io.legato.kazusa.help.config.AppConfig
|
||||||
import io.legato.kazusa.help.coroutine.Coroutine
|
|
||||||
import io.legato.kazusa.lib.theme.ThemeUtils
|
import io.legato.kazusa.lib.theme.ThemeUtils
|
||||||
import io.legato.kazusa.utils.gone
|
import io.legato.kazusa.utils.gone
|
||||||
import io.legato.kazusa.utils.longToastOnUi
|
import io.legato.kazusa.utils.longToastOnUi
|
||||||
import io.legato.kazusa.utils.themeColor
|
import io.legato.kazusa.utils.themeColor
|
||||||
import io.legato.kazusa.utils.visible
|
import io.legato.kazusa.utils.visible
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
class ChapterListAdapter(context: Context, val callback: Callback) :
|
class ChapterListAdapter(context: Context, val callback: Callback) :
|
||||||
@@ -30,6 +32,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
|
|
||||||
val cacheFileNames = hashSetOf<String>()
|
val cacheFileNames = hashSetOf<String>()
|
||||||
private val displayTitleMap = ConcurrentHashMap<String, String>()
|
private val displayTitleMap = ConcurrentHashMap<String, String>()
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
override val diffItemCallback: DiffUtil.ItemCallback<BookChapter>
|
override val diffItemCallback: DiffUtil.ItemCallback<BookChapter>
|
||||||
@@ -58,7 +61,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var upDisplayTileJob: Coroutine<*>? = null
|
private var upDisplayTileJob: Job? = null
|
||||||
|
|
||||||
override fun onCurrentListChanged() {
|
override fun onCurrentListChanged() {
|
||||||
super.onCurrentListChanged()
|
super.onCurrentListChanged()
|
||||||
@@ -72,41 +75,30 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
|
|
||||||
fun upDisplayTitles(startIndex: Int) {
|
fun upDisplayTitles(startIndex: Int) {
|
||||||
upDisplayTileJob?.cancel()
|
upDisplayTileJob?.cancel()
|
||||||
upDisplayTileJob = Coroutine.async(callback.scope) {
|
upDisplayTileJob = callback.scope.launch(Dispatchers.Default) {
|
||||||
val book = callback.book ?: return@async
|
val book = callback.book ?: return@launch
|
||||||
val replaceRules = ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
|
val replaceRules = ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
|
||||||
val useReplace = AppConfig.tocUiUseReplace && book.getUseReplaceRule()
|
val useReplace = AppConfig.tocUiUseReplace && book.getUseReplaceRule()
|
||||||
val items = getItems()
|
val items = getItems()
|
||||||
launch {
|
|
||||||
for (i in startIndex until items.size) {
|
val indices = (startIndex until items.size) + (startIndex downTo 0)
|
||||||
|
|
||||||
|
for (i in indices) {
|
||||||
val item = items[i]
|
val item = items[i]
|
||||||
if (displayTitleMap[item.title] == null) {
|
val key = item.url
|
||||||
|
if (displayTitleMap[key] == null) {
|
||||||
ensureActive()
|
ensureActive()
|
||||||
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
|
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
|
||||||
|
displayTitleMap[key] = displayTitle
|
||||||
ensureActive()
|
ensureActive()
|
||||||
displayTitleMap[item.title] = displayTitle
|
withContext(Dispatchers.Main) {
|
||||||
handler.post {
|
|
||||||
notifyItemChanged(i, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
launch {
|
|
||||||
for (i in startIndex downTo 0) {
|
|
||||||
val item = items[i]
|
|
||||||
if (displayTitleMap[item.title] == null) {
|
|
||||||
ensureActive()
|
|
||||||
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
|
|
||||||
ensureActive()
|
|
||||||
displayTitleMap[item.title] = displayTitle
|
|
||||||
handler.post {
|
|
||||||
notifyItemChanged(i, true)
|
notifyItemChanged(i, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDisplayTitle(chapter: BookChapter): String {
|
private fun getDisplayTitle(chapter: BookChapter): String {
|
||||||
return displayTitleMap[chapter.title] ?: chapter.title
|
return displayTitleMap[chapter.title] ?: chapter.title
|
||||||
@@ -128,6 +120,14 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
|| item.isVolume
|
|| item.isVolume
|
||||||
|| cacheFileNames.contains(item.getFileName())
|
|| cacheFileNames.contains(item.getFileName())
|
||||||
if (payloads.isEmpty()) {
|
if (payloads.isEmpty()) {
|
||||||
|
|
||||||
|
if (item.isVolume) {
|
||||||
|
ivVolume.visible()
|
||||||
|
tvChapterName.text = getDisplayTitle(item)
|
||||||
|
tvChapterName.textSize = 12f
|
||||||
|
tvChapterName.setTextColor(context.themeColor(com.google.android.material.R.attr.colorTertiary))
|
||||||
|
} else {
|
||||||
|
ivVolume.gone()
|
||||||
if (isDur) {
|
if (isDur) {
|
||||||
tvChapterName.setTextColor(context.themeColor(androidx.appcompat.R.attr.colorPrimary))
|
tvChapterName.setTextColor(context.themeColor(androidx.appcompat.R.attr.colorPrimary))
|
||||||
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
|
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
|
||||||
@@ -136,9 +136,6 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurface))
|
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurface))
|
||||||
}
|
}
|
||||||
tvChapterName.text = getDisplayTitle(item)
|
tvChapterName.text = getDisplayTitle(item)
|
||||||
if (item.isVolume) {
|
|
||||||
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSecondaryContainer))
|
|
||||||
} else {
|
|
||||||
tvChapterItem.foreground =
|
tvChapterItem.foreground =
|
||||||
ThemeUtils.resolveDrawable(context, android.R.attr.selectableItemBackground)
|
ThemeUtils.resolveDrawable(context, android.R.attr.selectableItemBackground)
|
||||||
}
|
}
|
||||||
@@ -165,10 +162,10 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
ivLocked.gone()
|
ivLocked.gone()
|
||||||
}
|
}
|
||||||
|
|
||||||
upHasCache(binding, isDur, cached)
|
upHasCache(binding, cached)
|
||||||
} else {
|
} else {
|
||||||
tvChapterName.text = getDisplayTitle(item)
|
tvChapterName.text = getDisplayTitle(item)
|
||||||
upHasCache(binding, isDur, cached)
|
upHasCache(binding, cached)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,12 +184,11 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun upHasCache(binding: ItemChapterListBinding, isDur: Boolean, cached: Boolean) =
|
private fun upHasCache(binding: ItemChapterListBinding, cached: Boolean) =
|
||||||
binding.apply {
|
binding.apply {
|
||||||
when {
|
when {
|
||||||
isDur -> ivChecked.gone()
|
|
||||||
cached -> {
|
cached -> {
|
||||||
ivChecked.setImageResource(R.drawable.ic_check)
|
ivChecked.setImageResource(R.drawable.ic_download_done)
|
||||||
ivChecked.visible()
|
ivChecked.visible()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package io.legato.kazusa.ui.book.toc
|
package io.legato.kazusa.ui.book.toc
|
||||||
|
|
||||||
//import io.legado.app.lib.theme.bottomBackground
|
|
||||||
//import io.legado.app.lib.theme.getPrimaryTextColor
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity.RESULT_OK
|
import android.app.Activity.RESULT_OK
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -36,7 +34,6 @@ import io.legato.kazusa.utils.themeColor
|
|||||||
import io.legato.kazusa.utils.toastOnUi
|
import io.legato.kazusa.utils.toastOnUi
|
||||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers.Default
|
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -79,7 +76,7 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
|
|||||||
|
|
||||||
toastOnUi("开始下载: ${adapter.getItem(position)?.title}")
|
toastOnUi("开始下载: ${adapter.getItem(position)?.title}")
|
||||||
CacheBook.start(requireContext(), book, chapter.index, chapter.index)
|
CacheBook.start(requireContext(), book, chapter.index, chapter.index)
|
||||||
VibrationUtils.vibrate(context!!, 100)
|
VibrationUtils.vibratePattern(requireContext(), longArrayOf(0, 50, 30, 50), -1)
|
||||||
adapter.notifyItemChanged(position)
|
adapter.notifyItemChanged(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,21 +188,16 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
|
|||||||
override fun observeLiveBus() {
|
override fun observeLiveBus() {
|
||||||
observeEvent<Pair<Book, BookChapter>>(EventBus.SAVE_CONTENT) { (book, chapter) ->
|
observeEvent<Pair<Book, BookChapter>>(EventBus.SAVE_CONTENT) { (book, chapter) ->
|
||||||
viewModel.bookData.value?.bookUrl?.let { bookUrl ->
|
viewModel.bookData.value?.bookUrl?.let { bookUrl ->
|
||||||
if (book.bookUrl == bookUrl) {
|
if (book.bookUrl == viewModel.bookData.value?.bookUrl) {
|
||||||
adapter.cacheFileNames.add(chapter.getFileName())
|
adapter.cacheFileNames.add(chapter.getFileName())
|
||||||
if (viewModel.searchKey.isNullOrEmpty()) {
|
val index = adapter.getItems().indexOfFirst { it.index == chapter.index }
|
||||||
adapter.notifyItemChanged(chapter.index, true)
|
if (index >= 0) {
|
||||||
} else {
|
|
||||||
adapter.getItems().forEachIndexed { index, bookChapter ->
|
|
||||||
if (bookChapter.index == chapter.index) {
|
|
||||||
adapter.notifyItemChanged(index, true)
|
adapter.notifyItemChanged(index, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun upChapterList(searchKey: String?) {
|
override fun upChapterList(searchKey: String?) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@@ -225,15 +217,9 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
|
|||||||
|
|
||||||
override fun onListChanged() {
|
override fun onListChanged() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
var scrollPos = 0
|
val scrollPos = adapter.getItems()
|
||||||
withContext(Default) {
|
.indexOfLast { it.index < durChapterIndex }
|
||||||
adapter.getItems().forEachIndexed { index, bookChapter ->
|
.coerceAtLeast(0)
|
||||||
if (bookChapter.index >= durChapterIndex) {
|
|
||||||
return@withContext
|
|
||||||
}
|
|
||||||
scrollPos = index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mLayoutManager.scrollToPositionWithOffset(scrollPos, 0)
|
mLayoutManager.scrollToPositionWithOffset(scrollPos, 0)
|
||||||
adapter.upDisplayTitles(scrollPos)
|
adapter.upDisplayTitles(scrollPos)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
|
|||||||
tabLayout = binding.tabLayout
|
tabLayout = binding.tabLayout
|
||||||
binding.viewPager.adapter = TabFragmentPageAdapter()
|
binding.viewPager.adapter = TabFragmentPageAdapter()
|
||||||
tabLayout.setupWithViewPager(binding.viewPager)
|
tabLayout.setupWithViewPager(binding.viewPager)
|
||||||
viewModel.bookData.observe(this) {
|
viewModel.bookData.observe(this) { book ->
|
||||||
menu?.setGroupVisible(R.id.menu_group_text, it.isLocalTxt)
|
menu?.setGroupVisible(R.id.menu_group_text, book.isLocalTxt)
|
||||||
|
supportActionBar?.title = book.name
|
||||||
}
|
}
|
||||||
intent.getStringExtra("bookUrl")?.let {
|
intent.getStringExtra("bookUrl")?.let {
|
||||||
viewModel.initBook(it)
|
viewModel.initBook(it)
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!-- res/drawable/md3_divider_inset.xml -->
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:insetLeft="16dp"
|
||||||
<size android:height="1px" />
|
android:insetRight="16dp">
|
||||||
<solid android:color="@color/bg_divider_line" />
|
<shape android:shape="rectangle">
|
||||||
|
<size android:height="1dp" />
|
||||||
|
<solid android:color="?attr/colorSurfaceContainer" />
|
||||||
</shape>
|
</shape>
|
||||||
|
</inset>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?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="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M382,640L155,413L212,356L382,526L748,160L805,217L382,640ZM200,800L200,720L760,720L760,800L200,800Z" />
|
||||||
|
</vector>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
app:layout_collapseMode="pin"
|
app:layout_collapseMode="pin"
|
||||||
app:navigationIcon="@drawable/ic_arrow_back"
|
app:navigationIcon="@drawable/ic_arrow_back"
|
||||||
app:title="@string/chapter_list" />
|
app:title="" />
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:id="@+id/tab_layout"
|
android:id="@+id/tab_layout"
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Σ(#`O′)"
|
android:text="Σ(#`O′)"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="24sp" />
|
android:textSize="32sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_msg"
|
android:id="@+id/tv_msg"
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
android:id="@+id/tv_retry"
|
android:id="@+id/tv_retry"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal"
|
style="@style/Widget.Material3Expressive.Button.TonalButton"
|
||||||
app:icon="@drawable/ic_refresh"
|
app:icon="@drawable/ic_refresh"
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
app:iconPadding="4dp"
|
app:iconPadding="4dp"
|
||||||
|
|||||||
@@ -9,18 +9,34 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<LinearLayout
|
||||||
android:id="@+id/tool_bar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:theme="?attr/actionBarStyle"
|
android:gravity="center"
|
||||||
app:title="@string/bookmark" />
|
android:orientation="vertical"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
|
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bottom_sheet_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="@string/bookmark"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_chapter_name"
|
android:id="@+id/tv_chapter_name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp" />
|
android:paddingHorizontal="16dp" />
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -36,8 +52,7 @@
|
|||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:paddingTop="3dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/edit_book_text"
|
android:id="@+id/edit_book_text"
|
||||||
@@ -74,11 +89,10 @@
|
|||||||
<!-- 删除按钮靠左 -->
|
<!-- 删除按钮靠左 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn_delete"
|
android:id="@+id/btn_delete"
|
||||||
style="@style/Widget.Material3Expressive.Button.TonalButton"
|
style="@style/Widget.Material3Expressive.Button.IconButton.Outlined"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="12dp"
|
app:icon="@drawable/ic_clear_all"
|
||||||
android:text="@string/delete"
|
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@@ -90,7 +104,7 @@
|
|||||||
style="@style/Widget.Material3Expressive.Button.TonalButton"
|
style="@style/Widget.Material3Expressive.Button.TonalButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="12dp"
|
android:minWidth="0dp"
|
||||||
android:text="@string/cancel"
|
android:text="@string/cancel"
|
||||||
app:layout_constraintEnd_toStartOf="@id/btn_ok"
|
app:layout_constraintEnd_toStartOf="@id/btn_ok"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@@ -100,10 +114,10 @@
|
|||||||
<!-- 确认按钮靠右 -->
|
<!-- 确认按钮靠右 -->
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/btn_ok"
|
android:id="@+id/btn_ok"
|
||||||
style="@style/Widget.Material3Expressive.Button.TonalButton"
|
style="@style/Widget.Material3Expressive.Button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="12dp"
|
android:minWidth="0dp"
|
||||||
android:text="@string/ok"
|
android:text="@string/ok"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
|||||||
@@ -7,22 +7,20 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingVertical="8dp">
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
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"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingVertical="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:paddingHorizontal="16dp">
|
android:paddingHorizontal="16dp">
|
||||||
|
|
||||||
<View
|
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||||
android:layout_width="36dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="4dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal" />
|
||||||
android:background="@drawable/bg_bottom_sheet_handle"
|
|
||||||
android:layout_marginBottom="16dp" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/bottom_sheet_title"
|
android:id="@+id/bottom_sheet_title"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:descendantFocusability="blocksDescendants">
|
android:descendantFocusability="blocksDescendants">
|
||||||
|
|
||||||
<io.legato.kazusa.ui.widget.recycler.scroller.FastScrollRecyclerView
|
<io.legato.kazusa.ui.widget.recycler.scroller.FastScrollRecyclerView
|
||||||
@@ -11,4 +12,31 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:overScrollMode="never" />
|
android:overScrollMode="never" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/tv_empty_msg"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="(๑`^´๑)"
|
||||||
|
android:textSize="32sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:text="还没有添加书签哦!" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="(๑`^´๑)"
|
android:text="(๑`^´๑)"
|
||||||
android:textSize="30sp"/>
|
android:textSize="32sp" />
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -10,32 +10,57 @@
|
|||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingVertical="12dp">
|
android:paddingVertical="12dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_info"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_locked"
|
android:id="@+id/iv_locked"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:paddingEnd="8dp"
|
android:padding="4dp"
|
||||||
android:src="@drawable/ic_lock_outline"
|
android:src="@drawable/ic_lock_outline"
|
||||||
android:visibility="gone"
|
android:visibility="visible" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/iv_volume"
|
||||||
|
android:layout_width="4dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:cardBackgroundColor="?attr/colorTertiary"
|
||||||
|
app:strokeWidth="0dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="4dp"
|
||||||
|
android:orientation="vertical"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/iv_checked"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:ignore="RtlSymmetry" />
|
app:layout_constraintStart_toEndOf="@id/ll_info">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_chapter_name"
|
android:id="@+id/tv_chapter_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="2"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:maxLines="2"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/iv_checked"
|
app:layout_constraintEnd_toStartOf="@+id/iv_checked"
|
||||||
app:layout_constraintStart_toEndOf="@+id/iv_locked"
|
app:layout_constraintStart_toEndOf="@+id/iv_locked"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_word_count"
|
android:id="@+id/tv_word_count"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:paddingEnd="18dp"
|
android:paddingEnd="18dp"
|
||||||
@@ -49,7 +74,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_tag"
|
android:id="@+id/tv_tag"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
@@ -58,6 +83,7 @@
|
|||||||
app:layout_constraintEnd_toStartOf="@+id/iv_checked"
|
app:layout_constraintEnd_toStartOf="@+id/iv_checked"
|
||||||
app:layout_constraintStart_toEndOf="@+id/iv_locked"
|
app:layout_constraintStart_toEndOf="@+id/iv_locked"
|
||||||
app:layout_constraintTop_toBottomOf="@id/tv_word_count" />
|
app:layout_constraintTop_toBottomOf="@id/tv_word_count" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_checked"
|
android:id="@+id/iv_checked"
|
||||||
|
|||||||
@@ -88,6 +88,7 @@
|
|||||||
android:id="@+id/cd_count"
|
android:id="@+id/cd_count"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_marginVertical="4dp"
|
android:layout_marginVertical="4dp"
|
||||||
app:cardBackgroundColor="?attr/colorSurfaceContainer"
|
app:cardBackgroundColor="?attr/colorSurfaceContainer"
|
||||||
app:cardCornerRadius="4dp"
|
app:cardCornerRadius="4dp"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||||
android:id="@+id/rotate_loading"
|
android:id="@+id/rotate_loading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
Reference in New Issue
Block a user