更新关于界面

搜索书籍界面切换至SearchBar与SearchView
This commit is contained in:
HapeLee
2025-08-06 17:52:07 +08:00
parent 3db111e87d
commit ccaf8973fe
18 changed files with 798 additions and 490 deletions
@@ -1,53 +1,97 @@
package io.legato.kazusa.ui.about
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import io.legato.kazusa.R
import io.legato.kazusa.base.BaseActivity
import io.legato.kazusa.databinding.ActivityAboutBinding
//import io.legado.app.lib.theme.accentColor
//import io.legado.app.lib.theme.filletBackground
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope
import io.legato.kazusa.R
import io.legato.kazusa.base.BaseActivity
import io.legato.kazusa.constant.AppLog
import io.legato.kazusa.databinding.ActivityAboutBinding
import io.legato.kazusa.help.CrashHandler
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.coroutine.Coroutine
import io.legato.kazusa.help.update.AppUpdate
import io.legato.kazusa.ui.widget.dialog.TextDialog
import io.legato.kazusa.ui.widget.dialog.WaitDialog
import io.legato.kazusa.utils.FileDoc
import io.legato.kazusa.utils.compress.ZipUtils
import io.legato.kazusa.utils.createFileIfNotExist
import io.legato.kazusa.utils.createFolderIfNotExist
import io.legato.kazusa.utils.delete
import io.legato.kazusa.utils.externalCache
import io.legato.kazusa.utils.find
import io.legato.kazusa.utils.list
import io.legato.kazusa.utils.openInputStream
import io.legato.kazusa.utils.openOutputStream
import io.legato.kazusa.utils.openUrl
import io.legato.kazusa.utils.share
import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.delay
import splitties.init.appCtx
import java.io.File
class AboutActivity : BaseActivity<ActivityAboutBinding>() {
override val binding by viewBinding(ActivityAboutBinding::inflate)
private val waitDialog by lazy {
WaitDialog(this).setText(R.string.checking_update)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setSupportActionBar(binding.topBar)
val fTag = "aboutFragment"
var aboutFragment = supportFragmentManager.findFragmentByTag(fTag)
if (aboutFragment == null) aboutFragment = AboutFragment()
supportFragmentManager.beginTransaction()
.replace(R.id.fl_fragment, aboutFragment, fTag)
.commit()
binding.tvAppSummary.post {
kotlin.runCatching {
val typedValue = TypedValue()
val context = binding.root.context
context.theme.resolveAttribute(
androidx.appcompat.R.attr.colorPrimary,
typedValue,
true
)
val accentColor = typedValue.data
val spannableString = SpannableString(binding.tvAppSummary.text)
val gzh = getString(R.string.legado_gzh)
val start = spannableString.indexOf(gzh)
spannableString.setSpan(
accentColor, start, start + gzh.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
binding.tvAppSummary.text = spannableString
}
binding.btnUpdate.setOnClickListener {
checkUpdate()
}
binding.btnGithub.setOnClickListener {
openUrl(R.string.github_url)
}
binding.btnWeb.setOnClickListener {
openUrl(R.string.legado_url)
}
binding.llContributors.setOnClickListener {
openUrl(R.string.contributors_url)
}
binding.llUpdateLog.setOnClickListener {
showMdFile(getString(R.string.update_log), "updateLog.md")
}
binding.llPrivacyPolicy.setOnClickListener {
showMdFile(getString(R.string.privacy_policy), "privacyPolicy.md")
}
binding.llLicense.setOnClickListener {
showMdFile(getString(R.string.license), "LICENSE.md")
}
binding.llDisclaimer.setOnClickListener {
showMdFile(getString(R.string.disclaimer), "disclaimer.md")
}
binding.llCrashLog.setOnClickListener {
showDialogFragment<CrashLogsDialog>()
}
binding.llSaveLog.setOnClickListener {
saveLog()
}
binding.llCreateHeapDump.setOnClickListener {
createHeapDump()
}
}
@@ -58,7 +102,6 @@ class AboutActivity : BaseActivity<ActivityAboutBinding>() {
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_scoring -> openUrl("market://details?id=$packageName")
R.id.menu_share_it -> share(
getString(R.string.app_share_description),
getString(R.string.app_name)
@@ -67,4 +110,118 @@ class AboutActivity : BaseActivity<ActivityAboutBinding>() {
return super.onCompatOptionsItemSelected(item)
}
private fun showMdFile(title: String, fileName: String) {
val mdText = String(this.assets.open(fileName).readBytes())
showDialogFragment(TextDialog(title, mdText, TextDialog.Mode.MD))
}
private fun checkUpdate() {
waitDialog.show()
AppUpdate.gitHubUpdate?.run {
check(lifecycleScope)
.onSuccess {
showDialogFragment(UpdateDialog(it))
}.onError {
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
}.onFinally {
waitDialog.dismiss()
}
}
}
@Suppress("SameParameterValue")
private fun openUrl(@StringRes addressID: Int) {
this.openUrl(getString(addressID))
}
private fun saveLog() {
Coroutine.async {
val backupPath = AppConfig.backupPath ?: let {
appCtx.toastOnUi("未设置备份目录")
return@async
}
if (!AppConfig.recordLog) {
appCtx.toastOnUi("未开启日志记录,请去其他设置里打开记录日志")
delay(3000)
}
val doc = FileDoc.fromUri(backupPath.toUri(), true)
copyLogs(doc)
copyHeapDump(doc)
appCtx.toastOnUi("已保存至备份目录")
}.onError {
AppLog.put("保存日志出错\n${it.localizedMessage}", it, true)
}
}
private fun createHeapDump() {
Coroutine.async {
val backupPath = AppConfig.backupPath ?: let {
appCtx.toastOnUi("未设置备份目录")
return@async
}
if (!AppConfig.recordHeapDump) {
appCtx.toastOnUi("未开启堆转储记录,请去其他设置里打开记录堆转储")
delay(3000)
}
appCtx.toastOnUi("开始创建堆转储")
System.gc()
CrashHandler.doHeapDump(true)
val doc = FileDoc.fromUri(backupPath.toUri(), true)
if (!copyHeapDump(doc)) {
appCtx.toastOnUi("未找到堆转储文件")
} else {
appCtx.toastOnUi("已保存至备份目录")
}
}.onError {
AppLog.put("保存堆转储失败\n${it.localizedMessage}", it)
}
}
private fun copyLogs(doc: FileDoc) {
val cacheDir = appCtx.externalCache
val logFiles = File(cacheDir, "logs")
val crashFiles = File(cacheDir, "crash")
val logcatFile = File(cacheDir, "logcat.txt")
dumpLogcat(logcatFile)
val zipFile = File(cacheDir, "logs.zip")
ZipUtils.zipFiles(arrayListOf(logFiles, crashFiles, logcatFile), zipFile)
doc.find("logs.zip")?.delete()
zipFile.inputStream().use { input ->
doc.createFileIfNotExist("logs.zip").openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
zipFile.delete()
}
private fun copyHeapDump(doc: FileDoc): Boolean {
val heapFile = FileDoc.fromFile(File(appCtx.externalCache, "heapDump")).list()
?.firstOrNull() ?: return false
doc.find("heapDump")?.delete()
val heapDumpDoc = doc.createFolderIfNotExist("heapDump")
heapFile.openInputStream().getOrNull()?.use { input ->
heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
return true
}
private fun dumpLogcat(file: File) {
try {
val process = Runtime.getRuntime().exec("logcat -d")
file.outputStream().use {
process.inputStream.copyTo(it)
}
} catch (e: Exception) {
AppLog.put("保存Logcat失败\n$e", e)
}
}
}
@@ -1,213 +0,0 @@
package io.legato.kazusa.ui.about
import android.os.Bundle
import android.view.View
import androidx.annotation.StringRes
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import io.legato.kazusa.R
import io.legato.kazusa.constant.AppConst.appInfo
import io.legato.kazusa.constant.AppLog
import io.legato.kazusa.help.CrashHandler
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.coroutine.Coroutine
import io.legato.kazusa.help.update.AppUpdate
import io.legato.kazusa.ui.widget.dialog.TextDialog
import io.legato.kazusa.ui.widget.dialog.WaitDialog
import io.legato.kazusa.utils.FileDoc
import io.legato.kazusa.utils.compress.ZipUtils
import io.legato.kazusa.utils.createFileIfNotExist
import io.legato.kazusa.utils.createFolderIfNotExist
import io.legato.kazusa.utils.delete
import io.legato.kazusa.utils.externalCache
import io.legato.kazusa.utils.find
import io.legato.kazusa.utils.list
import io.legato.kazusa.utils.openInputStream
import io.legato.kazusa.utils.openOutputStream
import io.legato.kazusa.utils.openUrl
import io.legato.kazusa.utils.sendMail
import io.legato.kazusa.utils.sendToClip
import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.toastOnUi
import kotlinx.coroutines.delay
import splitties.init.appCtx
import java.io.File
import androidx.core.net.toUri
class AboutFragment : PreferenceFragmentCompat() {
private val waitDialog by lazy {
WaitDialog(requireContext())
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.about)
findPreference<Preference>("update_log")?.summary =
"${getString(R.string.version)} ${appInfo.versionName}"
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.overScrollMode = View.OVER_SCROLL_NEVER
}
override fun onPreferenceTreeClick(preference: Preference): Boolean {
when (preference.key) {
"contributors" -> openUrl(R.string.contributors_url)
"update_log" -> showMdFile(getString(R.string.update_log), "updateLog.md")
"check_update" -> checkUpdate()
"mail" -> requireContext().sendMail(getString(R.string.email))
"license" -> showMdFile(getString(R.string.license), "LICENSE.md")
"disclaimer" -> showMdFile(getString(R.string.disclaimer), "disclaimer.md")
"privacyPolicy" -> showMdFile(getString(R.string.privacy_policy), "privacyPolicy.md")
"gzGzh" -> requireContext().sendToClip(getString(R.string.legado_gzh))
"crashLog" -> showDialogFragment<CrashLogsDialog>()
"saveLog" -> saveLog()
"createHeapDump" -> createHeapDump()
}
return super.onPreferenceTreeClick(preference)
}
@Suppress("SameParameterValue")
private fun openUrl(@StringRes addressID: Int) {
requireContext().openUrl(getString(addressID))
}
/**
* 显示md文件
*/
private fun showMdFile(title: String, fileName: String) {
val mdText = String(requireContext().assets.open(fileName).readBytes())
showDialogFragment(TextDialog(title, mdText, TextDialog.Mode.MD))
}
/**
* 检测更新
*/
private fun checkUpdate() {
waitDialog.show()
AppUpdate.gitHubUpdate?.run {
check(lifecycleScope)
.onSuccess {
showDialogFragment(
UpdateDialog(it)
)
}.onError {
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
}.onFinally {
waitDialog.dismiss()
}
}
}
// /**
// * 加入qq群
// */
// private fun joinQQGroup(key: String): Boolean {
// val intent = Intent()
// intent.data =
// "mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$key".toUri()
// // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面
// // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// kotlin.runCatching {
// startActivity(intent)
// return true
// }.onFailure {
// toastOnUi("添加失败,请手动添加")
// }
// return false
// }
private fun saveLog() {
Coroutine.async {
val backupPath = AppConfig.backupPath ?: let {
appCtx.toastOnUi("未设置备份目录")
return@async
}
if (!AppConfig.recordLog) {
appCtx.toastOnUi("未开启日志记录,请去其他设置里打开记录日志")
delay(3000)
}
val doc = FileDoc.fromUri(backupPath.toUri(), true)
copyLogs(doc)
copyHeapDump(doc)
appCtx.toastOnUi("已保存至备份目录")
}.onError {
AppLog.put("保存日志出错\n${it.localizedMessage}", it, true)
}
}
private fun createHeapDump() {
Coroutine.async {
val backupPath = AppConfig.backupPath ?: let {
appCtx.toastOnUi("未设置备份目录")
return@async
}
if (!AppConfig.recordHeapDump) {
appCtx.toastOnUi("未开启堆转储记录,请去其他设置里打开记录堆转储")
delay(3000)
}
appCtx.toastOnUi("开始创建堆转储")
System.gc()
CrashHandler.doHeapDump(true)
val doc = FileDoc.fromUri(backupPath.toUri(), true)
if (!copyHeapDump(doc)) {
appCtx.toastOnUi("未找到堆转储文件")
} else {
appCtx.toastOnUi("已保存至备份目录")
}
}.onError {
AppLog.put("保存堆转储失败\n${it.localizedMessage}", it)
}
}
private fun copyLogs(doc: FileDoc) {
val cacheDir = appCtx.externalCache
val logFiles = File(cacheDir, "logs")
val crashFiles = File(cacheDir, "crash")
val logcatFile = File(cacheDir, "logcat.txt")
dumpLogcat(logcatFile)
val zipFile = File(cacheDir, "logs.zip")
ZipUtils.zipFiles(arrayListOf(logFiles, crashFiles, logcatFile), zipFile)
doc.find("logs.zip")?.delete()
zipFile.inputStream().use { input ->
doc.createFileIfNotExist("logs.zip").openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
zipFile.delete()
}
private fun copyHeapDump(doc: FileDoc): Boolean {
val heapFile = FileDoc.fromFile(File(appCtx.externalCache, "heapDump")).list()
?.firstOrNull() ?: return false
doc.find("heapDump")?.delete()
val heapDumpDoc = doc.createFolderIfNotExist("heapDump")
heapFile.openInputStream().getOrNull()?.use { input ->
heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
return true
}
private fun dumpLogcat(file: File) {
try {
val process = Runtime.getRuntime().exec("logcat -d")
file.outputStream().use {
process.inputStream.copyTo(it)
}
} catch (e: Exception) {
AppLog.put("保存Logcat失败\n$e", e)
}
}
}
@@ -5,8 +5,8 @@ import android.view.ViewGroup
import io.legato.kazusa.base.adapter.ItemViewHolder
import io.legato.kazusa.base.adapter.RecyclerAdapter
import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.databinding.ItemFilletTextBinding
import io.legato.kazusa.databinding.ItemSearchHistoryBinding
import io.legato.kazusa.utils.gone
class BookAdapter(context: Context, val callBack: CallBack) :
@@ -39,6 +39,7 @@ class BookAdapter(context: Context, val callBack: CallBack) :
}
}
}
binding.btnDelete.gone()
}
interface CallBack {
@@ -4,7 +4,6 @@ import android.view.ViewGroup
import io.legato.kazusa.base.adapter.ItemViewHolder
import io.legato.kazusa.base.adapter.RecyclerAdapter
import io.legato.kazusa.data.entities.SearchKeyword
import io.legato.kazusa.databinding.ItemFilletTextBinding
import io.legato.kazusa.databinding.ItemSearchHistoryBinding
import io.legato.kazusa.ui.widget.anima.explosion_field.ExplosionField
import splitties.views.onLongClick
@@ -47,6 +46,11 @@ class HistoryKeyAdapter(activity: SearchActivity, val callBack: CallBack) :
}
}
}
binding.btnDelete.setOnClickListener {
getItemByLayoutPosition(holder.layoutPosition)?.let {
callBack.deleteHistory(it)
}
}
}
interface CallBack {
@@ -5,17 +5,18 @@ import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.TextView
import android.view.inputmethod.EditorInfo
import androidx.activity.viewModels
import androidx.appcompat.widget.SearchView
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.material.search.SearchBar
import com.google.android.material.search.SearchView
import io.legato.kazusa.R
import io.legato.kazusa.base.VMBaseActivity
import io.legato.kazusa.constant.AppLog
@@ -25,15 +26,12 @@ import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.SearchKeyword
import io.legato.kazusa.databinding.ActivityBookSearchBinding
import io.legato.kazusa.lib.dialogs.alert
//import io.legado.app.lib.theme.accentColor
//import io.legado.app.lib.theme.backgroundColor
//import io.legado.app.lib.theme.primaryColor
//import io.legado.app.lib.theme.primaryTextColor
import io.legato.kazusa.ui.about.AppLogDialog
import io.legato.kazusa.ui.book.info.BookInfoActivity
import io.legato.kazusa.ui.book.source.manage.BookSourceActivity
import io.legato.kazusa.utils.applyNavigationBarMargin
import io.legato.kazusa.utils.applyNavigationBarPadding
import io.legato.kazusa.utils.applyStatusBarPadding
import io.legato.kazusa.utils.getPrefBoolean
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.invisible
@@ -73,9 +71,10 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
setHasStableIds(true)
}
}
private val searchView: SearchView by lazy {
binding.titleBar.findViewById(R.id.search_view)
}
private val searchBar: SearchBar by lazy { binding.searchBar }
private val searchView: SearchView by lazy { binding.searchView }
private var menu: Menu? = null
private var groups: List<String>? = null
private var historyFlowJob: Job? = null
@@ -85,9 +84,9 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//binding.llInputHelp.setBackgroundColor(backgroundColor)
setSupportActionBar(binding.searchBar)
initRecyclerView()
initSearchView()
initMaterialSearch()
initOtherView()
initData()
receiptIntent(intent)
@@ -154,8 +153,8 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
!getPrefBoolean(PreferKey.precisionSearch)
)
precisionSearchMenuItem?.isChecked = getPrefBoolean(PreferKey.precisionSearch)
searchView.query?.toString()?.trim()?.let {
searchView.setQuery(it, true)
searchView.text.toString().trim().let {
searchView.setText(it)
}
}
@@ -174,44 +173,63 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
return super.onCompatOptionsItemSelected(item)
}
private fun initSearchView() {
//searchView.applyTint(primaryTextColor)
searchView.isSubmitButtonEnabled = true
searchView.queryHint = getString(R.string.search_book_key)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
searchView.clearFocus()
query.trim().let { searchKey ->
isManualStopSearch = false
viewModel.saveSearchKey(searchKey)
viewModel.searchKey = ""
viewModel.search(searchKey)
}
visibleInputHelp(false)
return true
}
private fun initMaterialSearch() {
override fun onQueryTextChange(newText: String): Boolean {
viewModel.stop()
binding.fbStartStop.invisible()
upHistory(newText.trim())
return false
binding.appBar.applyStatusBarPadding()
searchBar.setOnMenuItemClickListener { item ->
onCompatOptionsItemSelected(item)
}
searchBar.setNavigationOnClickListener {
finish()
}
searchView.setupWithSearchBar(searchBar)
binding.searchView.show()
binding.searchView.editText.requestFocus()
searchView.editText.hint = getString(R.string.search_book_key)
searchView.editText.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
val key = searchView.text.toString().trim()
if (key.isNotEmpty()) {
isManualStopSearch = false
viewModel.saveSearchKey(key)
viewModel.searchKey = ""
viewModel.search(key)
visibleInputHelp()
searchView.hide()
return@setOnEditorActionListener true
}
}
})
// searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
// if (binding.refreshProgressBar.isAutoLoading || (!hasFocus && adapter.isNotEmpty() && searchView.query.isNotBlank())) {
// visibleInputHelp(false)
// } else {
// visibleInputHelp(true)
// }
// }
visibleInputHelp(true)
false
}
searchView.editText.doAfterTextChanged {
viewModel.stop()
binding.fbStartStop.invisible()
upHistory(it?.toString()?.trim().orEmpty())
}
searchView.addTransitionListener { _, _, newState ->
if (newState == SearchView.TransitionState.HIDDEN) {
// 当 SearchView 关闭时,将搜索文本设置回 SearchBar
searchBar.setText(searchView.text)
}
}
searchView.addTransitionListener { _, oldState, newState ->
if (oldState == SearchView.TransitionState.HIDDEN && newState == SearchView.TransitionState.SHOWN) {
searchView.editText.requestFocus()
}
}
visibleInputHelp()
}
private fun initRecyclerView() {
// binding.recyclerView.setEdgeEffectColor(primaryColor)
// binding.rvBookshelfSearch.setEdgeEffectColor(primaryColor)
// binding.rvHistoryKey.setEdgeEffectColor(primaryColor)
binding.rvBookshelfSearch.layoutManager = FlexboxLayoutManager(this)
binding.rvBookshelfSearch.adapter = bookAdapter
binding.rvBookshelfSearch.applyNavigationBarMargin()
@@ -261,16 +279,10 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
}
private fun initOtherView() {
// binding.fbStartStop.backgroundTintList =
// Selector.colorBuild()
// .setDefaultColor(accentColor)
// .setPressedColor(ColorUtils.darkenColor(accentColor))
// .create()
binding.fbStartStop.setOnClickListener {
if (viewModel.isSearchLiveData.value == true) {
isManualStopSearch = true
viewModel.stop()
//binding.refreshProgressBar.visibility = GONE
} else {
viewModel.search("")
}
@@ -281,8 +293,8 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
private fun initData() {
viewModel.searchScope.stateLiveData.observe(this) {
if (!binding.llInputHelp.isVisible) {
searchView.query?.toString()?.trim()?.let {
searchView.setQuery(it, true)
searchView.text.toString().trim().let {
searchView.setText(it)
}
}
}
@@ -295,6 +307,11 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
}
viewModel.searchBookLiveData.observe(this) {
adapter.setItems(it)
if (it.isNullOrEmpty()) {
binding.tvEmptyMsg.visible()
} else {
binding.tvEmptyMsg.gone()
}
}
lifecycleScope.launch {
appDb.bookSourceDao.flowEnabledGroups().collect {
@@ -313,10 +330,9 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
}
val key = intent?.getStringExtra("key")
if (key.isNullOrBlank()) {
searchView.findViewById<TextView>(androidx.appcompat.R.id.search_src_text)
.requestFocus()
searchView.editText.requestFocus()
} else {
searchView.setQuery(key, true)
searchView.setText(key)
}
}
@@ -338,13 +354,9 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
/**
* 打开关闭输入帮助
*/
private fun visibleInputHelp(visible: Boolean) {
if (visible) {
upHistory(searchView.query.toString())
binding.llInputHelp.visibility = VISIBLE
} else {
binding.llInputHelp.visibility = GONE
}
private fun visibleInputHelp() {
upHistory(searchView.text.toString())
binding.llInputHelp.visibility = VISIBLE
}
/**
@@ -401,7 +413,6 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
* 搜索结束
*/
private fun searchFinally() {
//binding.refreshProgressBar.isAutoLoading = false
binding.refreshProgressBar.gone()
if (!isManualStopSearch && viewModel.hasMore) {
binding.fbStartStop.setImageResource(R.drawable.ic_play_24dp)
@@ -425,7 +436,7 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
appCtx.putPrefBoolean(PreferKey.precisionSearch, false)
precisionSearchMenuItem?.isChecked = false
viewModel.searchKey = ""
viewModel.search(searchView.query.toString())
viewModel.search(searchView.text.toString())
}
} else {
setMessage("${displayScope}分组搜索结果为空,是否切换到全部分组?")
@@ -469,16 +480,16 @@ class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel
override fun searchHistory(key: String) {
lifecycleScope.launch {
when {
searchView.query.toString() == key -> {
searchView.setQuery(key, true)
searchView.text.toString() == key -> {
searchView.setText(key)
}
withContext(IO) { appDb.bookDao.findByName(key).isEmpty() } -> {
searchView.setQuery(key, true)
searchView.setText(key)
}
else -> {
searchView.setQuery(key, false)
searchView.setText(key)
}
}
}
@@ -2,17 +2,23 @@ package io.legato.kazusa.ui.widget.dialog
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import io.legato.kazusa.R
import io.legato.kazusa.databinding.DialogWaitBinding
class WaitDialog(context: Context) {
@Suppress("unused")
class WaitDialog(context: Context) : Dialog(context) {
private val binding: DialogWaitBinding =
DialogWaitBinding.inflate(LayoutInflater.from(context))
val binding = DialogWaitBinding.inflate(layoutInflater)
private val dialog: Dialog = MaterialAlertDialogBuilder(context)
.setView(binding.root)
.setCancelable(false)
.create()
init {
setCanceledOnTouchOutside(false)
setContentView(binding.root)
binding.tvMsg.setText(R.string.loading)
}
fun setText(text: String): WaitDialog {
@@ -20,9 +26,31 @@ class WaitDialog(context: Context) : Dialog(context) {
return this
}
fun setText(res: Int): WaitDialog {
binding.tvMsg.setText(res)
fun setText(resId: Int): WaitDialog {
binding.tvMsg.setText(resId)
return this
}
}
fun show(): WaitDialog {
dialog.show()
return this
}
fun dismiss() {
dialog.dismiss()
}
fun isShowing(): Boolean {
return dialog.isShowing
}
fun setOnCancelListener(listener: () -> Unit): WaitDialog {
dialog.setOnCancelListener { listener() }
return this
}
fun setCancelable(cancelable: Boolean): WaitDialog {
dialog.setCancelable(cancelable)
return this
}
}
+9 -2
View File
@@ -1,3 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="960" android:viewportHeight="960" android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white" android:pathData="M480,420L480,420Q480,420 480,420Q480,420 480,420L480,420Q480,420 480,420Q480,420 480,420L480,420Q480,420 480,420Q480,420 480,420ZM80,800L80,720L480,720L480,800L80,800ZM200,680Q167,680 143.5,656.5Q120,633 120,600L120,240Q120,207 143.5,183.5Q167,160 200,160L760,160Q793,160 816.5,183.5Q840,207 840,240L200,240Q200,240 200,240Q200,240 200,240L200,600Q200,600 200,600Q200,600 200,600L480,600L480,680L200,680ZM800,720L800,400Q800,400 800,400Q800,400 800,400L640,400Q640,400 640,400Q640,400 640,400L640,720Q640,720 640,720Q640,720 640,720L800,720Q800,720 800,720Q800,720 800,720ZM620,800Q595,800 577.5,782.5Q560,765 560,740L560,380Q560,355 577.5,337.5Q595,320 620,320L820,320Q845,320 862.5,337.5Q880,355 880,380L880,740Q880,765 862.5,782.5Q845,800 820,800L620,800ZM720,500Q733,500 741.5,491Q750,482 750,470Q750,457 741.5,448.5Q733,440 720,440Q708,440 699,448.5Q690,457 690,470Q690,482 699,491Q708,500 720,500ZM720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560Z"/>
<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="M480,420L480,420Q480,420 480,420Q480,420 480,420L480,420Q480,420 480,420Q480,420 480,420L480,420Q480,420 480,420Q480,420 480,420ZM80,800L80,720L480,720L480,800L80,800ZM200,680Q167,680 143.5,656.5Q120,633 120,600L120,240Q120,207 143.5,183.5Q167,160 200,160L760,160Q793,160 816.5,183.5Q840,207 840,240L200,240Q200,240 200,240Q200,240 200,240L200,600Q200,600 200,600Q200,600 200,600L480,600L480,680L200,680ZM800,720L800,400Q800,400 800,400Q800,400 800,400L640,400Q640,400 640,400Q640,400 640,400L640,720Q640,720 640,720Q640,720 640,720L800,720Q800,720 800,720Q800,720 800,720ZM620,800Q595,800 577.5,782.5Q560,765 560,740L560,380Q560,355 577.5,337.5Q595,320 620,320L820,320Q845,320 862.5,337.5Q880,355 880,380L880,740Q880,765 862.5,782.5Q845,800 820,800L620,800ZM720,500Q733,500 741.5,491Q750,482 750,470Q750,457 741.5,448.5Q733,440 720,440Q708,440 699,448.5Q690,457 690,470Q690,482 699,491Q708,500 720,500ZM720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560L720,560Q720,560 720,560Q720,560 720,560Z" />
</vector>
+10
View File
@@ -0,0 +1,10 @@
<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="@android:color/white"
android:pathData="M12 1C5.923 1 1 5.923 1 12c0 4.867 3.149 8.979 7.521 10.436.55.096.756-.233.756-.522 0-.262-.013-1.128-.013-2.049-2.764.509-3.479-.674-3.699-1.292-.124-.317-.66-1.293-1.127-1.554-.385-.207-.936-.715-.014-.729.866-.014 1.485.797 1.691 1.128.99 1.663 2.571 1.196 3.204.907.096-.715.385-1.196.701-1.471-2.448-.275-5.005-1.224-5.005-5.432 0-1.196.426-2.186 1.128-2.956-.111-.275-.496-1.402.11-2.915 0 0 .921-.288 3.024 1.128a10.193 10.193 0 0 1 2.75-.371c.936 0 1.871.123 2.75.371 2.104-1.43 3.025-1.128 3.025-1.128.605 1.513.221 2.64.111 2.915.701.77 1.127 1.747 1.127 2.956 0 4.222-2.571 5.157-5.019 5.432.399.344.743 1.004.743 2.035 0 1.471-.014 2.654-.014 3.025 0 .289.206.632.756.522C19.851 20.979 23 16.854 23 12c0-6.077-4.922-11-11-11Z" />
</vector>
+297 -23
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@@ -7,41 +7,315 @@
android:orientation="vertical"
tools:context="io.legato.kazusa.ui.about.AboutActivity">
<io.legato.kazusa.ui.widget.TitleBar
android:id="@+id/title_bar"
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/about">
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/ll_about"
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutMediumStyle"
android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleCollapseMode="scale">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_arrow_back"
app:title="@string/about" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_card_view"
android:layout_marginVertical="8dp"
android:orientation="vertical"
android:layout_margin="16dp"
android:padding="16dp">
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_about"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/app_name"
android:textSize="20sp"
android:textStyle="bold" />
android:layout_marginStart="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/tv_app_summary"
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/app_name"
android:layout_marginEnd="16dp"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cd_about"
app:layout_constraintTop_toTopOf="@id/cd_about" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:text="@string/about_description"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/cd_about"
app:layout_constraintTop_toBottomOf="@id/tv_name" />
<LinearLayout
android:id="@+id/ll_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about_description" />
</LinearLayout>
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cd_about">
</io.legato.kazusa.ui.widget.TitleBar>
<com.google.android.material.card.MaterialCardView
android:layout_width="8dp"
android:layout_height="match_parent"
android:layout_marginVertical="8dp"
android:layout_marginEnd="12dp"
app:cardBackgroundColor="?attr/colorTertiary"
app:strokeWidth="0dp" />
<FrameLayout
android:id="@+id/fl_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_web"
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
app:icon="@drawable/ic_web_outline" />
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_github"
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:icon="@drawable/ic_github" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_update"
style="@style/Widget.Material3Expressive.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/check_update"
app:icon="@drawable/ic_import" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_contributors"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_btn">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/contributors"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/contributors_summary"
android:textSize="13sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_update_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_contributors">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/update_log"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_privacy_policy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_update_log">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/privacy_policy"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_license"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_privacy_policy">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/license"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_disclaimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_license">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/disclaimer"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_crash_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_disclaimer">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/crash_log"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_save_log"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_crash_log">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/save_log"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_create_heap_dump"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
app:layout_constraintTop_toBottomOf="@id/ll_save_log">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/create_heap_dump"
android:textSize="16sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
+114 -81
View File
@@ -1,34 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.book.search.SearchActivity">
<io.legato.kazusa.ui.widget.TitleBar
android:id="@+id/title_bar"
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStartWithNavigation="0dp"
app:contentLayout="@layout/view_search"
app:layout_constraintTop_toTopOf="parent"
app:title="搜索" />
android:backgroundTint="?attr/colorSurface"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="gone"
android:indeterminate="true"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<com.google.android.material.search.SearchBar
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search_book_key"
app:menu="@menu/book_search"
app:navigationIconTint="?attr/colorOnSurface" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/app_bar">
</com.google.android.material.progressindicator.LinearProgressIndicator>
</com.google.android.material.appbar.AppBarLayout>
<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="visible">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(๑`^´๑)"
android:textSize="30sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="@string/search_empty" />
</LinearLayout>
<io.legato.kazusa.ui.widget.dynamiclayout.DynamicFrameLayout
android:id="@+id/content_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar">
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
@@ -39,72 +71,75 @@
</io.legato.kazusa.ui.widget.dynamiclayout.DynamicFrameLayout>
<LinearLayout
android:id="@+id/ll_input_help"
<com.google.android.material.search.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_bar">
<TextView
android:id="@+id/tv_book_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp"
android:text="@string/bookshelf"
android:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:visibility="visible" />
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="4dp">
<TextView
android:id="@+id/tv_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:layout_gravity="center_vertical"
android:text="@string/searchHistory" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_clear_history"
style="@style/Widget.Material3Expressive.Button.IconButton.Outlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:iconGravity="textStart"
app:icon="@drawable/ic_clear_all" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_history_key"
android:id="@+id/ll_input_help"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="12dp" />
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:visibility="visible">
</LinearLayout>
<TextView
android:id="@+id/tv_book_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:text="@string/bookshelf"
android:textSize="16sp"
android:textStyle="bold"
android:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="4dp">
<TextView
android:id="@+id/tv_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/searchHistory"
android:textSize="16sp"
android:textStyle="bold" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_clear_history"
style="@style/Widget.Material3Expressive.Button.IconButton.Outlined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_clear_all"
app:iconGravity="textStart" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_history_key"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</com.google.android.material.search.SearchView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fb_start_stop"
@@ -114,9 +149,7 @@
android:contentDescription="@string/stop"
android:src="@drawable/ic_stop_black_24dp"
android:visibility="invisible"
app:fabSize="mini"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
android:layout_gravity="bottom|end" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
+2 -1
View File
@@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="16dp"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:scrollbars="none">
+19 -14
View File
@@ -1,30 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootView"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="2dp"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:background="@drawable/selector_fillet_btn_bg"
android:gravity="center"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:minHeight="36dp"
android:backgroundTint="?attr/colorSurfaceContainer"
android:clipToPadding="false"
android:clipChildren="false">
android:gravity="center_vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="关键词"
android:textSize="14sp"
android:textColor="?attr/colorOnSurface"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:layout_weight="1"
android:maxLines="1"
android:ellipsize="end"
android:paddingHorizontal="4dp" />
android:text="@string/text"
android:textSize="16sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_delete"
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:backgroundTint="@android:color/transparent"
app:icon="@drawable/ic_baseline_close" />
</LinearLayout>
-1
View File
@@ -3,7 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/search_view"
android:theme="?attr/actionBarStyle"
android:background="@drawable/bg_searchview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
-5
View File
@@ -10,9 +10,4 @@
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />
<item
android:id="@+id/menu_scoring"
android:title="@string/scoring"
android:icon="@drawable/ic_scoring"
app:showAsAction="always" />
</menu>
+2
View File
@@ -1234,5 +1234,7 @@
<string name="list">列表</string>
<string name="grid">网格</string>
<string name="descending_order">降序</string>
<string name="checking_update">检查更新中...</string>
<string name="search_empty">没有内容哦</string>
</resources>
+2 -1
View File
@@ -5,7 +5,8 @@
<string name="email" translatable="false">gekunfei@live.com</string>
<string name="contributors_url" translatable="false">https://github.com/gedoor/legado/graphs/contributors</string>
<string name="github_url" translatable="false">https://github.com/HapeLee/legado</string>
<string name="legado_url" translatable="false">https://gedoor.github.io/</string>
<string name="http_ip" translatable="false">http://%1$s:%2$d</string>
<string name="git_hub" translatable="false">GitHub</string>
<string name="diy_edit_source_group_title" translatable="false">【%s】</string>
+2
View File
@@ -1237,5 +1237,7 @@
<string name="number_rows_columns">每行列数</string>
<string name="ascending_order">升序</string>
<string name="descending_order">降序</string>
<string name="checking_update">检查更新中...</string>
<string name="search_empty">没有内容哦</string>
</resources>
+24 -33
View File
@@ -22,43 +22,34 @@
app:allowDividerBelow="false"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.PreferenceCategory
android:title="@string/other"
app:allowDividerAbove="true"
app:allowDividerBelow="false"
app:iconSpaceReserved="false"
app:layout="@layout/view_preference_category">
<io.legato.kazusa.lib.prefs.Preference
android:key="privacyPolicy"
android:title="@string/privacy_policy"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="crashLog"
android:title="@string/crash_log"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="license"
android:title="@string/license"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="saveLog"
android:title="@string/save_log"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="disclaimer"
android:title="@string/disclaimer"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="createHeapDump"
android:title="@string/create_heap_dump"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="crashLog"
android:title="@string/crash_log"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="privacyPolicy"
android:title="@string/privacy_policy"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="saveLog"
android:title="@string/save_log"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="license"
android:title="@string/license"
app:iconSpaceReserved="false" />
<io.legato.kazusa.lib.prefs.Preference
android:key="disclaimer"
android:title="@string/disclaimer"
app:iconSpaceReserved="false" />
</io.legato.kazusa.lib.prefs.PreferenceCategory>
<io.legato.kazusa.lib.prefs.Preference
android:key="createHeapDump"
android:title="@string/create_heap_dump"
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceScreen>