viewBinding

pull/517/head
gedoor 4 years ago
parent 3478f2210a
commit 6852689604
  1. 12
      app/build.gradle
  2. 18
      app/src/main/java/io/legado/app/base/BaseActivity.kt
  3. 2
      app/src/main/java/io/legado/app/base/BaseFragment.kt
  4. 6
      app/src/main/java/io/legado/app/base/VMBaseActivity.kt
  5. 4
      app/src/main/java/io/legado/app/data/entities/Book.kt
  6. 4
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  7. 2
      app/src/main/java/io/legado/app/data/entities/BookGroup.kt
  8. 2
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  9. 2
      app/src/main/java/io/legado/app/data/entities/Bookmark.kt
  10. 10
      app/src/main/java/io/legado/app/data/entities/ReplaceRule.kt
  11. 2
      app/src/main/java/io/legado/app/data/entities/RssSource.kt
  12. 4
      app/src/main/java/io/legado/app/data/entities/SearchBook.kt
  13. 2
      app/src/main/java/io/legado/app/data/entities/SearchKeyword.kt
  14. 5
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  15. 3
      app/src/main/java/io/legado/app/lib/theme/ATH.kt
  16. 12
      app/src/main/java/io/legado/app/ui/about/AboutActivity.kt
  17. 3
      app/src/main/java/io/legado/app/ui/about/DonateActivity.kt
  18. 25
      app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt
  19. 15
      app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt
  20. 16
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt
  21. 21
      app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt
  22. 16
      app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt
  23. 54
      app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt
  24. 30
      app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt
  25. 16
      app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt
  26. 8
      app/src/main/java/io/legado/app/ui/book/changecover/CoverAdapter.kt
  27. 14
      app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt
  28. 72
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  29. 32
      app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt
  30. 46
      app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt
  31. 192
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  32. 78
      app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt
  33. 168
      app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt
  34. 124
      app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
  35. 7
      app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
  36. 107
      app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt
  37. 49
      app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt
  38. 32
      app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt
  39. 36
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  40. 91
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  41. 28
      app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt
  42. 10
      app/src/main/java/io/legado/app/ui/config/ConfigActivity.kt
  43. 3
      app/src/main/java/io/legado/app/ui/filepicker/FilePicker.kt
  44. 16
      app/src/main/java/io/legado/app/ui/login/SourceLogin.kt
  45. 55
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  46. 2
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
  47. 16
      app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt
  48. 26
      app/src/main/java/io/legado/app/ui/qrcode/QrCodeActivity.kt
  49. 53
      app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt
  50. 8
      app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt
  51. 16
      app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt
  52. 15
      app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt
  53. 50
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
  54. 18
      app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugActivity.kt
  55. 29
      app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt
  56. 52
      app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt
  57. 10
      app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
  58. 51
      app/src/main/java/io/legado/app/ui/widget/DetailSeekBar.kt
  59. 43
      app/src/main/java/io/legado/app/ui/widget/recycler/RefreshRecyclerView.kt
  60. 58
      app/src/main/java/io/legado/app/utils/viewbindingdelegate/DialogFragmentViewBindings.kt
  61. 54
      app/src/main/java/io/legado/app/utils/viewbindingdelegate/FragmentViewBindings.kt
  62. 57
      app/src/main/java/io/legado/app/utils/viewbindingdelegate/ViewBindingProperty.kt
  63. 1
      app/src/main/res/layout/activity_book_source.xml
  64. 1
      app/src/main/res/layout/activity_book_source_edit.xml
  65. 0
      app/src/main/res/layout/activity_cache_book.xml
  66. 2
      app/src/main/res/layout/activity_qrcode_capture.xml
  67. 4
      app/src/main/res/layout/activity_read_record.xml
  68. 1
      app/src/main/res/layout/activity_rss_source_edit.xml
  69. 1
      app/src/main/res/layout/activity_welcome.xml
  70. 2
      build.gradle

@ -1,13 +1,14 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'de.timfreiheit.resourceplaceholders' apply plugin: 'de.timfreiheit.resourceplaceholders'
apply plugin: 'com.google.firebase.crashlytics' apply plugin: 'com.google.firebase.crashlytics'
androidExtensions { //androidExtensions {
experimental = true // experimental = true
} //}
static def releaseTime() { static def releaseTime() {
return new Date().format("yy.MMddHH", TimeZone.getTimeZone("GMT+8")) return new Date().format("yy.MMddHH", TimeZone.getTimeZone("GMT+8"))
@ -50,6 +51,9 @@ android {
} }
} }
} }
buildFeatures {
viewBinding true
}
buildTypes { buildTypes {
release { release {
if (project.hasProperty("RELEASE_STORE_FILE")) { if (project.hasProperty("RELEASE_STORE_FILE")) {

@ -5,11 +5,13 @@ import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
@ -22,10 +24,10 @@ import io.legado.app.utils.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import java.lang.reflect.ParameterizedType
abstract class BaseActivity( abstract class BaseActivity<VB : ViewBinding>(
private val layoutID: Int,
val fullScreen: Boolean = true, val fullScreen: Boolean = true,
private val theme: Theme = Theme.Auto, private val theme: Theme = Theme.Auto,
private val toolBarTheme: Theme = Theme.Auto, private val toolBarTheme: Theme = Theme.Auto,
@ -33,6 +35,16 @@ abstract class BaseActivity(
) : AppCompatActivity(), ) : AppCompatActivity(),
CoroutineScope by MainScope() { CoroutineScope by MainScope() {
@Suppress("UNCHECKED_CAST")
protected val binding: VB by lazy {
//使用反射得到viewBinding的class
val type = javaClass.genericSuperclass as ParameterizedType
val aClass = type.actualTypeArguments[0] as Class<*>
val method = aClass.getDeclaredMethod("inflate", LayoutInflater::class.java)
method.invoke(null, layoutInflater) as VB
}
val isInMultiWindow: Boolean val isInMultiWindow: Boolean
get() { get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -63,7 +75,7 @@ abstract class BaseActivity(
initTheme() initTheme()
setupSystemBar() setupSystemBar()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(layoutID) setContentView(binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
findViewById<TitleBar>(R.id.title_bar) findViewById<TitleBar>(R.id.title_bar)
?.onMultiWindowModeChanged(isInMultiWindowMode, fullScreen) ?.onMultiWindowModeChanged(isInMultiWindowMode, fullScreen)

@ -58,7 +58,7 @@ abstract class BaseFragment(layoutID: Int) : Fragment(layoutID),
} }
private fun onMultiWindowModeChanged() { private fun onMultiWindowModeChanged() {
(activity as? BaseActivity)?.let { (activity as? BaseActivity<*>)?.let {
view?.findViewById<TitleBar>(R.id.title_bar) view?.findViewById<TitleBar>(R.id.title_bar)
?.onMultiWindowModeChanged(it.isInMultiWindow, it.fullScreen) ?.onMultiWindowModeChanged(it.isInMultiWindow, it.fullScreen)
} }

@ -1,14 +1,14 @@
package io.legado.app.base package io.legado.app.base
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.viewbinding.ViewBinding
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
abstract class VMBaseActivity<VM : ViewModel>( abstract class VMBaseActivity<VB : ViewBinding, VM : ViewModel>(
layoutID: Int,
fullScreen: Boolean = true, fullScreen: Boolean = true,
theme: Theme = Theme.Auto, theme: Theme = Theme.Auto,
toolBarTheme: Theme = Theme.Auto toolBarTheme: Theme = Theme.Auto
) : BaseActivity(layoutID, fullScreen, theme, toolBarTheme) { ) : BaseActivity<VB>(fullScreen, theme, toolBarTheme) {
protected abstract val viewModel: VM protected abstract val viewModel: VM

@ -10,8 +10,8 @@ import io.legado.app.service.help.ReadBook
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
import java.nio.charset.Charset import java.nio.charset.Charset
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min

@ -10,8 +10,8 @@ import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize

@ -6,7 +6,7 @@ import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize
@Entity(tableName = "book_groups") @Entity(tableName = "book_groups")

@ -15,7 +15,7 @@ import io.legado.app.utils.ACache
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.splitNotBlank import io.legado.app.utils.splitNotBlank
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
import javax.script.SimpleBindings import javax.script.SimpleBindings
@Parcelize @Parcelize

@ -4,7 +4,7 @@ import android.os.Parcelable
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Index import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize
@Entity(tableName = "bookmarks", indices = [(Index(value = ["time"], unique = true))]) @Entity(tableName = "bookmarks", indices = [(Index(value = ["time"], unique = true))])

@ -6,7 +6,7 @@ import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Index import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
import java.util.regex.Pattern import java.util.regex.Pattern
import java.util.regex.PatternSyntaxException import java.util.regex.PatternSyntaxException
@ -43,17 +43,17 @@ data class ReplaceRule(
fun isValid(): Boolean{ fun isValid(): Boolean{
if (TextUtils.isEmpty(pattern)){ if (TextUtils.isEmpty(pattern)){
return false; return false
} }
//判断正则表达式是否正确 //判断正则表达式是否正确
if (isRegex){ if (isRegex){
try { try {
Pattern.compile(pattern); Pattern.compile(pattern)
} }
catch (ex: PatternSyntaxException){ catch (ex: PatternSyntaxException){
return false; return false
} }
} }
return true; return true
} }
} }

@ -11,7 +11,7 @@ import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore import io.legado.app.help.http.CookieStore
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
import java.util.* import java.util.*
import javax.script.SimpleBindings import javax.script.SimpleBindings

@ -4,8 +4,8 @@ import android.os.Parcelable
import androidx.room.* import androidx.room.*
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize
@Entity( @Entity(

@ -4,7 +4,7 @@ import android.os.Parcelable
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Index import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize import kotlinx.parcelize.Parcelize
@Parcelize @Parcelize

@ -4,7 +4,6 @@ import android.graphics.Color
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Parcelable
import androidx.annotation.Keep import androidx.annotation.Keep
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
@ -12,7 +11,6 @@ import io.legado.app.constant.PreferKey
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.parcel.Parcelize
import java.io.File import java.io.File
/** /**
@ -358,7 +356,6 @@ object ReadBookConfig {
} }
@Keep @Keep
@Parcelize
class Config( class Config(
var name: String = "", var name: String = "",
var bgStr: String = "#EEEEEE",//白天背景 var bgStr: String = "#EEEEEE",//白天背景
@ -409,7 +406,7 @@ object ReadBookConfig {
var tipColor: Int = 0, var tipColor: Int = 0,
var headerMode: Int = 0, var headerMode: Int = 0,
var footerMode: Int = 0 var footerMode: Int = 0
) : Parcelable { ) {
fun setCurTextColor(color: Int) { fun setCurTextColor(color: Int) {
when { when {

@ -24,7 +24,6 @@ import io.legado.app.help.AppConfig
import io.legado.app.utils.ColorUtils import io.legado.app.utils.ColorUtils
import io.legado.app.utils.dp import io.legado.app.utils.dp
import io.legado.app.utils.getCompatColor import io.legado.app.utils.getCompatColor
import kotlinx.android.synthetic.main.activity_main.view.*
import org.jetbrains.anko.backgroundColor import org.jetbrains.anko.backgroundColor
@ -258,7 +257,7 @@ object ATH {
val textColor = context.getSecondaryTextColor(textIsDark) val textColor = context.getSecondaryTextColor(textIsDark)
val colorStateList = Selector.colorBuild() val colorStateList = Selector.colorBuild()
.setDefaultColor(textColor) .setDefaultColor(textColor)
.setSelectedColor(ThemeStore.accentColor(bottom_navigation_view.context)).create() .setSelectedColor(ThemeStore.accentColor(context)).create()
itemIconTintList = colorStateList itemIconTintList = colorStateList
itemTextColor = colorStateList itemTextColor = colorStateList
} }

@ -8,34 +8,34 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.databinding.ActivityAboutBinding
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
import kotlinx.android.synthetic.main.activity_about.*
import org.jetbrains.anko.share import org.jetbrains.anko.share
class AboutActivity : BaseActivity(R.layout.activity_about) { class AboutActivity : BaseActivity<ActivityAboutBinding>() {
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
ll_about.background = ATH.getDialogBackground() binding.llAbout.background = ATH.getDialogBackground()
val fTag = "aboutFragment" val fTag = "aboutFragment"
var aboutFragment = supportFragmentManager.findFragmentByTag(fTag) var aboutFragment = supportFragmentManager.findFragmentByTag(fTag)
if (aboutFragment == null) aboutFragment = AboutFragment() if (aboutFragment == null) aboutFragment = AboutFragment()
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.fl_fragment, aboutFragment, fTag) .replace(R.id.fl_fragment, aboutFragment, fTag)
.commit() .commit()
tv_app_summary.post { binding.tvAppSummary.post {
try { try {
val span = ForegroundColorSpan(accentColor) val span = ForegroundColorSpan(accentColor)
val spannableString = SpannableString(tv_app_summary.text) val spannableString = SpannableString(binding.tvAppSummary.text)
val gzh = getString(R.string.legado_gzh) val gzh = getString(R.string.legado_gzh)
val start = spannableString.indexOf(gzh) val start = spannableString.indexOf(gzh)
spannableString.setSpan( spannableString.setSpan(
span, start, start + gzh.length, span, start, start + gzh.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
) )
tv_app_summary.text = spannableString binding.tvAppSummary.text = spannableString
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }

@ -4,13 +4,14 @@ package io.legado.app.ui.about
import android.os.Bundle import android.os.Bundle
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.databinding.ActivityDonateBinding
/** /**
* Created by GKF on 2018/1/13. * Created by GKF on 2018/1/13.
* 捐赠页面 * 捐赠页面
*/ */
class DonateActivity : BaseActivity(R.layout.activity_donate) { class DonateActivity : BaseActivity<ActivityDonateBinding>() {
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
val fTag = "donateFragment" val fTag = "donateFragment"

@ -8,17 +8,16 @@ import io.legado.app.base.BaseActivity
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.ReadRecordShow import io.legado.app.data.entities.ReadRecordShow
import io.legado.app.databinding.ActivityReadRecordBinding
import io.legado.app.databinding.ItemReadRecordBinding
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import kotlinx.android.synthetic.main.activity_read_record.*
import kotlinx.android.synthetic.main.item_read_record.*
import kotlinx.android.synthetic.main.item_read_record.view.*
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
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) { class ReadRecordActivity : BaseActivity<ActivityReadRecordBinding>() {
lateinit var adapter: RecordAdapter lateinit var adapter: RecordAdapter
@ -28,10 +27,10 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
} }
private fun initView() { private fun initView() {
tv_book_name.setText(R.string.all_read_time) binding.readRecord.tvBookName.setText(R.string.all_read_time)
adapter = RecordAdapter(this) adapter = RecordAdapter(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
iv_remove.onClick { binding.readRecord.ivRemove.onClick {
alert(R.string.delete, R.string.sure_del) { alert(R.string.delete, R.string.sure_del) {
okButton { okButton {
App.db.readRecordDao().clear() App.db.readRecordDao().clear()
@ -46,7 +45,7 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
launch(IO) { launch(IO) {
val allTime = App.db.readRecordDao().allTime val allTime = App.db.readRecordDao().allTime
withContext(Main) { withContext(Main) {
tv_read_time.text = formatDuring(allTime) binding.readRecord.tvReadTime.text = formatDuring(allTime)
} }
val readRecords = App.db.readRecordDao().allShow val readRecords = App.db.readRecordDao().allShow
withContext(Main) { withContext(Main) {
@ -63,15 +62,15 @@ class ReadRecordActivity : BaseActivity(R.layout.activity_read_record) {
item: ReadRecordShow, item: ReadRecordShow,
payloads: MutableList<Any> payloads: MutableList<Any>
) { ) {
holder.itemView.apply { ItemReadRecordBinding.bind(holder.itemView).apply {
tv_book_name.text = item.bookName tvBookName.text = item.bookName
tv_read_time.text = formatDuring(item.readTime) tvReadTime.text = formatDuring(item.readTime)
} }
} }
override fun registerListener(holder: ItemViewHolder) { override fun registerListener(holder: ItemViewHolder) {
holder.itemView.apply { ItemReadRecordBinding.bind(holder.itemView).apply {
iv_remove.onClick { ivRemove.onClick {
alert(R.string.delete, R.string.sure_del) { alert(R.string.delete, R.string.sure_del) {
okButton { okButton {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {

@ -2,33 +2,32 @@ package io.legado.app.ui.association
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.databinding.ActivityTranslucenceBinding
import io.legado.app.ui.main.MainActivity import io.legado.app.ui.main.MainActivity
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_translucence.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class FileAssociationActivity : VMBaseActivity<FileAssociationViewModel>( class FileAssociationActivity :
R.layout.activity_translucence, VMBaseActivity<ActivityTranslucenceBinding, FileAssociationViewModel>(
theme = Theme.Transparent theme = Theme.Transparent
) { ) {
override val viewModel: FileAssociationViewModel override val viewModel: FileAssociationViewModel
get() = getViewModel(FileAssociationViewModel::class.java) get() = getViewModel(FileAssociationViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() binding.rotateLoading.show()
viewModel.errorLiveData.observe(this, { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
toast(it) toast(it)
finish() finish()
}) })
viewModel.successLiveData.observe(this, { viewModel.successLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
startActivity(it) startActivity(it)
finish() finish()
}) })

@ -4,29 +4,29 @@ import android.os.Bundle
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.databinding.ActivityTranslucenceBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_translucence.*
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class ImportBookSourceActivity : VMBaseActivity<ImportBookSourceViewModel>( class ImportBookSourceActivity :
R.layout.activity_translucence, VMBaseActivity<ActivityTranslucenceBinding, ImportBookSourceViewModel>(
theme = Theme.Transparent theme = Theme.Transparent
) { ) {
override val viewModel: ImportBookSourceViewModel override val viewModel: ImportBookSourceViewModel
get() = getViewModel(ImportBookSourceViewModel::class.java) get() = getViewModel(ImportBookSourceViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() binding.rotateLoading.show()
viewModel.errorLiveData.observe(this, { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, { viewModel.successLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
if (it > 0) { if (it > 0) {
successDialog() successDialog()
} else { } else {
@ -61,7 +61,7 @@ class ImportBookSourceActivity : VMBaseActivity<ImportBookSourceViewModel>(
} }
} }
else -> { else -> {
rotate_loading.hide() binding.rotateLoading.hide()
toast(R.string.wrong_format) toast(R.string.wrong_format)
finish() finish()
} }

@ -2,32 +2,35 @@ package io.legado.app.ui.association
import android.os.Bundle import android.os.Bundle
import io.legado.app.App import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.data.entities.ReplaceRule import io.legado.app.data.entities.ReplaceRule
import io.legado.app.databinding.ActivityTranslucenceBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_translucence.*
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class ImportReplaceRuleActivity : VMBaseActivity<ImportReplaceRuleViewModel>( class ImportReplaceRuleActivity :
R.layout.activity_translucence, VMBaseActivity<ActivityTranslucenceBinding, ImportReplaceRuleViewModel>(
theme = Theme.Transparent theme = Theme.Transparent
) { ) {
override val viewModel: ImportReplaceRuleViewModel override val viewModel: ImportReplaceRuleViewModel
get() = getViewModel(ImportReplaceRuleViewModel::class.java) get() = getViewModel(ImportReplaceRuleViewModel::class.java)
override fun getViewBinding(): ActivityTranslucenceBinding {
return ActivityTranslucenceBinding.inflate(layoutInflater)
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() binding.rotateLoading.show()
viewModel.errorLiveData.observe(this, { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, { viewModel.successLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
if (it.size > 0) { if (it.size > 0) {
successDialog(it) successDialog(it)
} else { } else {
@ -62,7 +65,7 @@ class ImportReplaceRuleActivity : VMBaseActivity<ImportReplaceRuleViewModel>(
} }
} }
else -> { else -> {
rotate_loading.hide() binding.rotateLoading.hide()
toast("格式不对") toast("格式不对")
finish() finish()
} }

@ -4,28 +4,28 @@ import android.os.Bundle
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.databinding.ActivityTranslucenceBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_translucence.*
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class ImportRssSourceActivity : VMBaseActivity<ImportRssSourceViewModel>( class ImportRssSourceActivity :
R.layout.activity_translucence, VMBaseActivity<ActivityTranslucenceBinding, ImportRssSourceViewModel>(
theme = Theme.Transparent theme = Theme.Transparent
) { ) {
override val viewModel: ImportRssSourceViewModel override val viewModel: ImportRssSourceViewModel
get() = getViewModel(ImportRssSourceViewModel::class.java) get() = getViewModel(ImportRssSourceViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
rotate_loading.show() binding.rotateLoading.show()
viewModel.errorLiveData.observe(this, { viewModel.errorLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
errorDialog(it) errorDialog(it)
}) })
viewModel.successLiveData.observe(this, { viewModel.successLiveData.observe(this, {
rotate_loading.hide() binding.rotateLoading.hide()
if (it > 0) { if (it > 0) {
successDialog() successDialog()
} else { } else {
@ -60,7 +60,7 @@ class ImportRssSourceActivity : VMBaseActivity<ImportRssSourceViewModel>(
} }
} }
else -> { else -> {
rotate_loading.hide() binding.rotateLoading.hide()
toast(R.string.wrong_format) toast(R.string.wrong_format)
finish() finish()
} }

@ -17,6 +17,7 @@ import io.legado.app.constant.EventBus
import io.legado.app.constant.Status import io.legado.app.constant.Status
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.databinding.ActivityAudioPlayBinding
import io.legado.app.help.BlurTransformation import io.legado.app.help.BlurTransformation
import io.legado.app.help.ImageLoader import io.legado.app.help.ImageLoader
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
@ -25,7 +26,6 @@ import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.toc.ChapterListActivity import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.ui.widget.image.CoverImageView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_audio_play.*
import org.apache.commons.lang3.time.DateFormatUtils import org.apache.commons.lang3.time.DateFormatUtils
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.sdk27.listeners.onLongClick import org.jetbrains.anko.sdk27.listeners.onLongClick
@ -33,7 +33,7 @@ import org.jetbrains.anko.startActivityForResult
class AudioPlayActivity : class AudioPlayActivity :
VMBaseActivity<AudioPlayViewModel>(R.layout.activity_audio_play, toolBarTheme = Theme.Dark), VMBaseActivity<ActivityAudioPlayBinding, AudioPlayViewModel>(toolBarTheme = Theme.Dark),
ChangeSourceDialog.CallBack { ChangeSourceDialog.CallBack {
override val viewModel: AudioPlayViewModel override val viewModel: AudioPlayViewModel
@ -43,8 +43,8 @@ class AudioPlayActivity :
private var adjustProgress = false private var adjustProgress = false
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
title_bar.transparent() binding.titleBar.transparent()
AudioPlay.titleData.observe(this, { title_bar.title = it }) AudioPlay.titleData.observe(this, { binding.titleBar.title = it })
AudioPlay.coverData.observe(this, { upCover(it) }) AudioPlay.coverData.observe(this, { upCover(it) })
viewModel.initData(intent) viewModel.initData(intent)
initView() initView()
@ -65,22 +65,22 @@ class AudioPlayActivity :
} }
private fun initView() { private fun initView() {
fab_play_stop.onClick { binding.fabPlayStop.onClick {
playButton() playButton()
} }
fab_play_stop.onLongClick { binding.fabPlayStop.onLongClick {
AudioPlay.stop(this) AudioPlay.stop(this)
true true
} }
iv_skip_next.onClick { binding.ivSkipNext.onClick {
AudioPlay.next(this) AudioPlay.next(this)
} }
iv_skip_previous.onClick { binding.ivSkipPrevious.onClick {
AudioPlay.prev(this) AudioPlay.prev(this)
} }
player_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.playerProgress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
tv_dur_time.text = DateFormatUtils.format(progress.toLong(), "mm:ss") binding.tvDurTime.text = DateFormatUtils.format(progress.toLong(), "mm:ss")
} }
override fun onStartTrackingTouch(seekBar: SeekBar?) { override fun onStartTrackingTouch(seekBar: SeekBar?) {
@ -89,10 +89,10 @@ class AudioPlayActivity :
override fun onStopTrackingTouch(seekBar: SeekBar?) { override fun onStopTrackingTouch(seekBar: SeekBar?) {
adjustProgress = false adjustProgress = false
AudioPlay.adjustProgress(this@AudioPlayActivity, player_progress.progress) AudioPlay.adjustProgress(this@AudioPlayActivity, binding.playerProgress.progress)
} }
}) })
iv_chapter.onClick { binding.ivChapter.onClick {
AudioPlay.book?.let { AudioPlay.book?.let {
startActivityForResult<ChapterListActivity>( startActivityForResult<ChapterListActivity>(
requestCodeChapter, requestCodeChapter,
@ -101,13 +101,13 @@ class AudioPlayActivity :
} }
} }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
iv_fast_rewind.invisible() binding.ivFastRewind.invisible()
iv_fast_forward.invisible() binding.ivFastForward.invisible()
} }
iv_fast_forward.onClick { binding.ivFastForward.onClick {
AudioPlay.adjustSpeed(this, 0.1f) AudioPlay.adjustSpeed(this, 0.1f)
} }
iv_fast_rewind.onClick { binding.ivFastRewind.onClick {
AudioPlay.adjustSpeed(this, -0.1f) AudioPlay.adjustSpeed(this, -0.1f)
} }
} }
@ -116,12 +116,12 @@ class AudioPlayActivity :
ImageLoader.load(this, path) ImageLoader.load(this, path)
.placeholder(CoverImageView.defaultDrawable) .placeholder(CoverImageView.defaultDrawable)
.error(CoverImageView.defaultDrawable) .error(CoverImageView.defaultDrawable)
.into(iv_cover) .into(binding.ivCover)
ImageLoader.load(this, path) ImageLoader.load(this, path)
.transition(DrawableTransitionOptions.withCrossFade(1500)) .transition(DrawableTransitionOptions.withCrossFade(1500))
.thumbnail(defaultCover()) .thumbnail(defaultCover())
.apply(bitmapTransform(BlurTransformation(this, 25))) .apply(bitmapTransform(BlurTransformation(this, 25)))
.into(iv_bg) .into(binding.ivBg)
} }
private fun defaultCover(): RequestBuilder<Drawable> { private fun defaultCover(): RequestBuilder<Drawable> {
@ -190,26 +190,26 @@ class AudioPlayActivity :
observeEventSticky<Int>(EventBus.AUDIO_STATE) { observeEventSticky<Int>(EventBus.AUDIO_STATE) {
AudioPlay.status = it AudioPlay.status = it
if (it == Status.PLAY) { if (it == Status.PLAY) {
fab_play_stop.setImageResource(R.drawable.ic_pause_24dp) binding.fabPlayStop.setImageResource(R.drawable.ic_pause_24dp)
} else { } else {
fab_play_stop.setImageResource(R.drawable.ic_play_24dp) binding.fabPlayStop.setImageResource(R.drawable.ic_play_24dp)
} }
} }
observeEventSticky<String>(EventBus.AUDIO_SUB_TITLE) { observeEventSticky<String>(EventBus.AUDIO_SUB_TITLE) {
tv_sub_title.text = it binding.tvSubTitle.text = it
} }
observeEventSticky<Int>(EventBus.AUDIO_SIZE) { observeEventSticky<Int>(EventBus.AUDIO_SIZE) {
player_progress.max = it binding.playerProgress.max = it
tv_all_time.text = DateFormatUtils.format(it.toLong(), "mm:ss") binding.tvAllTime.text = DateFormatUtils.format(it.toLong(), "mm:ss")
} }
observeEventSticky<Int>(EventBus.AUDIO_PROGRESS) { observeEventSticky<Int>(EventBus.AUDIO_PROGRESS) {
AudioPlay.durPageIndex = it AudioPlay.durPageIndex = it
if (!adjustProgress) player_progress.progress = it if (!adjustProgress) binding.playerProgress.progress = it
tv_dur_time.text = DateFormatUtils.format(it.toLong(), "mm:ss") binding.tvDurTime.text = DateFormatUtils.format(it.toLong(), "mm:ss")
} }
observeEventSticky<Float>(EventBus.AUDIO_SPEED) { observeEventSticky<Float>(EventBus.AUDIO_SPEED) {
tv_speed.text = String.format("%.1fX", it) binding.tvSpeed.text = String.format("%.1fX", it)
tv_speed.visible() binding.tvSpeed.visible()
} }
} }

@ -14,6 +14,7 @@ import io.legado.app.constant.AppConst
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.ActivityArrangeBookBinding
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.ui.book.group.GroupManageDialog import io.legado.app.ui.book.group.GroupManageDialog
@ -24,10 +25,9 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.getPrefInt import io.legado.app.utils.getPrefInt
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_arrange_book.*
class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activity_arrange_book), class ArrangeBookActivity : VMBaseActivity<ActivityArrangeBookBinding, ArrangeBookViewModel>(),
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
SelectActionBar.CallBack, SelectActionBar.CallBack,
ArrangeBookAdapter.CallBack, ArrangeBookAdapter.CallBack,
@ -45,7 +45,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
groupId = intent.getLongExtra("groupId", -1) groupId = intent.getLongExtra("groupId", -1)
title_bar.subtitle = intent.getStringExtra("groupName") ?: getString(R.string.all) binding.titleBar.subtitle = intent.getStringExtra("groupName") ?: getString(R.string.all)
initView() initView()
initGroupData() initGroupData()
initBookData() initBookData()
@ -75,24 +75,24 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
} }
private fun initView() { private fun initView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
adapter = ArrangeBookAdapter(this, this) adapter = ArrangeBookAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
val itemTouchCallback = ItemTouchCallback(adapter) val itemTouchCallback = ItemTouchCallback(adapter)
itemTouchCallback.isCanDrag = getPrefInt(PreferKey.bookshelfSort) == 3 itemTouchCallback.isCanDrag = getPrefInt(PreferKey.bookshelfSort) == 3
val dragSelectTouchHelper: DragSelectTouchHelper = val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50) DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view) dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
// When this page is opened, it is in selection mode // When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect() dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it. // Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view) ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
select_action_bar.setMainActionText(R.string.move_to_group) binding.selectActionBar.setMainActionText(R.string.move_to_group)
select_action_bar.inflateMenu(R.menu.arrange_book_sel) binding.selectActionBar.inflateMenu(R.menu.arrange_book_sel)
select_action_bar.setOnMenuItemClickListener(this) binding.selectActionBar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this) binding.selectActionBar.setCallBack(this)
} }
private fun initGroupData() { private fun initGroupData() {
@ -133,7 +133,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
R.id.menu_group_manage -> GroupManageDialog() R.id.menu_group_manage -> GroupManageDialog()
.show(supportFragmentManager, "groupManage") .show(supportFragmentManager, "groupManage")
else -> if (item.groupId == R.id.menu_group) { else -> if (item.groupId == R.id.menu_group) {
title_bar.subtitle = item.title binding.titleBar.subtitle = item.title
groupId = App.db.bookGroupDao().getByName(item.title.toString())?.groupId ?: 0 groupId = App.db.bookGroupDao().getByName(item.title.toString())?.groupId ?: 0
initBookData() initBookData()
} }
@ -195,7 +195,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
} }
override fun upSelectCount() { override fun upSelectCount() {
select_action_bar.upCountView(adapter.selectedBooks().size, adapter.getItems().size) binding.selectActionBar.upCountView(adapter.selectedBooks().size, adapter.getItems().size)
} }
override fun updateBook(vararg book: Book) { override fun updateBook(vararg book: Book) {

@ -17,13 +17,13 @@ import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookGroup import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.ActivityCacheBookBinding
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.service.help.CacheBook import io.legado.app.service.help.CacheBook
import io.legado.app.ui.filepicker.FilePicker import io.legado.app.ui.filepicker.FilePicker
import io.legado.app.ui.filepicker.FilePickerDialog import io.legado.app.ui.filepicker.FilePickerDialog
import io.legado.app.ui.widget.dialog.TextListDialog import io.legado.app.ui.widget.dialog.TextListDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_download.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -32,7 +32,7 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download), class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>(),
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
CacheAdapter.CallBack { CacheAdapter.CallBack {
private val exportRequestCode = 32 private val exportRequestCode = 32
@ -50,7 +50,7 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
groupId = intent.getLongExtra("groupId", -1) groupId = intent.getLongExtra("groupId", -1)
title_bar.subtitle = intent.getStringExtra("groupName") ?: getString(R.string.all) binding.titleBar.subtitle = intent.getStringExtra("groupName") ?: getString(R.string.all)
initRecyclerView() initRecyclerView()
initGroupData() initGroupData()
initBookData() initBookData()
@ -96,7 +96,7 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
TextListDialog.show(supportFragmentManager, getString(R.string.log), CacheBook.logs) TextListDialog.show(supportFragmentManager, getString(R.string.log), CacheBook.logs)
} }
else -> if (item.groupId == R.id.menu_group) { else -> if (item.groupId == R.id.menu_group) {
title_bar.subtitle = item.title binding.titleBar.subtitle = item.title
groupId = App.db.bookGroupDao().getByName(item.title.toString())?.groupId ?: 0 groupId = App.db.bookGroupDao().getByName(item.title.toString())?.groupId ?: 0
initBookData() initBookData()
} }
@ -105,9 +105,9 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
} }
private fun initRecyclerView() { private fun initRecyclerView() {
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = CacheAdapter(this, this) adapter = CacheAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
} }
private fun initBookData() { private fun initBookData() {
@ -194,10 +194,10 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
private fun startExport(path: String) { private fun startExport(path: String) {
adapter.getItem(exportPosition)?.let { book -> adapter.getItem(exportPosition)?.let { book ->
Snackbar.make(title_bar, R.string.exporting, Snackbar.LENGTH_INDEFINITE) Snackbar.make(binding.titleBar, R.string.exporting, Snackbar.LENGTH_INDEFINITE)
.show() .show()
viewModel.export(path, book) { viewModel.export(path, book) {
title_bar.snackbar(it) binding.titleBar.snackbar(it)
} }
} }
} }

@ -5,16 +5,16 @@ import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import kotlinx.android.synthetic.main.item_cover.view.* import io.legado.app.databinding.ItemCoverBinding
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
class CoverAdapter(context: Context, val callBack: CallBack) : class CoverAdapter(context: Context, val callBack: CallBack) :
SimpleRecyclerAdapter<SearchBook>(context, R.layout.item_cover) { SimpleRecyclerAdapter<SearchBook>(context, R.layout.item_cover) {
override fun convert(holder: ItemViewHolder, item: SearchBook, payloads: MutableList<Any>) { override fun convert(holder: ItemViewHolder, item: SearchBook, payloads: MutableList<Any>) {
with(holder.itemView) { ItemCoverBinding.bind(holder.itemView).apply {
iv_cover.load(item.coverUrl, item.name, item.author) ivCover.load(item.coverUrl, item.name, item.author)
tv_source.text = item.originName tvSource.text = item.originName
} }
} }

@ -7,14 +7,14 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.databinding.ActivityExploreShowBinding
import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.widget.recycler.LoadMoreView import io.legado.app.ui.widget.recycler.LoadMoreView
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_explore_show.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
class ExploreShowActivity : VMBaseActivity<ExploreShowViewModel>(R.layout.activity_explore_show), class ExploreShowActivity : VMBaseActivity<ActivityExploreShowBinding, ExploreShowViewModel>(),
ExploreShowAdapter.CallBack { ExploreShowAdapter.CallBack {
override val viewModel: ExploreShowViewModel override val viewModel: ExploreShowViewModel
get() = getViewModel(ExploreShowViewModel::class.java) get() = getViewModel(ExploreShowViewModel::class.java)
@ -24,7 +24,7 @@ class ExploreShowActivity : VMBaseActivity<ExploreShowViewModel>(R.layout.activi
private var isLoading = true private var isLoading = true
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
title_bar.title = intent.getStringExtra("exploreName") binding.titleBar.title = intent.getStringExtra("exploreName")
initRecyclerView() initRecyclerView()
viewModel.booksData.observe(this, { upData(it) }) viewModel.booksData.observe(this, { upData(it) })
viewModel.initData(intent) viewModel.initData(intent)
@ -32,9 +32,9 @@ class ExploreShowActivity : VMBaseActivity<ExploreShowViewModel>(R.layout.activi
private fun initRecyclerView() { private fun initRecyclerView() {
adapter = ExploreShowAdapter(this, this) adapter = ExploreShowAdapter(this, this)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
loadMoreView = LoadMoreView(this) loadMoreView = LoadMoreView(this)
adapter.addFooterView(loadMoreView) adapter.addFooterView(loadMoreView)
loadMoreView.startLoad() loadMoreView.startLoad()
@ -45,7 +45,7 @@ class ExploreShowActivity : VMBaseActivity<ExploreShowViewModel>(R.layout.activi
isLoading = true isLoading = true
} }
} }
recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() { binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
if (!recyclerView.canScrollVertically(1)) { if (!recyclerView.canScrollVertically(1)) {

@ -18,6 +18,7 @@ import io.legado.app.constant.BookType
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.databinding.ActivityBookInfoBinding
import io.legado.app.help.BlurTransformation import io.legado.app.help.BlurTransformation
import io.legado.app.help.ImageLoader import io.legado.app.help.ImageLoader
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
@ -36,7 +37,6 @@ import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.ChapterListActivity import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.ui.widget.image.CoverImageView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_info.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
@ -44,7 +44,7 @@ import org.jetbrains.anko.toast
class BookInfoActivity : class BookInfoActivity :
VMBaseActivity<BookInfoViewModel>(R.layout.activity_book_info, toolBarTheme = Theme.Dark), VMBaseActivity<ActivityBookInfoBinding, BookInfoViewModel>(toolBarTheme = Theme.Dark),
GroupSelectDialog.CallBack, GroupSelectDialog.CallBack,
ChapterListAdapter.CallBack, ChapterListAdapter.CallBack,
ChangeSourceDialog.CallBack, ChangeSourceDialog.CallBack,
@ -59,13 +59,13 @@ class BookInfoActivity :
@SuppressLint("PrivateResource") @SuppressLint("PrivateResource")
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
title_bar.transparent() binding.titleBar.transparent()
arc_view.setBgColor(backgroundColor) binding.arcView.setBgColor(backgroundColor)
ll_info.setBackgroundColor(backgroundColor) binding.llInfo.setBackgroundColor(backgroundColor)
scroll_view.setBackgroundColor(backgroundColor) binding.scrollView.setBackgroundColor(backgroundColor)
fl_action.setBackgroundColor(bottomBackground) binding.flAction.setBackgroundColor(bottomBackground)
tv_shelf.setTextColor(getPrimaryTextColor(ColorUtils.isColorLight(bottomBackground))) binding.tvShelf.setTextColor(getPrimaryTextColor(ColorUtils.isColorLight(bottomBackground)))
tv_toc.text = getString(R.string.toc_s, getString(R.string.loading)) binding.tvToc.text = getString(R.string.toc_s, getString(R.string.loading))
viewModel.bookData.observe(this, { showBook(it) }) viewModel.bookData.observe(this, { showBook(it) })
viewModel.chapterListData.observe(this, { upLoading(false, it) }) viewModel.chapterListData.observe(this, { upLoading(false, it) })
viewModel.initData(intent) viewModel.initData(intent)
@ -133,29 +133,29 @@ class BookInfoActivity :
private fun showBook(book: Book) { private fun showBook(book: Book) {
showCover(book) showCover(book)
tv_name.text = book.name binding.tvName.text = book.name
tv_author.text = getString(R.string.author_show, book.getRealAuthor()) binding.tvAuthor.text = getString(R.string.author_show, book.getRealAuthor())
tv_origin.text = getString(R.string.origin_show, book.originName) binding.tvOrigin.text = getString(R.string.origin_show, book.originName)
tv_lasted.text = getString(R.string.lasted_show, book.latestChapterTitle) binding.tvLasted.text = getString(R.string.lasted_show, book.latestChapterTitle)
tv_intro.text = book.getDisplayIntro() binding.tvIntro.text = book.getDisplayIntro()
upTvBookshelf() upTvBookshelf()
val kinds = book.getKindList() val kinds = book.getKindList()
if (kinds.isEmpty()) { if (kinds.isEmpty()) {
lb_kind.gone() binding.lbKind.gone()
} else { } else {
lb_kind.visible() binding.lbKind.visible()
lb_kind.setLabels(kinds) binding.lbKind.setLabels(kinds)
} }
upGroup(book.group) upGroup(book.group)
} }
private fun showCover(book: Book) { private fun showCover(book: Book) {
iv_cover.load(book.getDisplayCover(), book.name, book.author) binding.ivCover.load(book.getDisplayCover(), book.name, book.author)
ImageLoader.load(this, book.getDisplayCover()) ImageLoader.load(this, book.getDisplayCover())
.transition(DrawableTransitionOptions.withCrossFade(1500)) .transition(DrawableTransitionOptions.withCrossFade(1500))
.thumbnail(defaultCover()) .thumbnail(defaultCover())
.apply(bitmapTransform(BlurTransformation(this, 25))) .apply(bitmapTransform(BlurTransformation(this, 25)))
.into(bg_book) //模糊、渐变、缩小效果 .into(binding.bgBook) //模糊、渐变、缩小效果
} }
private fun defaultCover(): RequestBuilder<Drawable> { private fun defaultCover(): RequestBuilder<Drawable> {
@ -166,18 +166,18 @@ class BookInfoActivity :
private fun upLoading(isLoading: Boolean, chapterList: List<BookChapter>? = null) { private fun upLoading(isLoading: Boolean, chapterList: List<BookChapter>? = null) {
when { when {
isLoading -> { isLoading -> {
tv_toc.text = getString(R.string.toc_s, getString(R.string.loading)) binding.tvToc.text = getString(R.string.toc_s, getString(R.string.loading))
} }
chapterList.isNullOrEmpty() -> { chapterList.isNullOrEmpty() -> {
tv_toc.text = getString(R.string.toc_s, getString(R.string.error_load_toc)) binding.tvToc.text = getString(R.string.toc_s, getString(R.string.error_load_toc))
} }
else -> { else -> {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
if (it.durChapterIndex < chapterList.size) { if (it.durChapterIndex < chapterList.size) {
tv_toc.text = binding.tvToc.text =
getString(R.string.toc_s, chapterList[it.durChapterIndex].title) getString(R.string.toc_s, chapterList[it.durChapterIndex].title)
} else { } else {
tv_toc.text = getString(R.string.toc_s, chapterList.last().title) binding.tvToc.text = getString(R.string.toc_s, chapterList.last().title)
} }
} }
} }
@ -186,34 +186,34 @@ class BookInfoActivity :
private fun upTvBookshelf() { private fun upTvBookshelf() {
if (viewModel.inBookshelf) { if (viewModel.inBookshelf) {
tv_shelf.text = getString(R.string.remove_from_bookshelf) binding.tvShelf.text = getString(R.string.remove_from_bookshelf)
} else { } else {
tv_shelf.text = getString(R.string.add_to_shelf) binding.tvShelf.text = getString(R.string.add_to_shelf)
} }
} }
private fun upGroup(groupId: Long) { private fun upGroup(groupId: Long) {
viewModel.loadGroup(groupId) { viewModel.loadGroup(groupId) {
if (it.isNullOrEmpty()) { if (it.isNullOrEmpty()) {
tv_group.text = getString(R.string.group_s, getString(R.string.no_group)) binding.tvGroup.text = getString(R.string.group_s, getString(R.string.no_group))
} else { } else {
tv_group.text = getString(R.string.group_s, it) binding.tvGroup.text = getString(R.string.group_s, it)
} }
} }
} }
private fun initOnClick() { private fun initOnClick() {
iv_cover.onClick { binding.ivCover.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
ChangeCoverDialog.show(supportFragmentManager, it.name, it.author) ChangeCoverDialog.show(supportFragmentManager, it.name, it.author)
} }
} }
tv_read.onClick { binding.tvRead.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
readBook(it) readBook(it)
} }
} }
tv_shelf.onClick { binding.tvShelf.onClick {
if (viewModel.inBookshelf) { if (viewModel.inBookshelf) {
deleteBook() deleteBook()
} else { } else {
@ -222,17 +222,17 @@ class BookInfoActivity :
} }
} }
} }
tv_origin.onClick { binding.tvOrigin.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
startActivity<BookSourceEditActivity>(Pair("data", it.origin)) startActivity<BookSourceEditActivity>(Pair("data", it.origin))
} }
} }
tv_change_source.onClick { binding.tvChangeSource.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
ChangeSourceDialog.show(supportFragmentManager, it.name, it.author) ChangeSourceDialog.show(supportFragmentManager, it.name, it.author)
} }
} }
tv_toc_view.onClick { binding.tvTocView.onClick {
if (!viewModel.inBookshelf) { if (!viewModel.inBookshelf) {
viewModel.saveBook { viewModel.saveBook {
viewModel.saveChapterList { viewModel.saveChapterList {
@ -243,15 +243,15 @@ class BookInfoActivity :
openChapterList() openChapterList()
} }
} }
tv_change_group.onClick { binding.tvChangeGroup.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
GroupSelectDialog.show(supportFragmentManager, it.group) GroupSelectDialog.show(supportFragmentManager, it.group)
} }
} }
tv_author.onClick { binding.tvAuthor.onClick {
startActivity<SearchActivity>(Pair("key", viewModel.bookData.value?.author)) startActivity<SearchActivity>(Pair("key", viewModel.bookData.value?.author))
} }
tv_name.onClick { binding.tvName.onClick {
startActivity<SearchActivity>(Pair("key", viewModel.bookData.value?.name)) startActivity<SearchActivity>(Pair("key", viewModel.bookData.value?.name))
} }
} }

@ -10,17 +10,17 @@ import androidx.documentfile.provider.DocumentFile
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.databinding.ActivityBookInfoEditBinding
import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.ui.book.changecover.ChangeCoverDialog import io.legado.app.ui.book.changecover.ChangeCoverDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_info_edit.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import java.io.File import java.io.File
class BookInfoEditActivity : class BookInfoEditActivity :
VMBaseActivity<BookInfoEditViewModel>(R.layout.activity_book_info_edit), VMBaseActivity<ActivityBookInfoEditBinding, BookInfoEditViewModel>(),
ChangeCoverDialog.CallBack { ChangeCoverDialog.CallBack {
private val resultSelectCover = 132 private val resultSelectCover = 132
@ -51,41 +51,41 @@ class BookInfoEditActivity :
} }
private fun initEvent() { private fun initEvent() {
tv_change_cover.onClick { binding.tvChangeCover.onClick {
viewModel.bookData.value?.let { viewModel.bookData.value?.let {
ChangeCoverDialog.show(supportFragmentManager, it.name, it.author) ChangeCoverDialog.show(supportFragmentManager, it.name, it.author)
} }
} }
tv_select_cover.onClick { binding.tvSelectCover.onClick {
selectImage() selectImage()
} }
tv_refresh_cover.onClick { binding.tvRefreshCover.onClick {
viewModel.book?.customCoverUrl = tie_cover_url.text?.toString() viewModel.book?.customCoverUrl = binding.tieCoverUrl.text?.toString()
upCover() upCover()
} }
} }
private fun upView(book: Book) { private fun upView(book: Book) {
tie_book_name.setText(book.name) binding.tieBookName.setText(book.name)
tie_book_author.setText(book.author) binding.tieBookAuthor.setText(book.author)
tie_cover_url.setText(book.getDisplayCover()) binding.tieCoverUrl.setText(book.getDisplayCover())
tie_book_intro.setText(book.getDisplayIntro()) binding.tieBookIntro.setText(book.getDisplayIntro())
upCover() upCover()
} }
private fun upCover() { private fun upCover() {
viewModel.book.let { viewModel.book.let {
iv_cover.load(it?.getDisplayCover(), it?.name, it?.author) binding.ivCover.load(it?.getDisplayCover(), it?.name, it?.author)
} }
} }
private fun saveData() { private fun saveData() {
viewModel.book?.let { book -> viewModel.book?.let { book ->
book.name = tie_book_name.text?.toString() ?: "" book.name = binding.tieBookName.text?.toString() ?: ""
book.author = tie_book_author.text?.toString() ?: "" book.author = binding.tieBookAuthor.text?.toString() ?: ""
val customCoverUrl = tie_cover_url.text?.toString() val customCoverUrl = binding.tieCoverUrl.text?.toString()
book.customCoverUrl = if (customCoverUrl == book.coverUrl) null else customCoverUrl book.customCoverUrl = if (customCoverUrl == book.coverUrl) null else customCoverUrl
book.customIntro = tie_book_intro.text?.toString() book.customIntro = binding.tieBookIntro.text?.toString()
viewModel.saveBook(book) { viewModel.saveBook(book) {
setResult(Activity.RESULT_OK) setResult(Activity.RESULT_OK)
finish() finish()
@ -102,7 +102,7 @@ class BookInfoEditActivity :
override fun coverChangeTo(coverUrl: String) { override fun coverChangeTo(coverUrl: String) {
viewModel.book?.customCoverUrl = coverUrl viewModel.book?.customCoverUrl = coverUrl
tie_cover_url.setText(coverUrl) binding.tieCoverUrl.setText(coverUrl)
upCover() upCover()
} }

@ -15,6 +15,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivityImportBookBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.permission.PermissionsCompat
@ -23,7 +24,6 @@ import io.legado.app.ui.filepicker.FilePicker
import io.legado.app.ui.filepicker.FilePickerDialog import io.legado.app.ui.filepicker.FilePickerDialog
import io.legado.app.ui.widget.SelectActionBar import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_import_book.*
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
@ -36,7 +36,7 @@ import java.util.*
/** /**
* 导入本地书籍界面 * 导入本地书籍界面
*/ */
class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity_import_book), class ImportBookActivity : VMBaseActivity<ActivityImportBookBinding, ImportBookViewModel>(),
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
SelectActionBar.CallBack, SelectActionBar.CallBack,
@ -97,18 +97,18 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} }
private fun initView() { private fun initView() {
lay_top.setBackgroundColor(backgroundColor) binding.layTop.setBackgroundColor(backgroundColor)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ImportBookAdapter(this, this) adapter = ImportBookAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
select_action_bar.setMainActionText(R.string.add_to_shelf) binding.selectActionBar.setMainActionText(R.string.add_to_shelf)
select_action_bar.inflateMenu(R.menu.import_book_sel) binding.selectActionBar.inflateMenu(R.menu.import_book_sel)
select_action_bar.setOnMenuItemClickListener(this) binding.selectActionBar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this) binding.selectActionBar.setCallBack(this)
} }
private fun initEvent() { private fun initEvent() {
tv_go_back.onClick { binding.tvGoBack.onClick {
goBackDir() goBackDir()
} }
} }
@ -125,14 +125,14 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
val lastPath = AppConfig.importBookPath val lastPath = AppConfig.importBookPath
when { when {
lastPath.isNullOrEmpty() -> { lastPath.isNullOrEmpty() -> {
tv_empty_msg.visible() binding.tvEmptyMsg.visible()
FilePicker.selectFolder(this, requestCodeSelectFolder) FilePicker.selectFolder(this, requestCodeSelectFolder)
} }
lastPath.isContentScheme() -> { lastPath.isContentScheme() -> {
val rootUri = Uri.parse(lastPath) val rootUri = Uri.parse(lastPath)
rootDoc = DocumentFile.fromTreeUri(this, rootUri) rootDoc = DocumentFile.fromTreeUri(this, rootUri)
if (rootDoc == null) { if (rootDoc == null) {
tv_empty_msg.visible() binding.tvEmptyMsg.visible()
FilePicker.selectFolder(this, requestCodeSelectFolder) FilePicker.selectFolder(this, requestCodeSelectFolder)
} else { } else {
subDocs.clear() subDocs.clear()
@ -140,11 +140,11 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} }
} }
Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> { Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
tv_empty_msg.visible() binding.tvEmptyMsg.visible()
FilePicker.selectFolder(this, requestCodeSelectFolder) FilePicker.selectFolder(this, requestCodeSelectFolder)
} }
else -> { else -> {
tv_empty_msg.visible() binding.tvEmptyMsg.visible()
PermissionsCompat.Builder(this) PermissionsCompat.Builder(this)
.addPermissions(*Permissions.Group.STORAGE) .addPermissions(*Permissions.Group.STORAGE)
.rationale(R.string.tip_perm_request_storage) .rationale(R.string.tip_perm_request_storage)
@ -167,14 +167,14 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} }
private fun upDocs(rootDoc: DocumentFile) { private fun upDocs(rootDoc: DocumentFile) {
tv_empty_msg.gone() binding.tvEmptyMsg.gone()
var path = rootDoc.name.toString() + File.separator var path = rootDoc.name.toString() + File.separator
var lastDoc = rootDoc var lastDoc = rootDoc
for (doc in subDocs) { for (doc in subDocs) {
lastDoc = doc lastDoc = doc
path = path + doc.name + File.separator path = path + doc.name + File.separator
} }
tv_path.text = path binding.tvPath.text = path
adapter.selectedUris.clear() adapter.selectedUris.clear()
adapter.clearItems() adapter.clearItems()
launch(IO) { launch(IO) {
@ -198,8 +198,8 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} }
private fun upFiles() { private fun upFiles() {
tv_empty_msg.gone() binding.tvEmptyMsg.gone()
tv_path.text = path.replace(sdPath, "SD") binding.tvPath.text = path.replace(sdPath, "SD")
val docList = arrayListOf<DocItem>() val docList = arrayListOf<DocItem>()
File(path).listFiles()?.forEach { File(path).listFiles()?.forEach {
if (it.isDirectory) { if (it.isDirectory) {
@ -238,11 +238,11 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
rootDoc?.let { doc -> rootDoc?.let { doc ->
adapter.clearItems() adapter.clearItems()
val lastDoc = subDocs.lastOrNull() ?: doc val lastDoc = subDocs.lastOrNull() ?: doc
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.isAutoLoading = true
launch(IO) { launch(IO) {
viewModel.scanDoc(lastDoc, true, find) { viewModel.scanDoc(lastDoc, true, find) {
launch { launch {
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
} }
} }
} }
@ -253,11 +253,11 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} else { } else {
adapter.clearItems() adapter.clearItems()
val file = File(path) val file = File(path)
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.isAutoLoading = true
launch(IO) { launch(IO) {
viewModel.scanFile(file, true, find) { viewModel.scanFile(file, true, find) {
launch { launch {
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
} }
} }
} }
@ -332,7 +332,7 @@ class ImportBookActivity : VMBaseActivity<ImportBookViewModel>(R.layout.activity
} }
override fun upCountView() { override fun upCountView() {
select_action_bar.upCountView(adapter.selectedUris.size, adapter.checkableCount) binding.selectActionBar.upCountView(adapter.selectedUris.size, adapter.checkableCount)
} }
} }

@ -41,14 +41,13 @@ import io.legado.app.ui.book.read.page.PageView
import io.legado.app.ui.book.read.page.TextPageFactory import io.legado.app.ui.book.read.page.TextPageFactory
import io.legado.app.ui.book.read.page.entities.PageDirection import io.legado.app.ui.book.read.page.entities.PageDirection
import io.legado.app.ui.book.searchContent.SearchContentActivity import io.legado.app.ui.book.searchContent.SearchContentActivity
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.ChapterListActivity import io.legado.app.ui.book.toc.ChapterListActivity
import io.legado.app.ui.login.SourceLogin import io.legado.app.ui.login.SourceLogin
import io.legado.app.ui.replace.ReplaceRuleActivity import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.replace.edit.ReplaceEditActivity import io.legado.app.ui.replace.edit.ReplaceEditActivity
import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_read.*
import kotlinx.android.synthetic.main.view_read_menu.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
@ -74,12 +73,13 @@ class ReadBookActivity : ReadBookBaseActivity(),
private val requestCodeChapterList = 568 private val requestCodeChapterList = 568
private val requestCodeReplace = 312 private val requestCodeReplace = 312
private val requestCodeSearchResult = 123 private val requestCodeSearchResult = 123
private val requestCodeEditSource = 111
private var menu: Menu? = null private var menu: Menu? = null
private var textActionMenu: TextActionMenu? = null private var textActionMenu: TextActionMenu? = null
override val scope: CoroutineScope get() = this override val scope: CoroutineScope get() = this
override val isInitFinish: Boolean get() = viewModel.isInitFinish override val isInitFinish: Boolean get() = viewModel.isInitFinish
override val isScroll: Boolean get() = page_view.isScroll override val isScroll: Boolean get() = binding.pageView.isScroll
private val mHandler = Handler(Looper.getMainLooper()) private val mHandler = Handler(Looper.getMainLooper())
private val keepScreenRunnable: Runnable = private val keepScreenRunnable: Runnable =
Runnable { keepScreenOn(window, false) } Runnable { keepScreenOn(window, false) }
@ -89,19 +89,20 @@ class ReadBookActivity : ReadBookBaseActivity(),
private var screenTimeOut: Long = 0 private var screenTimeOut: Long = 0
private var timeBatteryReceiver: TimeBatteryReceiver? = null private var timeBatteryReceiver: TimeBatteryReceiver? = null
private var loadStates: Boolean = false private var loadStates: Boolean = false
override val pageFactory: TextPageFactory get() = page_view.pageFactory override val pageFactory: TextPageFactory get() = binding.pageView.pageFactory
override val headerHeight: Int get() = page_view.curPage.headerHeight override val headerHeight: Int get() = binding.pageView.curPage.headerHeight
@SuppressLint("ClickableViewAccessibility")
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
cursor_left.setColorFilter(accentColor) binding.cursorLeft.setColorFilter(accentColor)
cursor_right.setColorFilter(accentColor) binding.cursorRight.setColorFilter(accentColor)
cursor_left.setOnTouchListener(this) binding.cursorLeft.setOnTouchListener(this)
cursor_right.setOnTouchListener(this) binding.cursorRight.setOnTouchListener(this)
upScreenTimeOut() upScreenTimeOut()
ReadBook.callBack = this ReadBook.callBack = this
ReadBook.titleDate.observe(this) { ReadBook.titleDate.observe(this) {
title_bar.title = it binding.readMenu.setTitle(it)
upMenu() upMenu()
upView() upView()
} }
@ -115,7 +116,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
page_view.upStatusBar() binding.pageView.upStatusBar()
ReadBook.loadContent(resetPageOffset = false) ReadBook.loadContent(resetPageOffset = false)
} }
@ -124,7 +125,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
ReadBook.readStartTime = System.currentTimeMillis() ReadBook.readStartTime = System.currentTimeMillis()
upSystemUiVisibility() upSystemUiVisibility()
timeBatteryReceiver = TimeBatteryReceiver.register(this) timeBatteryReceiver = TimeBatteryReceiver.register(this)
page_view.upTime() binding.pageView.upTime()
} }
override fun onPause() { override fun onPause() {
@ -180,7 +181,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.menu_change_source -> { R.id.menu_change_source -> {
read_menu.runMenuOut() binding.readMenu.runMenuOut()
ReadBook.book?.let { ReadBook.book?.let {
ChangeSourceDialog.show(supportFragmentManager, it.name, it.author) ChangeSourceDialog.show(supportFragmentManager, it.name, it.author)
} }
@ -188,7 +189,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
R.id.menu_refresh -> { R.id.menu_refresh -> {
ReadBook.book?.let { ReadBook.book?.let {
ReadBook.curTextChapter = null ReadBook.curTextChapter = null
page_view.upContent() binding.pageView.upContent()
viewModel.refreshContent(it) viewModel.refreshContent(it)
} }
} }
@ -210,7 +211,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
ReadBook.loadContent(false) ReadBook.loadContent(false)
} }
R.id.menu_page_anim -> showPageAnimConfig { R.id.menu_page_anim -> showPageAnimConfig {
page_view.upPageAnim() binding.pageView.upPageAnim()
} }
R.id.menu_book_info -> ReadBook.book?.let { R.id.menu_book_info -> ReadBook.book?.let {
startActivity<BookInfoActivity>( startActivity<BookInfoActivity>(
@ -243,12 +244,12 @@ class ReadBookActivity : ReadBookBaseActivity(),
val isDown = action == 0 val isDown = action == 0
if (keyCode == KeyEvent.KEYCODE_MENU) { if (keyCode == KeyEvent.KEYCODE_MENU) {
if (isDown && !read_menu.cnaShowMenu) { if (isDown && !binding.readMenu.cnaShowMenu) {
read_menu.runMenuIn() binding.readMenu.runMenuIn()
return true return true
} }
if (!isDown && !read_menu.cnaShowMenu) { if (!isDown && !binding.readMenu.cnaShowMenu) {
read_menu.cnaShowMenu = true binding.readMenu.cnaShowMenu = true
return true return true
} }
} }
@ -262,13 +263,13 @@ class ReadBookActivity : ReadBookBaseActivity(),
when { when {
isPrevKey(keyCode) -> { isPrevKey(keyCode) -> {
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
page_view.pageDelegate?.keyTurnPage(PageDirection.PREV) binding.pageView.pageDelegate?.keyTurnPage(PageDirection.PREV)
return true return true
} }
} }
isNextKey(keyCode) -> { isNextKey(keyCode) -> {
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
page_view.pageDelegate?.keyTurnPage(PageDirection.NEXT) binding.pageView.pageDelegate?.keyTurnPage(PageDirection.NEXT)
return true return true
} }
} }
@ -283,7 +284,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
} }
} }
keyCode == KeyEvent.KEYCODE_SPACE -> { keyCode == KeyEvent.KEYCODE_SPACE -> {
page_view.pageDelegate?.keyTurnPage(PageDirection.NEXT) binding.pageView.pageDelegate?.keyTurnPage(PageDirection.NEXT)
return true return true
} }
} }
@ -344,13 +345,13 @@ class ReadBookActivity : ReadBookBaseActivity(),
MotionEvent.ACTION_DOWN -> textActionMenu?.dismiss() MotionEvent.ACTION_DOWN -> textActionMenu?.dismiss()
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
when (v.id) { when (v.id) {
R.id.cursor_left -> page_view.curPage.selectStartMove( R.id.cursor_left -> binding.pageView.curPage.selectStartMove(
event.rawX + cursor_left.width, event.rawX + binding.cursorLeft.width,
event.rawY - cursor_left.height event.rawY - binding.cursorLeft.height
) )
R.id.cursor_right -> page_view.curPage.selectEndMove( R.id.cursor_right -> binding.pageView.curPage.selectEndMove(
event.rawX - cursor_right.width, event.rawX - binding.cursorRight.width,
event.rawY - cursor_right.height event.rawY - binding.cursorRight.height
) )
} }
} }
@ -363,28 +364,28 @@ class ReadBookActivity : ReadBookBaseActivity(),
* 更新文字选择开始位置 * 更新文字选择开始位置
*/ */
override fun upSelectedStart(x: Float, y: Float, top: Float) { override fun upSelectedStart(x: Float, y: Float, top: Float) {
cursor_left.x = x - cursor_left.width binding.cursorLeft.x = x - binding.cursorLeft.width
cursor_left.y = y binding.cursorLeft.y = y
cursor_left.visible(true) binding.cursorLeft.visible(true)
text_menu_position.x = x binding.textMenuPosition.x = x
text_menu_position.y = top binding.textMenuPosition.y = top
} }
/** /**
* 更新文字选择结束位置 * 更新文字选择结束位置
*/ */
override fun upSelectedEnd(x: Float, y: Float) { override fun upSelectedEnd(x: Float, y: Float) {
cursor_right.x = x binding.cursorRight.x = x
cursor_right.y = y binding.cursorRight.y = y
cursor_right.visible(true) binding.cursorRight.visible(true)
} }
/** /**
* 取消文字选择 * 取消文字选择
*/ */
override fun onCancelSelect() { override fun onCancelSelect() {
cursor_left.invisible() binding.cursorLeft.invisible()
cursor_right.invisible() binding.cursorRight.invisible()
textActionMenu?.dismiss() textActionMenu?.dismiss()
} }
@ -398,16 +399,16 @@ class ReadBookActivity : ReadBookBaseActivity(),
textActionMenu?.let { popup -> textActionMenu?.let { popup ->
popup.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) popup.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
val popupHeight = popup.contentView.measuredHeight val popupHeight = popup.contentView.measuredHeight
val x = text_menu_position.x.toInt() val x = binding.textMenuPosition.x.toInt()
var y = text_menu_position.y.toInt() - popupHeight var y = binding.textMenuPosition.y.toInt() - popupHeight
if (y < statusBarHeight) { if (y < statusBarHeight) {
y = (cursor_left.y + cursor_left.height).toInt() y = (binding.cursorLeft.y + binding.cursorLeft.height).toInt()
} }
if (cursor_right.y > y && cursor_right.y < y + popupHeight) { if (binding.cursorRight.y > y && binding.cursorRight.y < y + popupHeight) {
y = (cursor_right.y + cursor_right.height).toInt() y = (binding.cursorRight.y + binding.cursorRight.height).toInt()
} }
if (!popup.isShowing) { if (!popup.isShowing) {
popup.showAtLocation(text_menu_position, Gravity.TOP or Gravity.START, x, y) popup.showAtLocation(binding.textMenuPosition, Gravity.TOP or Gravity.START, x, y)
} else { } else {
popup.update(x, y, WRAP_CONTENT, WRAP_CONTENT) popup.update(x, y, WRAP_CONTENT, WRAP_CONTENT)
} }
@ -417,7 +418,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
/** /**
* 当前选择的文本 * 当前选择的文本
*/ */
override val selectedText: String get() = page_view.curPage.selectedText override val selectedText: String get() = binding.pageView.curPage.selectedText
/** /**
* 文本选择菜单操作 * 文本选择菜单操作
@ -453,21 +454,21 @@ class ReadBookActivity : ReadBookBaseActivity(),
*/ */
override fun onMenuActionFinally() { override fun onMenuActionFinally() {
textActionMenu?.dismiss() textActionMenu?.dismiss()
page_view.curPage.cancelSelect() binding.pageView.curPage.cancelSelect()
page_view.isTextSelected = false binding.pageView.isTextSelected = false
} }
/** /**
* 音量键翻页 * 音量键翻页
*/ */
private fun volumeKeyPage(direction: PageDirection): Boolean { private fun volumeKeyPage(direction: PageDirection): Boolean {
if (!read_menu.isVisible) { if (!binding.readMenu.isVisible) {
if (getPrefBoolean("volumeKeyPage", true)) { if (getPrefBoolean("volumeKeyPage", true)) {
if (getPrefBoolean("volumeKeyPageOnPlay") if (getPrefBoolean("volumeKeyPageOnPlay")
|| BaseReadAloudService.pause || BaseReadAloudService.pause
) { ) {
page_view.pageDelegate?.isCancel = false binding.pageView.pageDelegate?.isCancel = false
page_view.pageDelegate?.keyTurnPage(direction) binding.pageView.pageDelegate?.keyTurnPage(direction)
return true return true
} }
} }
@ -497,8 +498,8 @@ class ReadBookActivity : ReadBookBaseActivity(),
override fun upContent(relativePosition: Int, resetPageOffset: Boolean) { override fun upContent(relativePosition: Int, resetPageOffset: Boolean) {
autoPageProgress = 0 autoPageProgress = 0
launch { launch {
page_view.upContent(relativePosition, resetPageOffset) binding.pageView.upContent(relativePosition, resetPageOffset)
seek_read_page.progress = ReadBook.durPageIndex binding.readMenu.setSeekPage(ReadBook.durPageIndex)
} }
loadStates = false loadStates = false
} }
@ -508,29 +509,13 @@ class ReadBookActivity : ReadBookBaseActivity(),
*/ */
override fun upView() { override fun upView() {
launch { launch {
ReadBook.curTextChapter?.let { binding.readMenu.upBookView()
tv_chapter_name.text = it.title
tv_chapter_name.visible()
if (!ReadBook.isLocalBook) {
tv_chapter_url.text = it.url
tv_chapter_url.visible()
} else {
tv_chapter_url.gone()
}
seek_read_page.max = it.pageSize.minus(1)
seek_read_page.progress = ReadBook.durPageIndex
tv_pre.isEnabled = ReadBook.durChapterIndex != 0
tv_next.isEnabled = ReadBook.durChapterIndex != ReadBook.chapterSize - 1
} ?: let {
tv_chapter_name.gone()
tv_chapter_url.gone()
}
} }
} }
override fun upPageAnim() { override fun upPageAnim() {
launch { launch {
page_view.upPageAnim() binding.pageView.upPageAnim()
} }
} }
@ -540,7 +525,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
override fun pageChanged() { override fun pageChanged() {
autoPageProgress = 0 autoPageProgress = 0
launch { launch {
seek_read_page.progress = ReadBook.durPageIndex binding.readMenu.setSeekPage(ReadBook.durPageIndex)
} }
} }
@ -548,7 +533,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
* 显示菜单 * 显示菜单
*/ */
override fun showMenuBar() { override fun showMenuBar() {
read_menu.runMenuIn() binding.readMenu.runMenuIn()
} }
override val oldBook: Book? override val oldBook: Book?
@ -567,7 +552,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
AutoReadDialog().show(supportFragmentManager, "autoRead") AutoReadDialog().show(supportFragmentManager, "autoRead")
} }
else -> { else -> {
read_menu.runMenuIn() binding.readMenu.runMenuIn()
} }
} }
} }
@ -593,35 +578,44 @@ class ReadBookActivity : ReadBookBaseActivity(),
autoPageStop() autoPageStop()
} else { } else {
isAutoPage = true isAutoPage = true
page_view.upContent() binding.pageView.upContent()
page_view.upContent(1) binding.pageView.upContent(1)
autoPagePlus() autoPagePlus()
} }
read_menu.setAutoPage(isAutoPage) binding.readMenu.setAutoPage(isAutoPage)
} }
override fun autoPageStop() { override fun autoPageStop() {
isAutoPage = false isAutoPage = false
mHandler.removeCallbacks(autoPageRunnable) mHandler.removeCallbacks(autoPageRunnable)
page_view.upContent() binding.pageView.upContent()
} }
private fun autoPagePlus() { private fun autoPagePlus() {
mHandler.removeCallbacks(autoPageRunnable) mHandler.removeCallbacks(autoPageRunnable)
if (page_view.isScroll) { if (binding.pageView.isScroll) {
page_view.curPage.scroll(-page_view.height / ReadBookConfig.autoReadSpeed / 50) binding.pageView.curPage.scroll(-binding.pageView.height / ReadBookConfig.autoReadSpeed / 50)
} else { } else {
autoPageProgress++ autoPageProgress++
if (autoPageProgress >= ReadBookConfig.autoReadSpeed * 50) { if (autoPageProgress >= ReadBookConfig.autoReadSpeed * 50) {
autoPageProgress = 0 autoPageProgress = 0
page_view.fillPage(PageDirection.NEXT) binding.pageView.fillPage(PageDirection.NEXT)
} else { } else {
page_view.invalidate() binding.pageView.invalidate()
} }
} }
mHandler.postDelayed(autoPageRunnable, 20) mHandler.postDelayed(autoPageRunnable, 20)
} }
override fun openSourceEditActivity() {
ReadBook.webBook?.let {
startActivityForResult<BookSourceEditActivity>(
requestCodeEditSource,
Pair("data", it.bookSource.bookSourceUrl)
)
}
}
/** /**
* 替换 * 替换
*/ */
@ -672,7 +666,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
* 更新状态栏,导航栏 * 更新状态栏,导航栏
*/ */
override fun upSystemUiVisibility() { override fun upSystemUiVisibility() {
upSystemUiVisibility(isInMultiWindow, !read_menu.isVisible) upSystemUiVisibility(isInMultiWindow, !binding.readMenu.isVisible)
upNavigationBarColor() upNavigationBarColor()
} }
@ -726,6 +720,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
when (requestCode) { when (requestCode) {
requestCodeEditSource -> viewModel.upBookSource()
requestCodeChapterList -> requestCodeChapterList ->
data?.getIntExtra("index", ReadBook.durChapterIndex)?.let { index -> data?.getIntExtra("index", ReadBook.durChapterIndex)?.let { index ->
if (index != ReadBook.durChapterIndex) { if (index != ReadBook.durChapterIndex) {
@ -756,27 +751,28 @@ class ReadBookActivity : ReadBookBaseActivity(),
ReadBook.skipToPage(positions[0]) ReadBook.skipToPage(positions[0])
} }
withContext(Main) { withContext(Main) {
page_view.curPage.selectStartMoveIndex( binding.pageView.curPage.selectStartMoveIndex(
0, 0,
positions[1], positions[1],
positions[2] positions[2]
) )
delay(20L) delay(20L)
when (positions[3]) { when (positions[3]) {
0 -> page_view.curPage.selectEndMoveIndex( 0 -> binding.pageView.curPage.selectEndMoveIndex(
0, 0,
positions[1], positions[1],
positions[2] + viewModel.searchContentQuery.length - 1 positions[2] + viewModel.searchContentQuery.length - 1
) )
1 -> page_view.curPage.selectEndMoveIndex( 1 -> binding.pageView.curPage.selectEndMoveIndex(
0, 0,
positions[1] + 1, positions[1] + 1,
positions[4] positions[4]
) )
//consider change page, jump to scroll position //consider change page, jump to scroll position
-1 -> page_view.curPage.selectEndMoveIndex(1, 0, positions[4]) -1 -> binding.pageView.curPage
.selectEndMoveIndex(1, 0, positions[4])
} }
page_view.isTextSelected = true binding.pageView.isTextSelected = true
delay(100L) delay(100L)
} }
} }
@ -807,7 +803,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
super.onDestroy() super.onDestroy()
mHandler.removeCallbacks(keepScreenRunnable) mHandler.removeCallbacks(keepScreenRunnable)
textActionMenu?.dismiss() textActionMenu?.dismiss()
page_view.onDestroy() binding.pageView.onDestroy()
ReadBook.msg = null ReadBook.msg = null
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG) {
SyncBookProgress.uploadBookProgress() SyncBookProgress.uploadBookProgress()
@ -817,11 +813,11 @@ class ReadBookActivity : ReadBookBaseActivity(),
override fun observeLiveBus() { override fun observeLiveBus() {
super.observeLiveBus() super.observeLiveBus()
observeEvent<String>(EventBus.TIME_CHANGED) { page_view.upTime() } observeEvent<String>(EventBus.TIME_CHANGED) { binding.pageView.upTime() }
observeEvent<Int>(EventBus.BATTERY_CHANGED) { page_view.upBattery(it) } observeEvent<Int>(EventBus.BATTERY_CHANGED) { binding.pageView.upBattery(it) }
observeEvent<BookChapter>(EventBus.OPEN_CHAPTER) { observeEvent<BookChapter>(EventBus.OPEN_CHAPTER) {
viewModel.openChapter(it.index, ReadBook.durPageIndex) viewModel.openChapter(it.index, ReadBook.durPageIndex)
page_view.upContent() binding.pageView.upContent()
} }
observeEvent<Boolean>(EventBus.MEDIA_BUTTON) { observeEvent<Boolean>(EventBus.MEDIA_BUTTON) {
if (it) { if (it) {
@ -832,13 +828,13 @@ class ReadBookActivity : ReadBookBaseActivity(),
} }
observeEvent<Boolean>(EventBus.UP_CONFIG) { observeEvent<Boolean>(EventBus.UP_CONFIG) {
upSystemUiVisibility() upSystemUiVisibility()
page_view.upBg() binding.pageView.upBg()
page_view.upTipStyle() binding.pageView.upTipStyle()
page_view.upStyle() binding.pageView.upStyle()
if (it) { if (it) {
ReadBook.loadContent(resetPageOffset = false) ReadBook.loadContent(resetPageOffset = false)
} else { } else {
page_view.upContent(resetPageOffset = false) binding.pageView.upContent(resetPageOffset = false)
} }
} }
observeEvent<Int>(EventBus.ALOUD_STATE) { observeEvent<Int>(EventBus.ALOUD_STATE) {
@ -847,7 +843,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
val page = textChapter.page(ReadBook.durPageIndex) val page = textChapter.page(ReadBook.durPageIndex)
if (page != null) { if (page != null) {
page.removePageAloudSpan() page.removePageAloudSpan()
page_view.upContent(resetPageOffset = false) binding.pageView.upContent(resetPageOffset = false)
} }
} }
} }
@ -868,10 +864,10 @@ class ReadBookActivity : ReadBookBaseActivity(),
upScreenTimeOut() upScreenTimeOut()
} }
observeEvent<Boolean>(PreferKey.textSelectAble) { observeEvent<Boolean>(PreferKey.textSelectAble) {
page_view.curPage.upSelectAble(it) binding.pageView.curPage.upSelectAble(it)
} }
observeEvent<String>(PreferKey.showBrightnessView) { observeEvent<String>(PreferKey.showBrightnessView) {
read_menu.upBrightnessState() binding.readMenu.upBrightnessState()
} }
observeEvent<String>(EventBus.REPLACE_RULE_SAVE) { observeEvent<String>(EventBus.REPLACE_RULE_SAVE) {
viewModel.replaceRuleChanged() viewModel.replaceRuleChanged()

@ -1,11 +1,8 @@
package io.legado.app.ui.book.read package io.legado.app.ui.book.read
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.graphics.Color import android.graphics.Color
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
@ -16,6 +13,8 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Bookmark import io.legado.app.data.entities.Bookmark
import io.legado.app.databinding.ActivityBookReadBinding
import io.legado.app.databinding.DialogDownloadChoiceBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.LocalConfig import io.legado.app.help.LocalConfig
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
@ -31,27 +30,19 @@ import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.read.config.BgTextConfigDialog import io.legado.app.ui.book.read.config.BgTextConfigDialog
import io.legado.app.ui.book.read.config.ClickActionConfigDialog import io.legado.app.ui.book.read.config.ClickActionConfigDialog
import io.legado.app.ui.book.read.config.PaddingConfigDialog import io.legado.app.ui.book.read.config.PaddingConfigDialog
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.getPrefString import io.legado.app.utils.getPrefString
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.requestInputMethod import io.legado.app.utils.requestInputMethod
import kotlinx.android.synthetic.main.activity_book_read.*
import kotlinx.android.synthetic.main.dialog_download_choice.view.*
import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_read_menu.*
import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.startActivityForResult
/** /**
* 阅读界面 * 阅读界面
*/ */
abstract class ReadBookBaseActivity : abstract class ReadBookBaseActivity :
VMBaseActivity<ReadBookViewModel>(R.layout.activity_book_read) { VMBaseActivity<ActivityBookReadBinding, ReadBookViewModel>() {
override val viewModel: ReadBookViewModel override val viewModel: ReadBookViewModel
get() = getViewModel(ReadBookViewModel::class.java) get() = getViewModel(ReadBookViewModel::class.java)
private val requestCodeEditSource = 111
var bottomDialog = 0 var bottomDialog = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -62,43 +53,11 @@ abstract class ReadBookBaseActivity :
} }
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
initView()
if (LocalConfig.isFirstRead) { if (LocalConfig.isFirstRead) {
showClickRegionalConfig() showClickRegionalConfig()
} }
} }
/**
* 初始化View
*/
private fun initView() {
tv_chapter_name.onClick {
ReadBook.webBook?.let {
startActivityForResult<BookSourceEditActivity>(
requestCodeEditSource,
Pair("data", it.bookSource.bookSourceUrl)
)
}
}
tv_chapter_url.onClick {
runCatching {
val url = tv_chapter_url.text.toString()
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
requestCodeEditSource -> viewModel.upBookSource()
}
}
}
fun showPaddingConfig() { fun showPaddingConfig() {
PaddingConfigDialog().show(supportFragmentManager, "paddingConfig") PaddingConfigDialog().show(supportFragmentManager, "paddingConfig")
} }
@ -182,8 +141,7 @@ abstract class ReadBookBaseActivity :
override fun upNavigationBarColor() { override fun upNavigationBarColor() {
when { when {
read_menu == null -> return binding.readMenu.isVisible -> ATH.setNavigationBarColorAuto(this)
read_menu.isVisible -> ATH.setNavigationBarColorAuto(this)
bottomDialog > 0 -> ATH.setNavigationBarColorAuto(this, bottomBackground) bottomDialog > 0 -> ATH.setNavigationBarColorAuto(this, bottomBackground)
else -> { else -> {
ATH.setNavigationBarColorAuto(this, Color.TRANSPARENT) ATH.setNavigationBarColorAuto(this, Color.TRANSPARENT)
@ -218,23 +176,22 @@ abstract class ReadBookBaseActivity :
fun showDownloadDialog() { fun showDownloadDialog() {
ReadBook.book?.let { book -> ReadBook.book?.let { book ->
alert(titleResource = R.string.offline_cache) { alert(titleResource = R.string.offline_cache) {
var view: View? = null var dialogBinding: DialogDownloadChoiceBinding? = null
customView { customView {
LayoutInflater.from(this@ReadBookBaseActivity) LayoutInflater.from(this@ReadBookBaseActivity)
.inflate(R.layout.dialog_download_choice, null) .inflate(R.layout.dialog_download_choice, null)
.apply { .apply {
view = this dialogBinding = DialogDownloadChoiceBinding.bind(this)
setBackgroundColor(context.backgroundColor) setBackgroundColor(context.backgroundColor)
edit_start.setText((book.durChapterIndex + 1).toString()) dialogBinding!!.editStart.setText((book.durChapterIndex + 1).toString())
edit_end.setText(book.totalChapterNum.toString()) dialogBinding!!.editEnd.setText(book.totalChapterNum.toString())
} }
} }
yesButton { yesButton {
view?.apply { val start = dialogBinding!!.editStart.text?.toString()?.toInt() ?: 0
val start = edit_start?.text?.toString()?.toInt() ?: 0 val end =
val end = edit_end?.text?.toString()?.toInt() ?: book.totalChapterNum dialogBinding!!.editEnd.text?.toString()?.toInt() ?: book.totalChapterNum
CacheBook.start(context, book.bookUrl, start - 1, end - 1) CacheBook.start(this@ReadBookBaseActivity, book.bookUrl, start - 1, end - 1)
}
} }
noButton() noButton()
}.show() }.show()
@ -250,9 +207,8 @@ abstract class ReadBookBaseActivity :
message = book.name + "" + textChapter.title message = book.name + "" + textChapter.title
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view.apply { editText = findViewById(R.id.edit_view)
setHint(R.string.note_content) editText!!.setHint(R.string.note_content)
}
} }
} }
yesButton { yesButton {
@ -282,9 +238,9 @@ abstract class ReadBookBaseActivity :
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setFilterValues(charsets) editText?.setFilterValues(charsets)
edit_view.setText(ReadBook.book?.charset) editText?.setText(ReadBook.book?.charset)
} }
} }
okButton { okButton {

@ -4,6 +4,7 @@ import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.WindowManager import android.view.WindowManager
import android.view.animation.Animation import android.view.animation.Animation
import android.widget.FrameLayout import android.widget.FrameLayout
@ -12,12 +13,12 @@ import androidx.core.view.isVisible
import io.legado.app.App import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.databinding.ViewReadMenuBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.LocalConfig import io.legado.app.help.LocalConfig
import io.legado.app.lib.theme.* import io.legado.app.lib.theme.*
import io.legado.app.service.help.ReadBook import io.legado.app.service.help.ReadBook
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.view_read_menu.view.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.sdk27.listeners.onLongClick import org.jetbrains.anko.sdk27.listeners.onLongClick
@ -30,6 +31,7 @@ class ReadMenu @JvmOverloads constructor(
) : FrameLayout(context, attrs) { ) : FrameLayout(context, attrs) {
var cnaShowMenu: Boolean = false var cnaShowMenu: Boolean = false
private val callBack: CallBack get() = activity as CallBack private val callBack: CallBack get() = activity as CallBack
private val binding = ViewReadMenuBinding.inflate(LayoutInflater.from(context), this, true)
private lateinit var menuTopIn: Animation private lateinit var menuTopIn: Animation
private lateinit var menuTopOut: Animation private lateinit var menuTopOut: Animation
private lateinit var menuBottomIn: Animation private lateinit var menuBottomIn: Animation
@ -44,50 +46,49 @@ class ReadMenu @JvmOverloads constructor(
val showBrightnessView get() = context.getPrefBoolean(PreferKey.showBrightnessView, true) val showBrightnessView get() = context.getPrefBoolean(PreferKey.showBrightnessView, true)
init { init {
inflate(context, R.layout.view_read_menu, this)
if (AppConfig.isNightTheme) { if (AppConfig.isNightTheme) {
fabNightTheme.setImageResource(R.drawable.ic_daytime) binding.fabNightTheme.setImageResource(R.drawable.ic_daytime)
} else { } else {
fabNightTheme.setImageResource(R.drawable.ic_brightness) binding.fabNightTheme.setImageResource(R.drawable.ic_brightness)
} }
initAnimation() initAnimation()
val brightnessBackground = GradientDrawable() val brightnessBackground = GradientDrawable()
brightnessBackground.cornerRadius = 5F.dp brightnessBackground.cornerRadius = 5F.dp
brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f)) brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f))
ll_brightness.background = brightnessBackground binding.llBrightness.background = brightnessBackground
ll_bottom_bg.setBackgroundColor(bgColor) binding.llBottomBg.setBackgroundColor(bgColor)
fabSearch.backgroundTintList = bottomBackgroundList binding.fabSearch.backgroundTintList = bottomBackgroundList
fabSearch.setColorFilter(textColor) binding.fabSearch.setColorFilter(textColor)
fabAutoPage.backgroundTintList = bottomBackgroundList binding.fabAutoPage.backgroundTintList = bottomBackgroundList
fabAutoPage.setColorFilter(textColor) binding.fabAutoPage.setColorFilter(textColor)
fabReplaceRule.backgroundTintList = bottomBackgroundList binding.fabReplaceRule.backgroundTintList = bottomBackgroundList
fabReplaceRule.setColorFilter(textColor) binding.fabReplaceRule.setColorFilter(textColor)
fabNightTheme.backgroundTintList = bottomBackgroundList binding.fabNightTheme.backgroundTintList = bottomBackgroundList
fabNightTheme.setColorFilter(textColor) binding.fabNightTheme.setColorFilter(textColor)
tv_pre.setTextColor(textColor) binding.tvPre.setTextColor(textColor)
tv_next.setTextColor(textColor) binding.tvNext.setTextColor(textColor)
iv_catalog.setColorFilter(textColor) binding.ivCatalog.setColorFilter(textColor)
tv_catalog.setTextColor(textColor) binding.tvCatalog.setTextColor(textColor)
iv_read_aloud.setColorFilter(textColor) binding.ivReadAloud.setColorFilter(textColor)
tv_read_aloud.setTextColor(textColor) binding.tvReadAloud.setTextColor(textColor)
iv_font.setColorFilter(textColor) binding.ivFont.setColorFilter(textColor)
tv_font.setTextColor(textColor) binding.tvFont.setTextColor(textColor)
iv_setting.setColorFilter(textColor) binding.ivSetting.setColorFilter(textColor)
tv_setting.setTextColor(textColor) binding.tvSetting.setTextColor(textColor)
vw_bg.onClick { } binding.vwBg.onClick { }
vwNavigationBar.onClick { } binding.vwNavigationBar.onClick { }
seek_brightness.progress = context.getPrefInt("brightness", 100) binding.seekBrightness.progress = context.getPrefInt("brightness", 100)
upBrightnessState() upBrightnessState()
bindEvent() bindEvent()
} }
fun upBrightnessState() { fun upBrightnessState() {
if (brightnessAuto()) { if (brightnessAuto()) {
iv_brightness_auto.setColorFilter(context.accentColor) binding.ivBrightnessAuto.setColorFilter(context.accentColor)
seek_brightness.isEnabled = false binding.seekBrightness.isEnabled = false
} else { } else {
iv_brightness_auto.setColorFilter(context.buttonDisabledColor) binding.ivBrightnessAuto.setColorFilter(context.buttonDisabledColor)
seek_brightness.isEnabled = true binding.seekBrightness.isEnabled = true
} }
setScreenBrightness(context.getPrefInt("brightness", 100)) setScreenBrightness(context.getPrefInt("brightness", 100))
} }
@ -109,17 +110,17 @@ class ReadMenu @JvmOverloads constructor(
fun runMenuIn() { fun runMenuIn() {
this.visible() this.visible()
title_bar.visible() binding.titleBar.visible()
bottom_menu.visible() binding.bottomMenu.visible()
title_bar.startAnimation(menuTopIn) binding.titleBar.startAnimation(menuTopIn)
bottom_menu.startAnimation(menuBottomIn) binding.bottomMenu.startAnimation(menuBottomIn)
} }
fun runMenuOut(onMenuOutEnd: (() -> Unit)? = null) { fun runMenuOut(onMenuOutEnd: (() -> Unit)? = null) {
this.onMenuOutEnd = onMenuOutEnd this.onMenuOutEnd = onMenuOutEnd
if (this.isVisible) { if (this.isVisible) {
title_bar.startAnimation(menuTopOut) binding.titleBar.startAnimation(menuTopOut)
bottom_menu.startAnimation(menuBottomOut) binding.bottomMenu.startAnimation(menuBottomOut)
} }
} }
@ -128,28 +129,34 @@ class ReadMenu @JvmOverloads constructor(
} }
private fun bindEvent() { private fun bindEvent() {
iv_brightness_auto.onClick { binding.tvChapterName.onClick {
callBack.openSourceEditActivity()
}
binding.tvChapterUrl.onClick {
context.openUrl(binding.tvChapterUrl.text.toString())
}
binding.ivBrightnessAuto.onClick {
context.putPrefBoolean("brightnessAuto", !brightnessAuto()) context.putPrefBoolean("brightnessAuto", !brightnessAuto())
upBrightnessState() upBrightnessState()
} }
//亮度调节 //亮度调节
seek_brightness.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.seekBrightness.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
setScreenBrightness(progress) setScreenBrightness(progress)
} }
override fun onStartTrackingTouch(seekBar: SeekBar?) { override fun onStartTrackingTouch(seekBar: SeekBar) {
} }
override fun onStopTrackingTouch(seekBar: SeekBar?) { override fun onStopTrackingTouch(seekBar: SeekBar) {
context.putPrefInt("brightness", seek_brightness.progress) context.putPrefInt("brightness", seekBar.progress)
} }
}) })
//阅读进度 //阅读进度
seek_read_page.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { binding.seekBrightness.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
} }
@ -164,60 +171,60 @@ class ReadMenu @JvmOverloads constructor(
}) })
//搜索 //搜索
fabSearch.onClick { binding.fabSearch.onClick {
runMenuOut { runMenuOut {
callBack.openSearchActivity(null) callBack.openSearchActivity(null)
} }
} }
//自动翻页 //自动翻页
fabAutoPage.onClick { binding.fabAutoPage.onClick {
runMenuOut { runMenuOut {
callBack.autoPage() callBack.autoPage()
} }
} }
//替换 //替换
fabReplaceRule.onClick { callBack.openReplaceRule() } binding.fabReplaceRule.onClick { callBack.openReplaceRule() }
//夜间模式 //夜间模式
fabNightTheme.onClick { binding.fabNightTheme.onClick {
AppConfig.isNightTheme = !AppConfig.isNightTheme AppConfig.isNightTheme = !AppConfig.isNightTheme
App.INSTANCE.applyDayNight() App.INSTANCE.applyDayNight()
} }
//上一章 //上一章
tv_pre.onClick { ReadBook.moveToPrevChapter(upContent = true, toLast = false) } binding.tvPre.onClick { ReadBook.moveToPrevChapter(upContent = true, toLast = false) }
//下一章 //下一章
tv_next.onClick { ReadBook.moveToNextChapter(true) } binding.tvNext.onClick { ReadBook.moveToNextChapter(true) }
//目录 //目录
ll_catalog.onClick { binding.llCatalog.onClick {
runMenuOut { runMenuOut {
callBack.openChapterList() callBack.openChapterList()
} }
} }
//朗读 //朗读
ll_read_aloud.onClick { binding.llReadAloud.onClick {
runMenuOut { runMenuOut {
callBack.onClickReadAloud() callBack.onClickReadAloud()
} }
} }
ll_read_aloud.onLongClick { binding.llReadAloud.onLongClick {
runMenuOut { callBack.showReadAloudDialog() } runMenuOut { callBack.showReadAloudDialog() }
true true
} }
//界面 //界面
ll_font.onClick { binding.llFont.onClick {
runMenuOut { runMenuOut {
callBack.showReadStyle() callBack.showReadStyle()
} }
} }
//设置 //设置
ll_setting.onClick { binding.llSetting.onClick {
runMenuOut { runMenuOut {
callBack.showMoreSetting() callBack.showMoreSetting()
} }
@ -231,12 +238,12 @@ class ReadMenu @JvmOverloads constructor(
menuTopIn.setAnimationListener(object : Animation.AnimationListener { menuTopIn.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) { override fun onAnimationStart(animation: Animation) {
callBack.upSystemUiVisibility() callBack.upSystemUiVisibility()
ll_brightness.visible(showBrightnessView) binding.llBrightness.visible(showBrightnessView)
} }
override fun onAnimationEnd(animation: Animation) { override fun onAnimationEnd(animation: Animation) {
vw_menu_bg.onClick { runMenuOut() } binding.vwMenuBg.onClick { runMenuOut() }
vwNavigationBar.layoutParams = vwNavigationBar.layoutParams.apply { binding.vwNavigationBar.layoutParams = binding.vwNavigationBar.layoutParams.apply {
height = activity!!.navigationBarHeight height = activity!!.navigationBarHeight
} }
if (LocalConfig.isFirstReadMenuShow) { if (LocalConfig.isFirstReadMenuShow) {
@ -253,13 +260,13 @@ class ReadMenu @JvmOverloads constructor(
AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_out) AnimationUtilsSupport.loadAnimation(context, R.anim.anim_readbook_bottom_out)
menuTopOut.setAnimationListener(object : Animation.AnimationListener { menuTopOut.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) { override fun onAnimationStart(animation: Animation) {
vw_menu_bg.setOnClickListener(null) binding.vwMenuBg.setOnClickListener(null)
} }
override fun onAnimationEnd(animation: Animation) { override fun onAnimationEnd(animation: Animation) {
this@ReadMenu.invisible() this@ReadMenu.invisible()
title_bar.invisible() binding.titleBar.invisible()
bottom_menu.invisible() binding.bottomMenu.invisible()
cnaShowMenu = false cnaShowMenu = false
onMenuOutEnd?.invoke() onMenuOutEnd?.invoke()
callBack.upSystemUiVisibility() callBack.upSystemUiVisibility()
@ -269,15 +276,43 @@ class ReadMenu @JvmOverloads constructor(
}) })
} }
fun setTitle(title: String) {
binding.titleBar.title = title
}
fun upBookView() {
ReadBook.curTextChapter?.let {
binding.tvChapterName.text = it.title
binding.tvChapterName.visible()
if (!ReadBook.isLocalBook) {
binding.tvChapterUrl.text = it.url
binding.tvChapterUrl.visible()
} else {
binding.tvChapterUrl.gone()
}
binding.seekReadPage.max = it.pageSize.minus(1)
binding.seekReadPage.progress = ReadBook.durPageIndex
binding.tvPre.isEnabled = ReadBook.durChapterIndex != 0
binding.tvNext.isEnabled = ReadBook.durChapterIndex != ReadBook.chapterSize - 1
} ?: let {
binding.tvChapterName.gone()
binding.tvChapterUrl.gone()
}
}
fun setSeekPage(seek: Int) {
binding.seekReadPage.progress = seek
}
fun setAutoPage(autoPage: Boolean) { fun setAutoPage(autoPage: Boolean) {
if (autoPage) { if (autoPage) {
fabAutoPage.setImageResource(R.drawable.ic_auto_page_stop) binding.fabAutoPage.setImageResource(R.drawable.ic_auto_page_stop)
fabAutoPage.contentDescription = context.getString(R.string.auto_next_page_stop) binding.fabAutoPage.contentDescription = context.getString(R.string.auto_next_page_stop)
} else { } else {
fabAutoPage.setImageResource(R.drawable.ic_auto_page) binding.fabAutoPage.setImageResource(R.drawable.ic_auto_page)
fabAutoPage.contentDescription = context.getString(R.string.auto_next_page) binding.fabAutoPage.contentDescription = context.getString(R.string.auto_next_page)
} }
fabAutoPage.setColorFilter(textColor) binding.fabAutoPage.setColorFilter(textColor)
} }
interface CallBack { interface CallBack {
@ -285,6 +320,7 @@ class ReadMenu @JvmOverloads constructor(
fun openReplaceRule() fun openReplaceRule()
fun openChapterList() fun openChapterList()
fun openSearchActivity(searchWord: String?) fun openSearchActivity(searchWord: String?)
fun openSourceEditActivity()
fun showReadStyle() fun showReadStyle()
fun showMoreSetting() fun showMoreSetting()
fun showReadAloudDialog() fun showReadAloudDialog()

@ -3,6 +3,7 @@ package io.legado.app.ui.book.read.page
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
@ -10,6 +11,7 @@ import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.constant.AppConst.timeFormat import io.legado.app.constant.AppConst.timeFormat
import io.legado.app.databinding.ViewBookPageBinding
import io.legado.app.help.ReadBookConfig import io.legado.app.help.ReadBookConfig
import io.legado.app.help.ReadTipConfig import io.legado.app.help.ReadTipConfig
import io.legado.app.service.help.ReadBook import io.legado.app.service.help.ReadBook
@ -18,13 +20,14 @@ import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.ui.widget.BatteryView import io.legado.app.ui.widget.BatteryView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.view_book_page.view.*
import org.jetbrains.anko.topPadding import org.jetbrains.anko.topPadding
import java.util.* import java.util.*
/**
* 阅读界面
*/
class ContentView(context: Context) : FrameLayout(context) { class ContentView(context: Context) : FrameLayout(context) {
private val binding = ViewBookPageBinding.inflate(LayoutInflater.from(context), this, true)
private var battery = 100 private var battery = 100
private var tvTitle: BatteryView? = null private var tvTitle: BatteryView? = null
private var tvTime: BatteryView? = null private var tvTime: BatteryView? = null
@ -38,7 +41,7 @@ class ContentView(context: Context) : FrameLayout(context) {
val headerHeight: Int val headerHeight: Int
get() { get() {
val h1 = if (ReadBookConfig.hideStatusBar) 0 else context.statusBarHeight val h1 = if (ReadBookConfig.hideStatusBar) 0 else context.statusBarHeight
val h2 = if (ll_header.isGone) 0 else ll_header.height val h2 = if (binding.llHeader.isGone) 0 else binding.llHeader.height
return h1 + h2 return h1 + h2
} }
@ -46,52 +49,51 @@ class ContentView(context: Context) : FrameLayout(context) {
if (!isInEditMode) { if (!isInEditMode) {
//设置背景防止切换背景时文字重叠 //设置背景防止切换背景时文字重叠
setBackgroundColor(context.getCompatColor(R.color.background)) setBackgroundColor(context.getCompatColor(R.color.background))
inflate(context, R.layout.view_book_page, this)
upTipStyle() upTipStyle()
upStyle() upStyle()
content_text_view.upView = { binding.contentTextView.upView = {
setProgress(it) setProgress(it)
} }
} }
} }
fun upStyle() = ReadBookConfig.apply { fun upStyle() = ReadBookConfig.apply {
bv_header_left.typeface = ChapterProvider.typeface binding.bvHeaderLeft.typeface = ChapterProvider.typeface
tv_header_left.typeface = ChapterProvider.typeface binding.tvHeaderLeft.typeface = ChapterProvider.typeface
tv_header_middle.typeface = ChapterProvider.typeface binding.tvHeaderMiddle.typeface = ChapterProvider.typeface
tv_header_right.typeface = ChapterProvider.typeface binding.tvHeaderRight.typeface = ChapterProvider.typeface
bv_footer_left.typeface = ChapterProvider.typeface binding.bvFooterLeft.typeface = ChapterProvider.typeface
tv_footer_left.typeface = ChapterProvider.typeface binding.tvFooterLeft.typeface = ChapterProvider.typeface
tv_footer_middle.typeface = ChapterProvider.typeface binding.tvFooterMiddle.typeface = ChapterProvider.typeface
tv_footer_right.typeface = ChapterProvider.typeface binding.tvFooterRight.typeface = ChapterProvider.typeface
val tipColor = if (ReadTipConfig.tipColor == 0) textColor else ReadTipConfig.tipColor val tipColor = if (ReadTipConfig.tipColor == 0) textColor else ReadTipConfig.tipColor
bv_header_left.setColor(tipColor) binding.bvHeaderLeft.setColor(tipColor)
tv_header_left.setColor(tipColor) binding.tvHeaderLeft.setColor(tipColor)
tv_header_middle.setColor(tipColor) binding.tvHeaderMiddle.setColor(tipColor)
tv_header_right.setColor(tipColor) binding.tvHeaderRight.setColor(tipColor)
bv_footer_left.setColor(tipColor) binding.bvFooterLeft.setColor(tipColor)
tv_footer_left.setColor(tipColor) binding.tvFooterLeft.setColor(tipColor)
tv_footer_middle.setColor(tipColor) binding.tvFooterMiddle.setColor(tipColor)
tv_footer_right.setColor(tipColor) binding.tvFooterRight.setColor(tipColor)
upStatusBar() upStatusBar()
ll_header.setPadding( binding.llHeader.setPadding(
headerPaddingLeft.dp, headerPaddingLeft.dp,
headerPaddingTop.dp, headerPaddingTop.dp,
headerPaddingRight.dp, headerPaddingRight.dp,
headerPaddingBottom.dp headerPaddingBottom.dp
) )
ll_footer.setPadding( binding.llFooter.setPadding(
footerPaddingLeft.dp, footerPaddingLeft.dp,
footerPaddingTop.dp, footerPaddingTop.dp,
footerPaddingRight.dp, footerPaddingRight.dp,
footerPaddingBottom.dp footerPaddingBottom.dp
) )
vw_top_divider.visible(showHeaderLine) binding.vwTopDivider.visible(showHeaderLine)
vw_bottom_divider.visible(showFooterLine) binding.vwBottomDivider.visible(showFooterLine)
page_nv_bar.layoutParams = page_nv_bar.layoutParams.apply { binding.pageNvBar.layoutParams = binding.pageNvBar.layoutParams.apply {
height = if (hideNavigationBar) 0 else App.navigationBarHeight height = if (hideNavigationBar) 0 else App.navigationBarHeight
} }
content_text_view.upVisibleRect() binding.contentTextView.upVisibleRect()
upTime() upTime()
upBattery(battery) upBattery(battery)
} }
@ -100,27 +102,29 @@ class ContentView(context: Context) : FrameLayout(context) {
* 显示状态栏时隐藏header * 显示状态栏时隐藏header
*/ */
fun upStatusBar() { fun upStatusBar() {
vw_status_bar.topPadding = context.statusBarHeight binding.vwStatusBar.topPadding = context.statusBarHeight
vw_status_bar.isGone = binding.vwStatusBar.isGone =
ReadBookConfig.hideStatusBar || (activity as? BaseActivity)?.isInMultiWindow == true ReadBookConfig.hideStatusBar || (activity as? BaseActivity<*>)?.isInMultiWindow == true
} }
fun upTipStyle() { fun upTipStyle() {
ReadTipConfig.apply { ReadTipConfig.apply {
tv_header_left.isInvisible = tipHeaderLeft != chapterTitle binding.tvHeaderLeft.isInvisible = tipHeaderLeft != chapterTitle
bv_header_left.isInvisible = tipHeaderLeft == none || !tv_header_left.isInvisible binding.bvHeaderLeft.isInvisible =
tv_header_right.isGone = tipHeaderRight == none tipHeaderLeft == none || !binding.bvHeaderLeft.isInvisible
tv_header_middle.isGone = tipHeaderMiddle == none binding.tvHeaderRight.isGone = tipHeaderRight == none
tv_footer_left.isInvisible = tipFooterLeft != chapterTitle binding.tvHeaderMiddle.isGone = tipHeaderMiddle == none
bv_footer_left.isInvisible = tipFooterLeft == none || !tv_footer_left.isInvisible binding.tvFooterLeft.isInvisible = tipFooterLeft != chapterTitle
tv_footer_right.isGone = tipFooterRight == none binding.bvFooterLeft.isInvisible =
tv_footer_middle.isGone = tipFooterMiddle == none tipFooterLeft == none || !binding.tvFooterLeft.isInvisible
ll_header.isGone = when (headerMode) { binding.tvFooterRight.isGone = tipFooterRight == none
binding.tvFooterMiddle.isGone = tipFooterMiddle == none
binding.llHeader.isGone = when (headerMode) {
1 -> false 1 -> false
2 -> true 2 -> true
else -> !ReadBookConfig.hideStatusBar else -> !ReadBookConfig.hideStatusBar
} }
ll_footer.isGone = when (footerMode) { binding.llFooter.isGone = when (footerMode) {
1 -> true 1 -> true
else -> false else -> false
} }
@ -170,19 +174,19 @@ class ContentView(context: Context) : FrameLayout(context) {
private fun getTipView(tip: Int): BatteryView? { private fun getTipView(tip: Int): BatteryView? {
return when (tip) { return when (tip) {
ReadTipConfig.tipHeaderLeft -> ReadTipConfig.tipHeaderLeft ->
if (tip == ReadTipConfig.chapterTitle) tv_header_left else bv_header_left if (tip == ReadTipConfig.chapterTitle) binding.tvHeaderLeft else binding.bvHeaderLeft
ReadTipConfig.tipHeaderMiddle -> tv_header_middle ReadTipConfig.tipHeaderMiddle -> binding.tvHeaderMiddle
ReadTipConfig.tipHeaderRight -> tv_header_right ReadTipConfig.tipHeaderRight -> binding.tvHeaderRight
ReadTipConfig.tipFooterLeft -> ReadTipConfig.tipFooterLeft ->
if (tip == ReadTipConfig.chapterTitle) tv_footer_left else bv_footer_left if (tip == ReadTipConfig.chapterTitle) binding.tvFooterLeft else binding.bvFooterLeft
ReadTipConfig.tipFooterMiddle -> tv_footer_middle ReadTipConfig.tipFooterMiddle -> binding.tvFooterMiddle
ReadTipConfig.tipFooterRight -> tv_footer_right ReadTipConfig.tipFooterRight -> binding.tvFooterRight
else -> null else -> null
} }
} }
fun setBg(bg: Drawable?) { fun setBg(bg: Drawable?) {
page_panel.background = bg binding.pagePanel.background = bg
} }
fun upTime() { fun upTime() {
@ -209,15 +213,15 @@ class ContentView(context: Context) : FrameLayout(context) {
if (resetPageOffset) { if (resetPageOffset) {
resetPageOffset() resetPageOffset()
} }
content_text_view.setContent(pageData) binding.contentTextView.setContent(pageData)
} }
fun setContentDescription(content: String) { fun setContentDescription(content: String) {
content_text_view.contentDescription = content binding.contentTextView.contentDescription = content
} }
fun resetPageOffset() { fun resetPageOffset() {
content_text_view.resetPageOffset() binding.contentTextView.resetPageOffset()
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -230,40 +234,40 @@ class ContentView(context: Context) : FrameLayout(context) {
} }
fun scroll(offset: Int) { fun scroll(offset: Int) {
content_text_view.scroll(offset) binding.contentTextView.scroll(offset)
} }
fun upSelectAble(selectAble: Boolean) { fun upSelectAble(selectAble: Boolean) {
content_text_view.selectAble = selectAble binding.contentTextView.selectAble = selectAble
} }
fun selectText( fun selectText(
x: Float, y: Float, x: Float, y: Float,
select: (relativePage: Int, lineIndex: Int, charIndex: Int) -> Unit, select: (relativePage: Int, lineIndex: Int, charIndex: Int) -> Unit,
) { ) {
return content_text_view.selectText(x, y - headerHeight, select) return binding.contentTextView.selectText(x, y - headerHeight, select)
} }
fun selectStartMove(x: Float, y: Float) { fun selectStartMove(x: Float, y: Float) {
content_text_view.selectStartMove(x, y - headerHeight) binding.contentTextView.selectStartMove(x, y - headerHeight)
} }
fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) {
content_text_view.selectStartMoveIndex(relativePage, lineIndex, charIndex) binding.contentTextView.selectStartMoveIndex(relativePage, lineIndex, charIndex)
} }
fun selectEndMove(x: Float, y: Float) { fun selectEndMove(x: Float, y: Float) {
content_text_view.selectEndMove(x, y - headerHeight) binding.contentTextView.selectEndMove(x, y - headerHeight)
} }
fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) {
content_text_view.selectEndMoveIndex(relativePage, lineIndex, charIndex) binding.contentTextView.selectEndMoveIndex(relativePage, lineIndex, charIndex)
} }
fun cancelSelect() { fun cancelSelect() {
content_text_view.cancelSelect() binding.contentTextView.cancelSelect()
} }
val selectedText: String get() = content_text_view.selectedText val selectedText: String get() = binding.contentTextView.selectedText
} }

@ -20,7 +20,6 @@ import io.legado.app.ui.book.read.page.entities.TextChapter
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.activity import io.legado.app.utils.activity
import io.legado.app.utils.screenshot import io.legado.app.utils.screenshot
import kotlinx.android.synthetic.main.activity_book_read.view.*
import kotlin.math.abs import kotlin.math.abs
class PageView(context: Context, attrs: AttributeSet) : class PageView(context: Context, attrs: AttributeSet) :
@ -123,13 +122,13 @@ class PageView(context: Context, attrs: AttributeSet) :
if (!isInEditMode && callBack.isAutoPage && !isScroll) { if (!isInEditMode && callBack.isAutoPage && !isScroll) {
nextPage.screenshot()?.let { nextPage.screenshot()?.let {
val bottom = val bottom =
page_view.height * callBack.autoPageProgress / (ReadBookConfig.autoReadSpeed * 50) height * callBack.autoPageProgress / (ReadBookConfig.autoReadSpeed * 50)
autoPageRect.set(0, 0, page_view.width, bottom) autoPageRect.set(0, 0, width, bottom)
canvas.drawBitmap(it, autoPageRect, autoPageRect, null) canvas.drawBitmap(it, autoPageRect, autoPageRect, null)
canvas.drawRect( canvas.drawRect(
0f, 0f,
bottom.toFloat() - 1, bottom.toFloat() - 1,
page_view.width.toFloat(), width.toFloat(),
bottom.toFloat(), bottom.toFloat(),
autoPagePint autoPagePint
) )

@ -19,13 +19,12 @@ import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.data.entities.SearchKeyword import io.legado.app.data.entities.SearchKeyword
import io.legado.app.databinding.ActivityBookSearchBinding
import io.legado.app.lib.theme.* import io.legado.app.lib.theme.*
import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.book.source.manage.BookSourceActivity
import io.legado.app.ui.widget.recycler.LoadMoreView import io.legado.app.ui.widget.recycler.LoadMoreView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_search.*
import kotlinx.android.synthetic.main.view_search.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -34,7 +33,7 @@ import org.jetbrains.anko.startActivity
import java.text.Collator import java.text.Collator
class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_search), class SearchActivity : VMBaseActivity<ActivityBookSearchBinding, SearchViewModel>(),
BookAdapter.CallBack, BookAdapter.CallBack,
HistoryKeyAdapter.CallBack, HistoryKeyAdapter.CallBack,
SearchAdapter.CallBack { SearchAdapter.CallBack {
@ -46,6 +45,7 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
private lateinit var bookAdapter: BookAdapter private lateinit var bookAdapter: BookAdapter
private lateinit var historyKeyAdapter: HistoryKeyAdapter private lateinit var historyKeyAdapter: HistoryKeyAdapter
private lateinit var loadMoreView: LoadMoreView private lateinit var loadMoreView: LoadMoreView
private lateinit var serchView: SearchView
private var historyData: LiveData<List<SearchKeyword>>? = null private var historyData: LiveData<List<SearchKeyword>>? = null
private var bookData: LiveData<List<Book>>? = null private var bookData: LiveData<List<Book>>? = null
private var menu: Menu? = null private var menu: Menu? = null
@ -53,7 +53,8 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
private var groups = linkedSetOf<String>() private var groups = linkedSetOf<String>()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
ll_history.setBackgroundColor(backgroundColor) binding.llHistory.setBackgroundColor(backgroundColor)
serchView = binding.titleBar.findViewById(R.id.search_view)
initRecyclerView() initRecyclerView()
initSearchView() initSearchView()
initOtherView() initOtherView()
@ -83,8 +84,8 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
!getPrefBoolean(PreferKey.precisionSearch) !getPrefBoolean(PreferKey.precisionSearch)
) )
precisionSearchMenuItem?.isChecked = getPrefBoolean(PreferKey.precisionSearch) precisionSearchMenuItem?.isChecked = getPrefBoolean(PreferKey.precisionSearch)
search_view.query?.toString()?.trim()?.let { serchView.query?.toString()?.trim()?.let {
search_view.setQuery(it, true) serchView.setQuery(it, true)
} }
} }
R.id.menu_source_manage -> startActivity<BookSourceActivity>() R.id.menu_source_manage -> startActivity<BookSourceActivity>()
@ -95,8 +96,8 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} else { } else {
putPrefString("searchGroup", item.title.toString()) putPrefString("searchGroup", item.title.toString())
} }
search_view.query?.toString()?.trim()?.let { serchView.query?.toString()?.trim()?.let {
search_view.setQuery(it, true) serchView.setQuery(it, true)
} }
} }
} }
@ -104,14 +105,14 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} }
private fun initSearchView() { private fun initSearchView() {
ATH.setTint(search_view, primaryTextColor) ATH.setTint(serchView, primaryTextColor)
search_view.onActionViewExpanded() serchView.onActionViewExpanded()
search_view.isSubmitButtonEnabled = true serchView.isSubmitButtonEnabled = true
search_view.queryHint = getString(R.string.search_book_key) serchView.queryHint = getString(R.string.search_book_key)
search_view.clearFocus() serchView.clearFocus()
search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener { serchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean { override fun onQueryTextSubmit(query: String?): Boolean {
search_view.clearFocus() serchView.clearFocus()
query?.let { query?.let {
viewModel.saveSearchKey(query) viewModel.saveSearchKey(query)
viewModel.search(it) viewModel.search(it)
@ -126,8 +127,8 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
return false return false
} }
}) })
search_view.setOnQueryTextFocusChangeListener { _, hasFocus -> serchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
if (!hasFocus && search_view.query.toString().trim().isEmpty()) { if (!hasFocus && serchView.query.toString().trim().isEmpty()) {
finish() finish()
} else { } else {
openOrCloseHistory(hasFocus) openOrCloseHistory(hasFocus)
@ -137,28 +138,28 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
ATH.applyEdgeEffectColor(rv_bookshelf_search) ATH.applyEdgeEffectColor(binding.rvBookshelfSearch)
ATH.applyEdgeEffectColor(rv_history_key) ATH.applyEdgeEffectColor(binding.rvHistoryKey)
bookAdapter = BookAdapter(this, this) bookAdapter = BookAdapter(this, this)
rv_bookshelf_search.layoutManager = FlexboxLayoutManager(this) binding.rvBookshelfSearch.layoutManager = FlexboxLayoutManager(this)
rv_bookshelf_search.adapter = bookAdapter binding.rvBookshelfSearch.adapter = bookAdapter
historyKeyAdapter = HistoryKeyAdapter(this, this) historyKeyAdapter = HistoryKeyAdapter(this, this)
rv_history_key.layoutManager = FlexboxLayoutManager(this) binding.rvHistoryKey.layoutManager = FlexboxLayoutManager(this)
rv_history_key.adapter = historyKeyAdapter binding.rvHistoryKey.adapter = historyKeyAdapter
adapter = SearchAdapter(this, this) adapter = SearchAdapter(this, this)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount) super.onItemRangeInserted(positionStart, itemCount)
if (positionStart == 0) { if (positionStart == 0) {
recycler_view.scrollToPosition(0) binding.recyclerView.scrollToPosition(0)
} }
} }
}) })
loadMoreView = LoadMoreView(this) loadMoreView = LoadMoreView(this)
recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() { binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
if (!recyclerView.canScrollVertically(1)) { if (!recyclerView.canScrollVertically(1)) {
@ -169,16 +170,16 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
} }
private fun initOtherView() { private fun initOtherView() {
fb_stop.backgroundTintList = binding.fbStop.backgroundTintList =
Selector.colorBuild() Selector.colorBuild()
.setDefaultColor(accentColor) .setDefaultColor(accentColor)
.setPressedColor(ColorUtils.darkenColor(accentColor)) .setPressedColor(ColorUtils.darkenColor(accentColor))
.create() .create()
fb_stop.onClick { binding.fbStop.onClick {
viewModel.stop() viewModel.stop()
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
} }
tv_clear_history.onClick { viewModel.clearHistory() } binding.tvClearHistory.onClick { viewModel.clearHistory() }
} }
private fun initLiveData() { private fun initLiveData() {
@ -203,9 +204,9 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
private fun receiptIntent(intent: Intent? = null) { private fun receiptIntent(intent: Intent? = null) {
intent?.getStringExtra("key")?.let { intent?.getStringExtra("key")?.let {
search_view.setQuery(it, true) serchView.setQuery(it, true)
} ?: let { } ?: let {
search_view.requestFocus() serchView.requestFocus()
} }
} }
@ -223,10 +224,10 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
*/ */
private fun openOrCloseHistory(open: Boolean) { private fun openOrCloseHistory(open: Boolean) {
if (open) { if (open) {
upHistory(search_view.query.toString()) upHistory(serchView.query.toString())
ll_history.visibility = VISIBLE binding.llHistory.visibility = VISIBLE
} else { } else {
ll_history.visibility = GONE binding.llHistory.visibility = GONE
} }
} }
@ -256,17 +257,17 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
private fun upHistory(key: String? = null) { private fun upHistory(key: String? = null) {
bookData?.removeObservers(this) bookData?.removeObservers(this)
if (key.isNullOrBlank()) { if (key.isNullOrBlank()) {
tv_book_show.gone() binding.tvBookShow.gone()
rv_bookshelf_search.gone() binding.rvBookshelfSearch.gone()
} else { } else {
bookData = App.db.bookDao().liveDataSearch(key) bookData = App.db.bookDao().liveDataSearch(key)
bookData?.observe(this, { bookData?.observe(this, {
if (it.isEmpty()) { if (it.isEmpty()) {
tv_book_show.gone() binding.tvBookShow.gone()
rv_bookshelf_search.gone() binding.rvBookshelfSearch.gone()
} else { } else {
tv_book_show.visible() binding.tvBookShow.visible()
rv_bookshelf_search.visible() binding.rvBookshelfSearch.visible()
} }
bookAdapter.setItems(it) bookAdapter.setItems(it)
}) })
@ -281,9 +282,9 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
historyData?.observe(this, { historyData?.observe(this, {
historyKeyAdapter.setItems(it) historyKeyAdapter.setItems(it)
if (it.isEmpty()) { if (it.isEmpty()) {
tv_clear_history.invisible() binding.tvClearHistory.invisible()
} else { } else {
tv_clear_history.visible() binding.tvClearHistory.visible()
} }
}) })
} }
@ -300,17 +301,17 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
* 开始搜索 * 开始搜索
*/ */
private fun startSearch() { private fun startSearch() {
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.isAutoLoading = true
fb_stop.visible() binding.fbStop.visible()
} }
/** /**
* 搜索结束 * 搜索结束
*/ */
private fun searchFinally() { private fun searchFinally() {
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
loadMoreView.startLoad() loadMoreView.startLoad()
fb_stop.invisible() binding.fbStop.invisible()
} }
/** /**
@ -343,14 +344,14 @@ class SearchActivity : VMBaseActivity<SearchViewModel>(R.layout.activity_book_se
override fun searchHistory(key: String) { override fun searchHistory(key: String) {
launch { launch {
when { when {
search_view.query.toString() == key -> { serchView.query.toString() == key -> {
search_view.setQuery(key, true) serchView.setQuery(key, true)
} }
withContext(IO) { App.db.bookDao().findByName(key).isEmpty() } -> { withContext(IO) { App.db.bookDao().findByName(key).isEmpty() } -> {
search_view.setQuery(key, true) serchView.setQuery(key, true)
} }
else -> { else -> {
search_view.setQuery(key, false) serchView.setQuery(key, false)
} }
} }
} }

@ -11,6 +11,7 @@ import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.databinding.ActivitySearchContentBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
@ -22,8 +23,6 @@ import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.ColorUtils import io.legado.app.utils.ColorUtils
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.observeEvent import io.legado.app.utils.observeEvent
import kotlinx.android.synthetic.main.activity_search_content.*
import kotlinx.android.synthetic.main.view_search.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -31,24 +30,26 @@ import org.jetbrains.anko.sdk27.listeners.onClick
class SearchContentActivity : class SearchContentActivity :
VMBaseActivity<SearchContentViewModel>(R.layout.activity_search_content), VMBaseActivity<ActivitySearchContentBinding, SearchContentViewModel>(),
SearchContentAdapter.Callback { SearchContentAdapter.Callback {
override val viewModel: SearchContentViewModel override val viewModel: SearchContentViewModel
get() = getViewModel(SearchContentViewModel::class.java) get() = getViewModel(SearchContentViewModel::class.java)
lateinit var adapter: SearchContentAdapter lateinit var adapter: SearchContentAdapter
private lateinit var mLayoutManager: UpLinearLayoutManager private lateinit var mLayoutManager: UpLinearLayoutManager
private lateinit var searchView: SearchView
private var searchResultCounts = 0 private var searchResultCounts = 0
private var durChapterIndex = 0 private var durChapterIndex = 0
private var searchResultList: MutableList<SearchResult> = mutableListOf() private var searchResultList: MutableList<SearchResult> = mutableListOf()
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
searchView = binding.titleBar.findViewById(R.id.search_view)
val bbg = bottomBackground val bbg = bottomBackground
val btc = getPrimaryTextColor(ColorUtils.isColorLight(bbg)) val btc = getPrimaryTextColor(ColorUtils.isColorLight(bbg))
ll_search_base_info.setBackgroundColor(bbg) binding.llSearchBaseInfo.setBackgroundColor(bbg)
tv_current_search_info.setTextColor(btc) binding.tvCurrentSearchInfo.setTextColor(btc)
iv_search_content_top.setColorFilter(btc) binding.ivSearchContentTop.setColorFilter(btc)
iv_search_content_bottom.setColorFilter(btc) binding.ivSearchContentBottom.setColorFilter(btc)
initSearchView() initSearchView()
initRecyclerView() initRecyclerView()
initView() initView()
@ -60,12 +61,12 @@ class SearchContentActivity :
} }
private fun initSearchView() { private fun initSearchView() {
ATH.setTint(search_view, primaryTextColor) ATH.setTint(searchView, primaryTextColor)
search_view.onActionViewExpanded() searchView.onActionViewExpanded()
search_view.isSubmitButtonEnabled = true searchView.isSubmitButtonEnabled = true
search_view.queryHint = getString(R.string.search) searchView.queryHint = getString(R.string.search)
search_view.clearFocus() searchView.clearFocus()
search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
if (viewModel.lastQuery != query) { if (viewModel.lastQuery != query) {
startContentSearch(query) startContentSearch(query)
@ -82,14 +83,14 @@ class SearchContentActivity :
private fun initRecyclerView() { private fun initRecyclerView() {
adapter = SearchContentAdapter(this, this) adapter = SearchContentAdapter(this, this)
mLayoutManager = UpLinearLayoutManager(this) mLayoutManager = UpLinearLayoutManager(this)
recycler_view.layoutManager = mLayoutManager binding.recyclerView.layoutManager = mLayoutManager
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
} }
private fun initView() { private fun initView() {
iv_search_content_top.onClick { mLayoutManager.scrollToPositionWithOffset(0, 0) } binding.ivSearchContentTop.onClick { mLayoutManager.scrollToPositionWithOffset(0, 0) }
iv_search_content_bottom.onClick { binding.ivSearchContentBottom.onClick {
if (adapter.itemCount > 0) { if (adapter.itemCount > 0) {
mLayoutManager.scrollToPositionWithOffset(adapter.itemCount - 1, 0) mLayoutManager.scrollToPositionWithOffset(adapter.itemCount - 1, 0)
} }
@ -98,12 +99,12 @@ class SearchContentActivity :
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun initBook() { private fun initBook() {
tv_current_search_info.text = "搜索结果:$searchResultCounts" binding.tvCurrentSearchInfo.text = "搜索结果:$searchResultCounts"
viewModel.book?.let { viewModel.book?.let {
initCacheFileNames(it) initCacheFileNames(it)
durChapterIndex = it.durChapterIndex durChapterIndex = it.durChapterIndex
intent.getStringExtra("searchWord")?.let { searchWord -> intent.getStringExtra("searchWord")?.let { searchWord ->
search_view.setQuery(searchWord, true) searchView.setQuery(searchWord, true)
} }
} }
} }
@ -131,10 +132,10 @@ class SearchContentActivity :
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun startContentSearch(newText: String) { fun startContentSearch(newText: String) {
// 按章节搜索内容 // 按章节搜索内容
if (!newText.isBlank()) { if (newText.isNotBlank()) {
adapter.clearItems() adapter.clearItems()
searchResultList.clear() searchResultList.clear()
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.isAutoLoading = true
searchResultCounts = 0 searchResultCounts = 0
viewModel.lastQuery = newText viewModel.lastQuery = newText
var searchResults = listOf<SearchResult>() var searchResults = listOf<SearchResult>()
@ -149,8 +150,8 @@ class SearchContentActivity :
} }
if (searchResults.isNotEmpty()) { if (searchResults.isNotEmpty()) {
searchResultList.addAll(searchResults) searchResultList.addAll(searchResults)
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
tv_current_search_info.text = "搜索结果:$searchResultCounts" binding.tvCurrentSearchInfo.text = "搜索结果:$searchResultCounts"
adapter.addItems(searchResults) adapter.addItems(searchResults)
searchResults = listOf() searchResults = listOf()
} }

@ -7,54 +7,54 @@ import android.view.MenuItem
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivitySourceDebugBinding
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.qrcode.QrCodeActivity
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_source_debug.*
import kotlinx.android.synthetic.main.view_search.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class BookSourceDebugActivity : class BookSourceDebugActivity : VMBaseActivity<ActivitySourceDebugBinding, BookSourceDebugModel>() {
VMBaseActivity<BookSourceDebugModel>(R.layout.activity_source_debug) {
override val viewModel: BookSourceDebugModel override val viewModel: BookSourceDebugModel
get() = getViewModel(BookSourceDebugModel::class.java) get() = getViewModel(BookSourceDebugModel::class.java)
private lateinit var adapter: BookSourceDebugAdapter private lateinit var adapter: BookSourceDebugAdapter
private lateinit var searchView: SearchView
private val qrRequestCode = 101 private val qrRequestCode = 101
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
searchView = binding.titleBar.findViewById(R.id.search_view)
viewModel.init(intent.getStringExtra("key")) viewModel.init(intent.getStringExtra("key"))
initRecyclerView() initRecyclerView()
initSearchView() initSearchView()
viewModel.observe{state, msg-> viewModel.observe { state, msg ->
launch { launch {
adapter.addItem(msg) adapter.addItem(msg)
if (state == -1 || state == 1000) { if (state == -1 || state == 1000) {
rotate_loading.hide() binding.rotateLoading.hide()
} }
} }
} }
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
adapter = BookSourceDebugAdapter(this) adapter = BookSourceDebugAdapter(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
rotate_loading.loadingColor = accentColor binding.rotateLoading.loadingColor = accentColor
} }
private fun initSearchView() { private fun initSearchView() {
search_view.onActionViewExpanded() searchView.onActionViewExpanded()
search_view.isSubmitButtonEnabled = true searchView.isSubmitButtonEnabled = true
search_view.queryHint = getString(R.string.search_book_key) searchView.queryHint = getString(R.string.search_book_key)
search_view.clearFocus() searchView.clearFocus()
search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean { override fun onQueryTextSubmit(query: String?): Boolean {
search_view.clearFocus() searchView.clearFocus()
startSearch(query ?: "我的") startSearch(query ?: "我的")
return true return true
} }
@ -68,7 +68,7 @@ class BookSourceDebugActivity :
private fun startSearch(key: String) { private fun startSearch(key: String) {
adapter.clearItems() adapter.clearItems()
viewModel.startDebug(key, { viewModel.startDebug(key, {
rotate_loading.show() binding.rotateLoading.show()
}, { }, {
toast("未获取到书源") toast("未获取到书源")
}) })

@ -18,6 +18,7 @@ import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.rule.* import io.legado.app.data.entities.rule.*
import io.legado.app.databinding.ActivityBookSourceEditBinding
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.backgroundColor import io.legado.app.lib.theme.backgroundColor
@ -29,12 +30,11 @@ import io.legado.app.ui.qrcode.QrCodeActivity
import io.legado.app.ui.widget.KeyboardToolPop import io.legado.app.ui.widget.KeyboardToolPop
import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_source_edit.*
import org.jetbrains.anko.* import org.jetbrains.anko.*
import kotlin.math.abs import kotlin.math.abs
class BookSourceEditActivity : class BookSourceEditActivity :
VMBaseActivity<BookSourceEditViewModel>(R.layout.activity_book_source_edit, false), VMBaseActivity<ActivityBookSourceEditBinding, BookSourceEditViewModel>(false),
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
KeyboardToolPop.CallBack { KeyboardToolPop.CallBack {
override val viewModel: BookSourceEditViewModel override val viewModel: BookSourceEditViewModel
@ -116,13 +116,13 @@ class BookSourceEditActivity :
} }
private fun initView() { private fun initView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this) mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this)
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(KeyboardOnGlobalChangeListener()) window.decorView.viewTreeObserver.addOnGlobalLayoutListener(KeyboardOnGlobalChangeListener())
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
tab_layout.setBackgroundColor(backgroundColor) binding.tabLayout.setBackgroundColor(backgroundColor)
tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabReselected(tab: TabLayout.Tab?) { override fun onTabReselected(tab: TabLayout.Tab?) {
} }
@ -166,14 +166,14 @@ class BookSourceEditActivity :
5 -> adapter.editEntities = contentEntities 5 -> adapter.editEntities = contentEntities
else -> adapter.editEntities = sourceEntities else -> adapter.editEntities = sourceEntities
} }
recycler_view.scrollToPosition(0) binding.recyclerView.scrollToPosition(0)
} }
private fun upRecyclerView(source: BookSource? = viewModel.bookSource) { private fun upRecyclerView(source: BookSource? = viewModel.bookSource) {
source?.let { source?.let {
cb_is_enable.isChecked = it.enabled binding.cbIsEnable.isChecked = it.enabled
cb_is_enable_find.isChecked = it.enabledExplore binding.cbIsEnableFind.isChecked = it.enabledExplore
sp_type.setSelection(it.bookSourceType) binding.spType.setSelection(it.bookSourceType)
} }
//基本信息 //基本信息
sourceEntities.clear() sourceEntities.clear()
@ -253,15 +253,15 @@ class BookSourceEditActivity :
add(EditEntity("coverUrl", er?.coverUrl, R.string.rule_cover_url)) add(EditEntity("coverUrl", er?.coverUrl, R.string.rule_cover_url))
add(EditEntity("bookUrl", er?.bookUrl, R.string.r_book_url)) add(EditEntity("bookUrl", er?.bookUrl, R.string.r_book_url))
} }
tab_layout.selectTab(tab_layout.getTabAt(0)) binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0))
setEditEntities(0) setEditEntities(0)
} }
private fun getSource(): BookSource { private fun getSource(): BookSource {
val source = viewModel.bookSource?.copy() ?: BookSource() val source = viewModel.bookSource?.copy() ?: BookSource()
source.enabled = cb_is_enable.isChecked source.enabled = binding.cbIsEnable.isChecked
source.enabledExplore = cb_is_enable_find.isChecked source.enabledExplore = binding.cbIsEnableFind.isChecked
source.bookSourceType = sp_type.selectedItemPosition source.bookSourceType = binding.spType.selectedItemPosition
val searchRule = SearchRule() val searchRule = SearchRule()
val exploreRule = ExploreRule() val exploreRule = ExploreRule()
val bookInfoRule = BookInfoRule() val bookInfoRule = BookInfoRule()
@ -407,7 +407,7 @@ class BookSourceEditActivity :
mSoftKeyboardTool?.let { mSoftKeyboardTool?.let {
if (it.isShowing) return if (it.isShowing) return
if (!isFinishing) { if (!isFinishing) {
it.showAtLocation(ll_content, Gravity.BOTTOM, 0, 0) it.showAtLocation(binding.root, Gravity.BOTTOM, 0, 0)
} }
} }
} }
@ -448,11 +448,11 @@ class BookSourceEditActivity :
val preShowing = mIsSoftKeyBoardShowing val preShowing = mIsSoftKeyBoardShowing
if (abs(keyboardHeight) > screenHeight / 5) { if (abs(keyboardHeight) > screenHeight / 5) {
mIsSoftKeyBoardShowing = true // 超过屏幕五分之一则表示弹出了输入法 mIsSoftKeyBoardShowing = true // 超过屏幕五分之一则表示弹出了输入法
recycler_view.setPadding(0, 0, 0, 100) binding.recyclerView.setPadding(0, 0, 0, 100)
showKeyboardTopPopupWindow() showKeyboardTopPopupWindow()
} else { } else {
mIsSoftKeyBoardShowing = false mIsSoftKeyBoardShowing = false
recycler_view.setPadding(0, 0, 0, 0) binding.recyclerView.setPadding(0, 0, 0, 0)
if (preShowing) { if (preShowing) {
closePopupWindow() closePopupWindow()
} }

@ -21,6 +21,7 @@ import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ActivityBookSourceBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.help.LocalConfig import io.legado.app.help.LocalConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
@ -39,16 +40,13 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_book_source.*
import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import java.io.File import java.io.File
import java.text.Collator import java.text.Collator
class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity_book_source), class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceViewModel>(),
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
BookSourceAdapter.CallBack, BookSourceAdapter.CallBack,
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
@ -61,6 +59,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
private val importRequestCode = 132 private val importRequestCode = 132
private val exportRequestCode = 65 private val exportRequestCode = 65
private lateinit var adapter: BookSourceAdapter private lateinit var adapter: BookSourceAdapter
private lateinit var searchView: SearchView
private var bookSourceLiveDate: LiveData<List<BookSource>>? = null private var bookSourceLiveDate: LiveData<List<BookSource>>? = null
private var groups = linkedSetOf<String>() private var groups = linkedSetOf<String>()
private var groupMenu: SubMenu? = null private var groupMenu: SubMenu? = null
@ -69,6 +68,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
private var snackBar: Snackbar? = null private var snackBar: Snackbar? = null
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
searchView = binding.titleBar.findViewById(R.id.search_view)
initRecyclerView() initRecyclerView()
initSearchView() initSearchView()
initLiveDataBookSource() initLiveDataBookSource()
@ -105,65 +105,65 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
R.id.menu_sort_manual -> { R.id.menu_sort_manual -> {
item.isChecked = true item.isChecked = true
sortCheck(0) sortCheck(0)
initLiveDataBookSource(search_view.query?.toString()) initLiveDataBookSource(searchView.query?.toString())
} }
R.id.menu_sort_auto -> { R.id.menu_sort_auto -> {
item.isChecked = true item.isChecked = true
sortCheck(1) sortCheck(1)
initLiveDataBookSource(search_view.query?.toString()) initLiveDataBookSource(searchView.query?.toString())
} }
R.id.menu_sort_pin_yin -> { R.id.menu_sort_pin_yin -> {
item.isChecked = true item.isChecked = true
sortCheck(2) sortCheck(2)
initLiveDataBookSource(search_view.query?.toString()) initLiveDataBookSource(searchView.query?.toString())
} }
R.id.menu_sort_url -> { R.id.menu_sort_url -> {
item.isChecked = true item.isChecked = true
sortCheck(3) sortCheck(3)
initLiveDataBookSource(search_view.query?.toString()) initLiveDataBookSource(searchView.query?.toString())
} }
R.id.menu_sort_time -> { R.id.menu_sort_time -> {
item.isChecked = true item.isChecked = true
sortCheck(4) sortCheck(4)
initLiveDataBookSource(search_view.query?.toString()) initLiveDataBookSource(searchView.query?.toString())
} }
R.id.menu_enabled_group -> { R.id.menu_enabled_group -> {
search_view.setQuery(getString(R.string.enabled), true) searchView.setQuery(getString(R.string.enabled), true)
} }
R.id.menu_disabled_group -> { R.id.menu_disabled_group -> {
search_view.setQuery(getString(R.string.disabled), true) searchView.setQuery(getString(R.string.disabled), true)
} }
R.id.menu_help -> showHelp() R.id.menu_help -> showHelp()
} }
if (item.groupId == R.id.source_group) { if (item.groupId == R.id.source_group) {
search_view.setQuery(item.title, true) searchView.setQuery(item.title, true)
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
adapter = BookSourceAdapter(this, this) adapter = BookSourceAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
val itemTouchCallback = ItemTouchCallback(adapter) val itemTouchCallback = ItemTouchCallback(adapter)
itemTouchCallback.isCanDrag = true itemTouchCallback.isCanDrag = true
val dragSelectTouchHelper: DragSelectTouchHelper = val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50) DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view) dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
// When this page is opened, it is in selection mode // When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect() dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it. // Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view) ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
} }
private fun initSearchView() { private fun initSearchView() {
ATH.setTint(search_view, primaryTextColor) ATH.setTint(searchView, primaryTextColor)
search_view.onActionViewExpanded() searchView.onActionViewExpanded()
search_view.queryHint = getString(R.string.search_book_source) searchView.queryHint = getString(R.string.search_book_source)
search_view.clearFocus() searchView.clearFocus()
search_view.setOnQueryTextListener(this) searchView.setOnQueryTextListener(this)
} }
private fun initLiveDataBookSource(searchKey: String? = null) { private fun initLiveDataBookSource(searchKey: String? = null) {
@ -250,10 +250,10 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
private fun initSelectActionBar() { private fun initSelectActionBar() {
select_action_bar.setMainActionText(R.string.delete) binding.selectActionBar.setMainActionText(R.string.delete)
select_action_bar.inflateMenu(R.menu.book_source_sel) binding.selectActionBar.inflateMenu(R.menu.book_source_sel)
select_action_bar.setOnMenuItemClickListener(this) binding.selectActionBar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this) binding.selectActionBar.setCallBack(this)
} }
override fun onMenuItemClick(item: MenuItem?): Boolean { override fun onMenuItemClick(item: MenuItem?): Boolean {
@ -278,8 +278,8 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setText(CheckSource.keyword) editText?.setText(CheckSource.keyword)
} }
} }
okButton { okButton {
@ -300,10 +300,10 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setHint(R.string.group_name) editText?.setHint(R.string.group_name)
edit_view.setFilterValues(groups.toList()) editText?.setFilterValues(groups.toList())
edit_view.dropDownHeight = 180.dp editText?.dropDownHeight = 180.dp
} }
} }
okButton { okButton {
@ -323,10 +323,10 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setHint(R.string.group_name) editText?.setHint(R.string.group_name)
edit_view.setFilterValues(groups.toList()) editText?.setFilterValues(groups.toList())
edit_view.dropDownHeight = 180.dp editText?.dropDownHeight = 180.dp
} }
} }
okButton { okButton {
@ -359,9 +359,9 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setFilterValues(cacheUrls) editText?.setFilterValues(cacheUrls)
edit_view.delCallBack = { editText?.delCallBack = {
cacheUrls.remove(it) cacheUrls.remove(it)
aCache.put(importRecordKey, cacheUrls.joinToString(",")) aCache.put(importRecordKey, cacheUrls.joinToString(","))
} }
@ -385,7 +385,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
observeEvent<String>(EventBus.CHECK_SOURCE) { msg -> observeEvent<String>(EventBus.CHECK_SOURCE) { msg ->
snackBar?.setText(msg) ?: let { snackBar?.setText(msg) ?: let {
snackBar = Snackbar snackBar = Snackbar
.make(root_view, msg, Snackbar.LENGTH_INDEFINITE) .make(binding.root, msg, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.cancel) { .setAction(R.string.cancel) {
CheckSource.stop(this) CheckSource.stop(this)
}.apply { show() } }.apply { show() }
@ -396,7 +396,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
snackBar = null snackBar = null
groups.map { group -> groups.map { group ->
if (group.contains("失效")) { if (group.contains("失效")) {
search_view.setQuery("失效", true) searchView.setQuery("失效", true)
toast("发现有失效书源,已为您自动筛选!") toast("发现有失效书源,已为您自动筛选!")
} }
} }
@ -404,7 +404,8 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
override fun upCountView() { override fun upCountView() {
select_action_bar.upCountView(adapter.getSelection().size, adapter.getActualItemCount()) binding.selectActionBar
.upCountView(adapter.getSelection().size, adapter.getActualItemCount())
} }
override fun onQueryTextChange(newText: String?): Boolean { override fun onQueryTextChange(newText: String?): Boolean {
@ -479,10 +480,10 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
override fun finish() { override fun finish() {
if (search_view.query.isNullOrEmpty()) { if (searchView.query.isNullOrEmpty()) {
super.finish() super.finish()
} else { } else {
search_view.setQuery("", true) searchView.setQuery("", true)
} }
} }

@ -7,31 +7,33 @@ import androidx.core.view.isGone
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter import androidx.fragment.app.FragmentPagerAdapter
import com.google.android.material.tabs.TabLayout
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivityChapterListBinding
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.gone import io.legado.app.utils.gone
import io.legado.app.utils.visible import io.legado.app.utils.visible
import kotlinx.android.synthetic.main.activity_chapter_list.*
import kotlinx.android.synthetic.main.view_tab_layout.*
class ChapterListActivity : VMBaseActivity<ChapterListViewModel>(R.layout.activity_chapter_list) { class ChapterListActivity : VMBaseActivity<ActivityChapterListBinding, ChapterListViewModel>() {
override val viewModel: ChapterListViewModel override val viewModel: ChapterListViewModel
get() = getViewModel(ChapterListViewModel::class.java) get() = getViewModel(ChapterListViewModel::class.java)
private lateinit var tabLayout: TabLayout
private var searchView: SearchView? = null private var searchView: SearchView? = null
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
tab_layout.isTabIndicatorFullWidth = false tabLayout = binding.titleBar.findViewById(R.id.tab_layout)
tab_layout.setSelectedTabIndicatorColor(accentColor) tabLayout.isTabIndicatorFullWidth = false
tabLayout.setSelectedTabIndicatorColor(accentColor)
intent.getStringExtra("bookUrl")?.let { intent.getStringExtra("bookUrl")?.let {
viewModel.initBook(it) { viewModel.initBook(it) {
view_pager.adapter = TabFragmentPageAdapter(supportFragmentManager) binding.viewPager.adapter = TabFragmentPageAdapter(supportFragmentManager)
tab_layout.setupWithViewPager(view_pager) tabLayout.setupWithViewPager(binding.viewPager)
} }
} }
} }
@ -44,17 +46,17 @@ class ChapterListActivity : VMBaseActivity<ChapterListViewModel>(R.layout.activi
searchView?.maxWidth = resources.displayMetrics.widthPixels searchView?.maxWidth = resources.displayMetrics.widthPixels
searchView?.onActionViewCollapsed() searchView?.onActionViewCollapsed()
searchView?.setOnCloseListener { searchView?.setOnCloseListener {
tab_layout.visible() tabLayout.visible()
false false
} }
searchView?.setOnSearchClickListener { tab_layout.gone() } searchView?.setOnSearchClickListener { tabLayout.gone() }
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
return false return false
} }
override fun onQueryTextChange(newText: String): Boolean { override fun onQueryTextChange(newText: String): Boolean {
if (tab_layout.selectedTabPosition == 1) { if (tabLayout.selectedTabPosition == 1) {
viewModel.startBookmarkSearch(newText) viewModel.startBookmarkSearch(newText)
} else { } else {
viewModel.startChapterListSearch(newText) viewModel.startChapterListSearch(newText)
@ -78,7 +80,7 @@ class ChapterListActivity : VMBaseActivity<ChapterListViewModel>(R.layout.activi
return 2 return 2
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
return when (position) { return when (position) {
1 -> getString(R.string.bookmark) 1 -> getString(R.string.bookmark)
else -> getString(R.string.chapter_list) else -> getString(R.string.chapter_list)
@ -88,9 +90,9 @@ class ChapterListActivity : VMBaseActivity<ChapterListViewModel>(R.layout.activi
} }
override fun onBackPressed() { override fun onBackPressed() {
if (tab_layout.isGone) { if (tabLayout.isGone) {
searchView?.onActionViewCollapsed() searchView?.onActionViewCollapsed()
tab_layout.visible() tabLayout.visible()
} else { } else {
super.onBackPressed() super.onBackPressed()
} }

@ -4,11 +4,11 @@ import android.os.Bundle
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.databinding.ActivityConfigBinding
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.observeEvent import io.legado.app.utils.observeEvent
import kotlinx.android.synthetic.main.activity_config.*
class ConfigActivity : VMBaseActivity<ConfigViewModel>(R.layout.activity_config) { class ConfigActivity : VMBaseActivity<ActivityConfigBinding, ConfigViewModel>() {
override val viewModel: ConfigViewModel override val viewModel: ConfigViewModel
get() = getViewModel(ConfigViewModel::class.java) get() = getViewModel(ConfigViewModel::class.java)
@ -19,7 +19,7 @@ class ConfigActivity : VMBaseActivity<ConfigViewModel>(R.layout.activity_config)
when (viewModel.configType) { when (viewModel.configType) {
ConfigViewModel.TYPE_CONFIG -> { ConfigViewModel.TYPE_CONFIG -> {
title_bar.title = getString(R.string.other_setting) binding.titleBar.title = getString(R.string.other_setting)
val fTag = "otherConfigFragment" val fTag = "otherConfigFragment"
var configFragment = supportFragmentManager.findFragmentByTag(fTag) var configFragment = supportFragmentManager.findFragmentByTag(fTag)
if (configFragment == null) configFragment = OtherConfigFragment() if (configFragment == null) configFragment = OtherConfigFragment()
@ -28,7 +28,7 @@ class ConfigActivity : VMBaseActivity<ConfigViewModel>(R.layout.activity_config)
.commit() .commit()
} }
ConfigViewModel.TYPE_THEME_CONFIG -> { ConfigViewModel.TYPE_THEME_CONFIG -> {
title_bar.title = getString(R.string.theme_setting) binding.titleBar.title = getString(R.string.theme_setting)
val fTag = "themeConfigFragment" val fTag = "themeConfigFragment"
var configFragment = supportFragmentManager.findFragmentByTag(fTag) var configFragment = supportFragmentManager.findFragmentByTag(fTag)
if (configFragment == null) configFragment = ThemeConfigFragment() if (configFragment == null) configFragment = ThemeConfigFragment()
@ -37,7 +37,7 @@ class ConfigActivity : VMBaseActivity<ConfigViewModel>(R.layout.activity_config)
.commit() .commit()
} }
ConfigViewModel.TYPE_WEB_DAV_CONFIG -> { ConfigViewModel.TYPE_WEB_DAV_CONFIG -> {
title_bar.title = getString(R.string.backup_restore) binding.titleBar.title = getString(R.string.backup_restore)
val fTag = "backupConfigFragment" val fTag = "backupConfigFragment"
var configFragment = supportFragmentManager.findFragmentByTag(fTag) var configFragment = supportFragmentManager.findFragmentByTag(fTag)
if (configFragment == null) configFragment = BackupConfigFragment() if (configFragment == null) configFragment = BackupConfigFragment()

@ -5,7 +5,6 @@ import android.os.Build
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity
import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
@ -116,7 +115,7 @@ object FilePicker {
} }
fun selectFile( fun selectFile(
activity: BaseActivity, activity: AppCompatActivity,
requestCode: Int, requestCode: Int,
title: String = activity.getString(R.string.select_file), title: String = activity.getString(R.string.select_file),
allowExtensions: Array<String> = arrayOf(), allowExtensions: Array<String> = arrayOf(),

@ -10,12 +10,12 @@ import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.databinding.ActivitySourceLoginBinding
import io.legado.app.help.http.CookieStore import io.legado.app.help.http.CookieStore
import io.legado.app.utils.snackbar import io.legado.app.utils.snackbar
import kotlinx.android.synthetic.main.activity_source_login.*
class SourceLogin : BaseActivity(R.layout.activity_source_login) { class SourceLogin : BaseActivity<ActivitySourceLoginBinding>() {
var sourceUrl: String? = null var sourceUrl: String? = null
var loginUrl: String? = null var loginUrl: String? = null
@ -30,12 +30,12 @@ class SourceLogin : BaseActivity(R.layout.activity_source_login) {
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
private fun initWebView() { private fun initWebView() {
val settings = web_view.settings val settings = binding.webView.settings
settings.setSupportZoom(true) settings.setSupportZoom(true)
settings.builtInZoomControls = true settings.builtInZoomControls = true
settings.javaScriptEnabled = true settings.javaScriptEnabled = true
val cookieManager = CookieManager.getInstance() val cookieManager = CookieManager.getInstance()
web_view.webViewClient = object : WebViewClient() { binding.webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
val cookie = cookieManager.getCookie(url) val cookie = cookieManager.getCookie(url)
sourceUrl?.let { sourceUrl?.let {
@ -56,7 +56,7 @@ class SourceLogin : BaseActivity(R.layout.activity_source_login) {
} }
} }
loginUrl?.let { loginUrl?.let {
web_view.loadUrl(it) binding.webView.loadUrl(it)
} }
} }
@ -70,9 +70,9 @@ class SourceLogin : BaseActivity(R.layout.activity_source_login) {
R.id.menu_success -> { R.id.menu_success -> {
if (!checking) { if (!checking) {
checking = true checking = true
title_bar.snackbar(R.string.check_host_cookie) binding.titleBar.snackbar(R.string.check_host_cookie)
loginUrl?.let { loginUrl?.let {
web_view.loadUrl(it) binding.webView.loadUrl(it)
} }
} }
} }
@ -82,6 +82,6 @@ class SourceLogin : BaseActivity(R.layout.activity_source_login) {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
web_view.destroy() binding.webView.destroy()
} }
} }

@ -15,6 +15,7 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.databinding.ActivityMainBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.help.DefaultData import io.legado.app.help.DefaultData
@ -31,11 +32,10 @@ import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.hideSoftInput import io.legado.app.utils.hideSoftInput
import io.legado.app.utils.observeEvent import io.legado.app.utils.observeEvent
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main), class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
BottomNavigationView.OnNavigationItemSelectedListener, BottomNavigationView.OnNavigationItemSelectedListener,
BottomNavigationView.OnNavigationItemReselectedListener, BottomNavigationView.OnNavigationItemReselectedListener,
ViewPager.OnPageChangeListener by ViewPager.SimpleOnPageChangeListener() { ViewPager.OnPageChangeListener by ViewPager.SimpleOnPageChangeListener() {
@ -47,17 +47,21 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
private var pagePosition = 0 private var pagePosition = 0
private val fragmentMap = hashMapOf<Int, Fragment>() private val fragmentMap = hashMapOf<Int, Fragment>()
override fun getViewBinding(): ActivityMainBinding {
return ActivityMainBinding.inflate(layoutInflater)
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
ATH.applyEdgeEffectColor(view_pager_main) ATH.applyEdgeEffectColor(binding.viewPagerMain)
ATH.applyBottomNavigationColor(bottom_navigation_view) ATH.applyBottomNavigationColor(binding.bottomNavigationView)
view_pager_main.offscreenPageLimit = 3 binding.viewPagerMain.offscreenPageLimit = 3
view_pager_main.adapter = TabFragmentPageAdapter(supportFragmentManager) binding.viewPagerMain.adapter = TabFragmentPageAdapter(supportFragmentManager)
view_pager_main.addOnPageChangeListener(this) binding.viewPagerMain.addOnPageChangeListener(this)
bottom_navigation_view.elevation = binding.bottomNavigationView.elevation =
if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat() if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat()
bottom_navigation_view.setOnNavigationItemSelectedListener(this) binding.bottomNavigationView.setOnNavigationItemSelectedListener(this)
bottom_navigation_view.setOnNavigationItemReselectedListener(this) binding.bottomNavigationView.setOnNavigationItemReselectedListener(this)
bottom_navigation_view.menu.findItem(R.id.menu_rss).isVisible = AppConfig.isShowRSS binding.bottomNavigationView.menu.findItem(R.id.menu_rss).isVisible = AppConfig.isShowRSS
} }
override fun onPostCreate(savedInstanceState: Bundle?) { override fun onPostCreate(savedInstanceState: Bundle?) {
@ -65,21 +69,21 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
upVersion() upVersion()
//自动更新书籍 //自动更新书籍
if (AppConfig.autoRefreshBook) { if (AppConfig.autoRefreshBook) {
view_pager_main.postDelayed({ binding.viewPagerMain.postDelayed({
viewModel.upAllBookToc() viewModel.upAllBookToc()
}, 1000) }, 1000)
} }
view_pager_main.postDelayed({ binding.viewPagerMain.postDelayed({
viewModel.postLoad() viewModel.postLoad()
}, 3000) }, 3000)
} }
override fun onNavigationItemSelected(item: MenuItem): Boolean { override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.menu_bookshelf -> view_pager_main.setCurrentItem(0, false) R.id.menu_bookshelf -> binding.viewPagerMain.setCurrentItem(0, false)
R.id.menu_explore -> view_pager_main.setCurrentItem(1, false) R.id.menu_explore -> binding.viewPagerMain.setCurrentItem(1, false)
R.id.menu_rss -> view_pager_main.setCurrentItem(2, false) R.id.menu_rss -> binding.viewPagerMain.setCurrentItem(2, false)
R.id.menu_my_config -> view_pager_main.setCurrentItem(3, false) R.id.menu_my_config -> binding.viewPagerMain.setCurrentItem(3, false)
} }
return false return false
} }
@ -119,14 +123,14 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
} }
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
view_pager_main.hideSoftInput() binding.viewPagerMain.hideSoftInput()
pagePosition = position pagePosition = position
when (position) { when (position) {
0, 1, 3 -> bottom_navigation_view.menu.getItem(position).isChecked = true 0, 1, 3 -> binding.bottomNavigationView.menu.getItem(position).isChecked = true
2 -> if (AppConfig.isShowRSS) { 2 -> if (AppConfig.isShowRSS) {
bottom_navigation_view.menu.getItem(position).isChecked = true binding.bottomNavigationView.menu.getItem(position).isChecked = true
} else { } else {
bottom_navigation_view.menu.getItem(3).isChecked = true binding.bottomNavigationView.menu.getItem(3).isChecked = true
} }
} }
} }
@ -136,7 +140,7 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
when (keyCode) { when (keyCode) {
KeyEvent.KEYCODE_BACK -> if (event.isTracking && !event.isCanceled) { KeyEvent.KEYCODE_BACK -> if (event.isTracking && !event.isCanceled) {
if (pagePosition != 0) { if (pagePosition != 0) {
view_pager_main.currentItem = 0 binding.viewPagerMain.currentItem = 0
return true return true
} }
if (System.currentTimeMillis() - exitTime > 2000) { if (System.currentTimeMillis() - exitTime > 2000) {
@ -173,10 +177,11 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
recreate() recreate()
} }
observeEvent<String>(EventBus.SHOW_RSS) { observeEvent<String>(EventBus.SHOW_RSS) {
bottom_navigation_view.menu.findItem(R.id.menu_rss).isVisible = AppConfig.isShowRSS binding.bottomNavigationView.menu.findItem(R.id.menu_rss).isVisible =
view_pager_main.adapter?.notifyDataSetChanged() AppConfig.isShowRSS
binding.viewPagerMain.adapter?.notifyDataSetChanged()
if (AppConfig.isShowRSS) { if (AppConfig.isShowRSS) {
view_pager_main.setCurrentItem(3, false) binding.viewPagerMain.setCurrentItem(3, false)
} }
} }
observeEvent<String>(PreferKey.threadCount) { observeEvent<String>(PreferKey.threadCount) {

@ -208,7 +208,7 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
private inner class TabFragmentPageAdapter(fm: FragmentManager) : private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
return bookGroups[position].groupName return bookGroups[position].groupName
} }

@ -7,8 +7,8 @@ import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.databinding.ItemRssBinding
import io.legado.app.help.ImageLoader import io.legado.app.help.ImageLoader
import kotlinx.android.synthetic.main.item_rss.view.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.sdk27.listeners.onLongClick import org.jetbrains.anko.sdk27.listeners.onLongClick
@ -16,29 +16,31 @@ class RssAdapter(context: Context, val callBack: CallBack) :
SimpleRecyclerAdapter<RssSource>(context, R.layout.item_rss) { SimpleRecyclerAdapter<RssSource>(context, R.layout.item_rss) {
override fun convert(holder: ItemViewHolder, item: RssSource, payloads: MutableList<Any>) { override fun convert(holder: ItemViewHolder, item: RssSource, payloads: MutableList<Any>) {
with(holder.itemView) { ItemRssBinding.bind(holder.itemView).apply {
tv_name.text = item.sourceName tvName.text = item.sourceName
ImageLoader.load(context, item.sourceIcon) ImageLoader.load(context, item.sourceIcon)
.centerCrop() .centerCrop()
.placeholder(R.drawable.image_rss) .placeholder(R.drawable.image_rss)
.error(R.drawable.image_rss) .error(R.drawable.image_rss)
.into(iv_icon) .into(ivIcon)
} }
} }
override fun registerListener(holder: ItemViewHolder) { override fun registerListener(holder: ItemViewHolder) {
holder.itemView.onClick { ItemRssBinding.bind(holder.itemView).apply {
root.onClick {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
callBack.openRss(it) callBack.openRss(it)
} }
} }
holder.itemView.onLongClick { root.onLongClick {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
showMenu(holder.itemView.iv_icon, it) showMenu(ivIcon, it)
} }
true true
} }
} }
}
private fun showMenu(view: View, rssSource: RssSource) { private fun showMenu(view: View, rssSource: RssSource) {
val popupMenu = PopupMenu(context, view) val popupMenu = PopupMenu(context, view)

@ -10,28 +10,26 @@ import android.view.View
import cn.bingoogolapple.qrcode.core.QRCodeView import cn.bingoogolapple.qrcode.core.QRCodeView
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.databinding.ActivityQrcodeCaptureBinding
import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.Permissions
import io.legado.app.help.permission.PermissionsCompat import io.legado.app.help.permission.PermissionsCompat
import io.legado.app.utils.readBytes import io.legado.app.utils.readBytes
import kotlinx.android.synthetic.main.activity_qrcode_capture.*
import kotlinx.android.synthetic.main.view_title_bar.*
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class QrCodeActivity : BaseActivity(R.layout.activity_qrcode_capture), QRCodeView.Delegate { class QrCodeActivity : BaseActivity<ActivityQrcodeCaptureBinding>(), QRCodeView.Delegate {
private val requestQrImage = 202 private val requestQrImage = 202
private var flashlightIsOpen: Boolean = false private var flashlightIsOpen: Boolean = false
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
setSupportActionBar(toolbar) binding.zXingView.setDelegate(this)
zxingview.setDelegate(this) binding.fabFlashlight.setOnClickListener {
fab_flashlight.setOnClickListener {
if (flashlightIsOpen) { if (flashlightIsOpen) {
flashlightIsOpen = false flashlightIsOpen = false
zxingview.closeFlashlight() binding.zXingView.closeFlashlight()
} else { } else {
flashlightIsOpen = true flashlightIsOpen = true
zxingview.openFlashlight() binding.zXingView.openFlashlight()
} }
} }
} }
@ -63,21 +61,21 @@ class QrCodeActivity : BaseActivity(R.layout.activity_qrcode_capture), QRCodeVie
.addPermissions(*Permissions.Group.CAMERA) .addPermissions(*Permissions.Group.CAMERA)
.rationale(R.string.qr_per) .rationale(R.string.qr_per)
.onGranted { .onGranted {
zxingview.visibility = View.VISIBLE binding.zXingView.visibility = View.VISIBLE
//TODO 显示扫描框,并开始识别 //TODO 显示扫描框,并开始识别
zxingview.startSpotAndShowRect() binding.zXingView.startSpotAndShowRect()
}.request() }.request()
} }
override fun onStop() { override fun onStop() {
//TODO 关闭摄像头预览,并且隐藏扫描框 //TODO 关闭摄像头预览,并且隐藏扫描框
zxingview.stopCamera() binding.zXingView.stopCamera()
super.onStop() super.onStop()
} }
override fun onDestroy() { override fun onDestroy() {
//TODO 销毁二维码扫描控件 //TODO 销毁二维码扫描控件
zxingview.onDestroy() binding.zXingView.onDestroy()
super.onDestroy() super.onDestroy()
} }
@ -100,13 +98,13 @@ class QrCodeActivity : BaseActivity(R.layout.activity_qrcode_capture), QRCodeVie
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
data?.data?.let { data?.data?.let {
//TODO 显示扫描框,并开始识别 //TODO 显示扫描框,并开始识别
zxingview.startSpotAndShowRect() binding.zXingView.startSpotAndShowRect()
if (resultCode == Activity.RESULT_OK && requestCode == requestQrImage) { if (resultCode == Activity.RESULT_OK && requestCode == requestQrImage) {
// 本来就用到 QRCodeView 时可直接调 QRCodeView 的方法,走通用的回调 // 本来就用到 QRCodeView 时可直接调 QRCodeView 的方法,走通用的回调
it.readBytes(this)?.let { bytes -> it.readBytes(this)?.let { bytes ->
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
zxingview.decodeQRCode(bitmap) binding.zXingView.decodeQRCode(bitmap)
} }
} }
} }

@ -19,6 +19,7 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.data.entities.ReplaceRule import io.legado.app.data.entities.ReplaceRule
import io.legado.app.databinding.ActivityReplaceRuleBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
@ -35,9 +36,6 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_replace_rule.*
import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import java.io.File import java.io.File
@ -45,8 +43,7 @@ import java.io.File
/** /**
* 替换规则管理 * 替换规则管理
*/ */
class ReplaceRuleActivity : class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRuleViewModel>(),
VMBaseActivity<ReplaceRuleViewModel>(R.layout.activity_replace_rule),
SearchView.OnQueryTextListener, SearchView.OnQueryTextListener,
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
@ -83,29 +80,31 @@ class ReplaceRuleActivity :
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = ReplaceRuleAdapter(this, this) adapter = ReplaceRuleAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
val itemTouchCallback = ItemTouchCallback(adapter) val itemTouchCallback = ItemTouchCallback(adapter)
itemTouchCallback.isCanDrag = true itemTouchCallback.isCanDrag = true
val dragSelectTouchHelper: DragSelectTouchHelper = val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50) DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view) dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
// When this page is opened, it is in selection mode // When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect() dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it. // Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view) ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
} }
private fun initSearchView() { private fun initSearchView() {
ATH.setTint(search_view, primaryTextColor) binding.titleBar.findViewById<SearchView>(R.id.search_view).let {
search_view.onActionViewExpanded() ATH.setTint(it, primaryTextColor)
search_view.queryHint = getString(R.string.replace_purify_search) it.onActionViewExpanded()
search_view.clearFocus() it.queryHint = getString(R.string.replace_purify_search)
search_view.setOnQueryTextListener(this) it.clearFocus()
it.setOnQueryTextListener(this)
}
} }
override fun selectAll(selectAll: Boolean) { override fun selectAll(selectAll: Boolean) {
@ -125,10 +124,10 @@ class ReplaceRuleActivity :
} }
private fun initSelectActionView() { private fun initSelectActionView() {
select_action_bar.setMainActionText(R.string.delete) binding.selectActionBar.setMainActionText(R.string.delete)
select_action_bar.inflateMenu(R.menu.replace_rule_sel) binding.selectActionBar.inflateMenu(R.menu.replace_rule_sel)
select_action_bar.setOnMenuItemClickListener(this) binding.selectActionBar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this) binding.selectActionBar.setCallBack(this)
} }
private fun delSourceDialog() { private fun delSourceDialog() {
@ -180,7 +179,8 @@ class ReplaceRuleActivity :
R.id.menu_import_source_local -> FilePicker R.id.menu_import_source_local -> FilePicker
.selectFile(this, importRequestCode, allowExtensions = arrayOf("txt", "json")) .selectFile(this, importRequestCode, allowExtensions = arrayOf("txt", "json"))
else -> if (item.groupId == R.id.replace_group) { else -> if (item.groupId == R.id.replace_group) {
search_view.setQuery(item.title, true) binding.titleBar.findViewById<SearchView>(R.id.search_view)
.setQuery(item.title, true)
} }
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
@ -213,9 +213,9 @@ class ReplaceRuleActivity :
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setFilterValues(cacheUrls) editText?.setFilterValues(cacheUrls)
edit_view.delCallBack = { editText?.delCallBack = {
cacheUrls.remove(it) cacheUrls.remove(it)
aCache.put(importRecordKey, cacheUrls.joinToString(",")) aCache.put(importRecordKey, cacheUrls.joinToString(","))
} }
@ -281,7 +281,10 @@ class ReplaceRuleActivity :
} }
override fun upCountView() { override fun upCountView() {
select_action_bar.upCountView(adapter.getSelection().size, adapter.getActualItemCount()) binding.selectActionBar.upCountView(
adapter.getSelection().size,
adapter.getActualItemCount()
)
} }
override fun update(vararg rule: ReplaceRule) { override fun update(vararg rule: ReplaceRule) {

@ -15,13 +15,13 @@ import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.entities.ReplaceRule import io.legado.app.data.entities.ReplaceRule
import io.legado.app.databinding.ActivityReplaceEditBinding
import io.legado.app.ui.widget.KeyboardToolPop import io.legado.app.ui.widget.KeyboardToolPop
import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import kotlinx.android.synthetic.main.activity_replace_edit.* import kotlinx.android.synthetic.main.activity_replace_edit.*
import org.jetbrains.anko.displayMetrics import org.jetbrains.anko.displayMetrics
import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.selector import org.jetbrains.anko.selector
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
import kotlin.math.abs import kotlin.math.abs
@ -30,7 +30,7 @@ import kotlin.math.abs
* 编辑替换规则 * 编辑替换规则
*/ */
class ReplaceEditActivity : class ReplaceEditActivity :
VMBaseActivity<ReplaceEditViewModel>(R.layout.activity_replace_edit, false), VMBaseActivity<ActivityReplaceEditBinding, ReplaceEditViewModel>(false),
ViewTreeObserver.OnGlobalLayoutListener, ViewTreeObserver.OnGlobalLayoutListener,
KeyboardToolPop.CallBack { KeyboardToolPop.CallBack {
@ -58,6 +58,10 @@ class ReplaceEditActivity :
private var mSoftKeyboardTool: PopupWindow? = null private var mSoftKeyboardTool: PopupWindow? = null
private var mIsSoftKeyBoardShowing = false private var mIsSoftKeyBoardShowing = false
override fun getViewBinding(): ActivityReplaceEditBinding {
return ActivityReplaceEditBinding.inflate(layoutInflater)
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this) mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this)
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this) window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this)

@ -10,14 +10,14 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivityRssArtivlesBinding
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.gone import io.legado.app.utils.gone
import io.legado.app.utils.visible import io.legado.app.utils.visible
import kotlinx.android.synthetic.main.activity_rss_artivles.*
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_artivles) { class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewModel>() {
override val viewModel: RssSortViewModel override val viewModel: RssSortViewModel
get() = getViewModel(RssSortViewModel::class.java) get() = getViewModel(RssSortViewModel::class.java)
@ -27,10 +27,10 @@ class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_a
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
adapter = TabFragmentPageAdapter(supportFragmentManager) adapter = TabFragmentPageAdapter(supportFragmentManager)
tab_layout.setupWithViewPager(view_pager) binding.tabLayout.setupWithViewPager(binding.viewPager)
view_pager.adapter = adapter binding.viewPager.adapter = adapter
viewModel.titleLiveData.observe(this, { viewModel.titleLiveData.observe(this, {
title_bar.title = it binding.titleBar.title = it
}) })
viewModel.initData(intent) { viewModel.initData(intent) {
upFragments() upFragments()
@ -66,9 +66,9 @@ class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_a
fragments[it.key] = RssArticlesFragment.create(it.key, it.value) fragments[it.key] = RssArticlesFragment.create(it.key, it.value)
} }
if (fragments.size == 1) { if (fragments.size == 1) {
tab_layout.gone() binding.tabLayout.gone()
} else { } else {
tab_layout.visible() binding.tabLayout.visible()
} }
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
} }
@ -91,7 +91,7 @@ class RssSortActivity : VMBaseActivity<RssSortViewModel>(R.layout.activity_rss_a
return POSITION_NONE return POSITION_NONE
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
return fragments.keys.elementAt(position) return fragments.keys.elementAt(position)
} }

@ -4,17 +4,15 @@ import android.os.Bundle
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App import io.legado.app.App
import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.data.entities.RssStar import io.legado.app.data.entities.RssStar
import io.legado.app.lib.theme.ATH import io.legado.app.databinding.ActivityRssFavoritesBinding
import io.legado.app.ui.rss.read.ReadRssActivity import io.legado.app.ui.rss.read.ReadRssActivity
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import kotlinx.android.synthetic.main.view_refresh_recycler.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
class RssFavoritesActivity : BaseActivity(R.layout.activity_rss_favorites), class RssFavoritesActivity : BaseActivity<ActivityRssFavoritesBinding>(),
RssFavoritesAdapter.CallBack { RssFavoritesAdapter.CallBack {
private var liveData: LiveData<List<RssStar>>? = null private var liveData: LiveData<List<RssStar>>? = null
@ -26,11 +24,12 @@ class RssFavoritesActivity : BaseActivity(R.layout.activity_rss_favorites),
} }
private fun initView() { private fun initView() {
ATH.applyEdgeEffectColor(recycler_view) binding.refreshRecyclerView.recyclerView.let {
recycler_view.layoutManager = LinearLayoutManager(this) it.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this)) it.addItemDecoration(VerticalDivider(this))
adapter = RssFavoritesAdapter(this, this) adapter = RssFavoritesAdapter(this, this)
recycler_view.adapter = adapter it.adapter = adapter
}
} }
private fun initData() { private fun initData() {

@ -13,6 +13,7 @@ import android.webkit.*
import androidx.core.view.size import androidx.core.view.size
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivityRssReadBinding
import io.legado.app.lib.theme.DrawableUtils import io.legado.app.lib.theme.DrawableUtils
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.service.help.Download import io.legado.app.service.help.Download
@ -22,7 +23,6 @@ import io.legado.app.ui.association.ImportRssSourceActivity
import io.legado.app.ui.filepicker.FilePicker import io.legado.app.ui.filepicker.FilePicker
import io.legado.app.ui.filepicker.FilePickerDialog import io.legado.app.ui.filepicker.FilePickerDialog
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_rss_read.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils import org.apache.commons.text.StringEscapeUtils
import org.jetbrains.anko.downloadManager import org.jetbrains.anko.downloadManager
@ -30,7 +30,7 @@ import org.jetbrains.anko.share
import org.jsoup.Jsoup import org.jsoup.Jsoup
class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_read, false), class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>(false),
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
ReadRssViewModel.CallBack { ReadRssViewModel.CallBack {
@ -45,7 +45,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.callBack = this viewModel.callBack = this
title_bar.title = intent.getStringExtra("title") binding.titleBar.title = intent.getStringExtra("title")
initWebView() initWebView()
initLiveData() initLiveData()
viewModel.initData(intent) viewModel.initData(intent)
@ -91,21 +91,21 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
} }
private fun initWebView() { private fun initWebView() {
web_view.webChromeClient = object : WebChromeClient() { binding.webView.webChromeClient = object : WebChromeClient() {
override fun onShowCustomView(view: View?, callback: CustomViewCallback?) { override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
ll_view.invisible() binding.llView.invisible()
custom_web_view.addView(view) binding.customWebView.addView(view)
customWebViewCallback = callback customWebViewCallback = callback
} }
override fun onHideCustomView() { override fun onHideCustomView() {
custom_web_view.removeAllViews() binding.customWebView.removeAllViews()
ll_view.visible() binding.llView.visible()
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
} }
} }
web_view.webViewClient = object : WebViewClient() { binding.webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading( override fun shouldOverrideUrlLoading(
view: WebView?, view: WebView?,
request: WebResourceRequest? request: WebResourceRequest?
@ -158,13 +158,13 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
return true return true
} }
} }
web_view.settings.apply { binding.webView.settings.apply {
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
domStorageEnabled = true domStorageEnabled = true
allowContentAccess = true allowContentAccess = true
} }
web_view.setOnLongClickListener { binding.webView.setOnLongClickListener {
val hitTestResult = web_view.hitTestResult val hitTestResult = binding.webView.hitTestResult
if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE
) { ) {
@ -176,9 +176,9 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
} }
return@setOnLongClickListener false return@setOnLongClickListener false
} }
web_view.setDownloadListener { url, _, contentDisposition, _, _ -> binding.webView.setDownloadListener { url, _, contentDisposition, _, _ ->
val fileName = URLUtil.guessFileName(url, contentDisposition, null) val fileName = URLUtil.guessFileName(url, contentDisposition, null)
ll_view.longSnackbar(fileName, getString(R.string.action_download)) { binding.llView.longSnackbar(fileName, getString(R.string.action_download)) {
// 指定下载地址 // 指定下载地址
val request = DownloadManager.Request(Uri.parse(url)) val request = DownloadManager.Request(Uri.parse(url))
// 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库 // 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库
@ -229,7 +229,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
val url = NetworkUtils.getAbsoluteURL(it.origin, it.link) val url = NetworkUtils.getAbsoluteURL(it.origin, it.link)
val html = viewModel.clHtml(content) val html = viewModel.clHtml(content)
if (viewModel.rssSource?.loadWithBaseUrl == true) { if (viewModel.rssSource?.loadWithBaseUrl == true) {
web_view.loadDataWithBaseURL( binding.webView.loadDataWithBaseURL(
url, url,
html, html,
"text/html", "text/html",
@ -237,7 +237,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
url url
)//不想用baseUrl进else )//不想用baseUrl进else
} else { } else {
web_view.loadDataWithBaseURL( binding.webView.loadDataWithBaseURL(
null, null,
html, html,
"text/html;charset=utf-8", "text/html;charset=utf-8",
@ -249,14 +249,14 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
}) })
viewModel.urlLiveData.observe(this, { viewModel.urlLiveData.observe(this, {
upJavaScriptEnable() upJavaScriptEnable()
web_view.loadUrl(it.url, it.headerMap) binding.webView.loadUrl(it.url, it.headerMap)
}) })
} }
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
private fun upJavaScriptEnable() { private fun upJavaScriptEnable() {
if (viewModel.rssSource?.enableJs == true) { if (viewModel.rssSource?.enableJs == true) {
web_view.settings.javaScriptEnabled = true binding.webView.settings.javaScriptEnabled = true
} }
} }
@ -297,12 +297,12 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
event?.let { event?.let {
when (keyCode) { when (keyCode) {
KeyEvent.KEYCODE_BACK -> if (event.isTracking && !event.isCanceled && web_view.canGoBack()) { KeyEvent.KEYCODE_BACK -> if (event.isTracking && !event.isCanceled && binding.webView.canGoBack()) {
if (custom_web_view.size > 0) { if (binding.customWebView.size > 0) {
customWebViewCallback?.onCustomViewHidden() customWebViewCallback?.onCustomViewHidden()
return true return true
} else if (web_view.copyBackForwardList().size > 1) { } else if (binding.webView.copyBackForwardList().size > 1) {
web_view.goBack() binding.webView.goBack()
return true return true
} }
} }
@ -317,8 +317,8 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
viewModel.textToSpeech?.stop() viewModel.textToSpeech?.stop()
upTtsMenu(false) upTtsMenu(false)
} else { } else {
web_view.settings.javaScriptEnabled = true binding.webView.settings.javaScriptEnabled = true
web_view.evaluateJavascript("document.documentElement.outerHTML") { binding.webView.evaluateJavascript("document.documentElement.outerHTML") {
val html = StringEscapeUtils.unescapeJson(it) val html = StringEscapeUtils.unescapeJson(it)
.replace("^\"|\"$".toRegex(), "") .replace("^\"|\"$".toRegex(), "")
Jsoup.parse(html).text() Jsoup.parse(html).text()
@ -339,7 +339,7 @@ class ReadRssActivity : VMBaseActivity<ReadRssViewModel>(R.layout.activity_rss_r
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
web_view.destroy() binding.webView.destroy()
} }
} }

@ -1,19 +1,17 @@
package io.legado.app.ui.rss.source.debug package io.legado.app.ui.rss.source.debug
import android.os.Bundle import android.os.Bundle
import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.databinding.ActivitySourceDebugBinding
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.gone import io.legado.app.utils.gone
import kotlinx.android.synthetic.main.activity_source_debug.*
import kotlinx.android.synthetic.main.view_search.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class RssSourceDebugActivity : VMBaseActivity<RssSourceDebugModel>(R.layout.activity_source_debug) { class RssSourceDebugActivity : VMBaseActivity<ActivitySourceDebugBinding, RssSourceDebugModel>() {
override val viewModel: RssSourceDebugModel override val viewModel: RssSourceDebugModel
get() = getViewModel(RssSourceDebugModel::class.java) get() = getViewModel(RssSourceDebugModel::class.java)
@ -27,7 +25,7 @@ class RssSourceDebugActivity : VMBaseActivity<RssSourceDebugModel>(R.layout.acti
launch { launch {
adapter.addItem(msg) adapter.addItem(msg)
if (state == -1 || state == 1000) { if (state == -1 || state == 1000) {
rotate_loading.hide() binding.rotateLoading.hide()
} }
} }
} }
@ -37,20 +35,20 @@ class RssSourceDebugActivity : VMBaseActivity<RssSourceDebugModel>(R.layout.acti
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
adapter = RssSourceDebugAdapter(this) adapter = RssSourceDebugAdapter(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
rotate_loading.loadingColor = accentColor binding.rotateLoading.loadingColor = accentColor
} }
private fun initSearchView() { private fun initSearchView() {
search_view.gone() binding.recyclerView.gone()
} }
private fun startSearch() { private fun startSearch() {
adapter.clearItems() adapter.clearItems()
viewModel.startDebug({ viewModel.startDebug({
rotate_loading.show() binding.rotateLoading.show()
}, { }, {
toast("未获取到源") toast("未获取到源")
}) })

@ -15,6 +15,7 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.databinding.ActivityRssSourceEditBinding
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.qrcode.QrCodeActivity
@ -25,12 +26,11 @@ import io.legado.app.utils.GSON
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.sendToClip import io.legado.app.utils.sendToClip
import io.legado.app.utils.shareWithQr import io.legado.app.utils.shareWithQr
import kotlinx.android.synthetic.main.activity_rss_source_edit.*
import org.jetbrains.anko.* import org.jetbrains.anko.*
import kotlin.math.abs import kotlin.math.abs
class RssSourceEditActivity : class RssSourceEditActivity :
VMBaseActivity<RssSourceEditViewModel>(R.layout.activity_rss_source_edit, false), VMBaseActivity<ActivityRssSourceEditBinding, RssSourceEditViewModel>(false),
ViewTreeObserver.OnGlobalLayoutListener, ViewTreeObserver.OnGlobalLayoutListener,
KeyboardToolPop.CallBack { KeyboardToolPop.CallBack {
@ -43,7 +43,6 @@ class RssSourceEditActivity :
override val viewModel: RssSourceEditViewModel override val viewModel: RssSourceEditViewModel
get() = getViewModel(RssSourceEditViewModel::class.java) get() = getViewModel(RssSourceEditViewModel::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
initView() initView()
viewModel.initData(intent) { viewModel.initData(intent) {
@ -105,18 +104,18 @@ class RssSourceEditActivity :
} }
private fun initView() { private fun initView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this) mSoftKeyboardTool = KeyboardToolPop(this, AppConst.keyboardToolChars, this)
window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this) window.decorView.viewTreeObserver.addOnGlobalLayoutListener(this)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
} }
private fun upRecyclerView(rssSource: RssSource? = viewModel.rssSource) { private fun upRecyclerView(rssSource: RssSource? = viewModel.rssSource) {
rssSource?.let { rssSource?.let {
cb_is_enable.isChecked = rssSource.enabled binding.cbIsEnable.isChecked = rssSource.enabled
cb_enable_js.isChecked = rssSource.enableJs binding.cbEnableJs.isChecked = rssSource.enableJs
cb_enable_base_url.isChecked = rssSource.loadWithBaseUrl binding.cbEnableBaseUrl.isChecked = rssSource.loadWithBaseUrl
} }
sourceEntities.clear() sourceEntities.clear()
sourceEntities.apply { sourceEntities.apply {
@ -141,9 +140,9 @@ class RssSourceEditActivity :
private fun getRssSource(): RssSource { private fun getRssSource(): RssSource {
val source = viewModel.rssSource val source = viewModel.rssSource
source.enabled = cb_is_enable.isChecked source.enabled = binding.cbIsEnable.isChecked
source.enableJs = cb_enable_js.isChecked source.enableJs = binding.cbEnableJs.isChecked
source.loadWithBaseUrl = cb_enable_base_url.isChecked source.loadWithBaseUrl = binding.cbEnableBaseUrl.isChecked
sourceEntities.forEach { sourceEntities.forEach {
when (it.key) { when (it.key) {
"sourceName" -> source.sourceName = it.value ?: "" "sourceName" -> source.sourceName = it.value ?: ""
@ -222,7 +221,7 @@ class RssSourceEditActivity :
mSoftKeyboardTool?.let { mSoftKeyboardTool?.let {
if (it.isShowing) return if (it.isShowing) return
if (!isFinishing) { if (!isFinishing) {
it.showAtLocation(ll_content, Gravity.BOTTOM, 0, 0) it.showAtLocation(binding.root, Gravity.BOTTOM, 0, 0)
} }
} }
} }
@ -240,11 +239,11 @@ class RssSourceEditActivity :
val preShowing = mIsSoftKeyBoardShowing val preShowing = mIsSoftKeyBoardShowing
if (abs(keyboardHeight) > screenHeight / 5) { if (abs(keyboardHeight) > screenHeight / 5) {
mIsSoftKeyBoardShowing = true // 超过屏幕五分之一则表示弹出了输入法 mIsSoftKeyBoardShowing = true // 超过屏幕五分之一则表示弹出了输入法
recycler_view.setPadding(0, 0, 0, 100) binding.recyclerView.setPadding(0, 0, 0, 100)
showKeyboardTopPopupWindow() showKeyboardTopPopupWindow()
} else { } else {
mIsSoftKeyBoardShowing = false mIsSoftKeyBoardShowing = false
recycler_view.setPadding(0, 0, 0, 0) binding.recyclerView.setPadding(0, 0, 0, 0)
if (preShowing) { if (preShowing) {
closePopupWindow() closePopupWindow()
} }

@ -19,6 +19,7 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.databinding.ActivityRssSourceBinding
import io.legado.app.help.IntentDataHelp import io.legado.app.help.IntentDataHelp
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
@ -34,9 +35,6 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.ui.widget.text.AutoCompleteTextView import io.legado.app.ui.widget.text.AutoCompleteTextView
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_rss_source.*
import kotlinx.android.synthetic.main.dialog_edit_text.view.*
import kotlinx.android.synthetic.main.view_search.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
@ -45,7 +43,7 @@ import java.text.Collator
import java.util.* import java.util.*
class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_rss_source), class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceViewModel>(),
PopupMenu.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener,
FilePickerDialog.CallBack, FilePickerDialog.CallBack,
SelectActionBar.CallBack, SelectActionBar.CallBack,
@ -91,7 +89,8 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
R.id.menu_group_manage -> GroupManageDialog() R.id.menu_group_manage -> GroupManageDialog()
.show(supportFragmentManager, "rssGroupManage") .show(supportFragmentManager, "rssGroupManage")
else -> if (item.groupId == R.id.source_group) { else -> if (item.groupId == R.id.source_group) {
search_view.setQuery(item.title, true) binding.titleBar.findViewById<SearchView>(R.id.search_view)
.setQuery(item.title, true)
} }
} }
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
@ -110,29 +109,30 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(binding.recyclerView)
recycler_view.layoutManager = LinearLayoutManager(this) binding.recyclerView.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this)) binding.recyclerView.addItemDecoration(VerticalDivider(this))
adapter = RssSourceAdapter(this, this) adapter = RssSourceAdapter(this, this)
recycler_view.adapter = adapter binding.recyclerView.adapter = adapter
val itemTouchCallback = ItemTouchCallback(adapter) val itemTouchCallback = ItemTouchCallback(adapter)
itemTouchCallback.isCanDrag = true itemTouchCallback.isCanDrag = true
val dragSelectTouchHelper: DragSelectTouchHelper = val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50) DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view) dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
// When this page is opened, it is in selection mode // When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect() dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it. // Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view) ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
} }
private fun initSearchView() { private fun initSearchView() {
ATH.setTint(search_view, primaryTextColor) binding.titleBar.findViewById<SearchView>(R.id.search_view).let {
search_view.onActionViewExpanded() ATH.setTint(it, primaryTextColor)
search_view.queryHint = getString(R.string.search_rss_source) it.onActionViewExpanded()
search_view.clearFocus() it.queryHint = getString(R.string.search_rss_source)
search_view.setOnQueryTextListener(object : SearchView.OnQueryTextListener { it.clearFocus()
it.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean { override fun onQueryTextSubmit(query: String?): Boolean {
return false return false
} }
@ -143,6 +143,7 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} }
}) })
} }
}
private fun initLiveDataGroup() { private fun initLiveDataGroup() {
App.db.rssSourceDao().liveGroup().observe(this, { App.db.rssSourceDao().liveGroup().observe(this, {
@ -171,10 +172,10 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} }
private fun initViewEvent() { private fun initViewEvent() {
select_action_bar.setMainActionText(R.string.delete) binding.selectActionBar.setMainActionText(R.string.delete)
select_action_bar.inflateMenu(R.menu.rss_source_sel) binding.selectActionBar.inflateMenu(R.menu.rss_source_sel)
select_action_bar.setOnMenuItemClickListener(this) binding.selectActionBar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this) binding.selectActionBar.setCallBack(this)
} }
private fun delSourceDialog() { private fun delSourceDialog() {
@ -209,7 +210,10 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
} }
override fun upCountView() { override fun upCountView() {
select_action_bar.upCountView(adapter.getSelection().size, adapter.getActualItemCount()) binding.selectActionBar.upCountView(
adapter.getSelection().size,
adapter.getActualItemCount()
)
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
@ -223,9 +227,9 @@ class RssSourceActivity : VMBaseActivity<RssSourceViewModel>(R.layout.activity_r
var editText: AutoCompleteTextView? = null var editText: AutoCompleteTextView? = null
customView { customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = findViewById(R.id.edit_view)
edit_view.setFilterValues(cacheUrls) editText?.setFilterValues(cacheUrls)
edit_view.delCallBack = { editText?.delCallBack = {
cacheUrls.remove(it) cacheUrls.remove(it)
aCache.put(importRecordKey, cacheUrls.joinToString(",")) aCache.put(importRecordKey, cacheUrls.joinToString(","))
} }

@ -7,6 +7,7 @@ import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.databinding.ActivityWelcomeBinding
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.storage.SyncBookProgress import io.legado.app.help.storage.SyncBookProgress
@ -14,15 +15,14 @@ import io.legado.app.lib.theme.accentColor
import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.main.MainActivity import io.legado.app.ui.main.MainActivity
import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.getPrefBoolean
import kotlinx.android.synthetic.main.activity_welcome.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) { open class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
iv_book.setColorFilter(accentColor) binding.ivBook.setColorFilter(accentColor)
vw_title_line.setBackgroundColor(accentColor) binding.vwTitleLine.setBackgroundColor(accentColor)
// 避免从桌面启动程序后,会重新实例化入口类的activity // 避免从桌面启动程序后,会重新实例化入口类的activity
if (intent.flags and Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT != 0) { if (intent.flags and Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT != 0) {
finish() finish()
@ -47,7 +47,7 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) {
} }
} }
SyncBookProgress.downloadBookProgress() SyncBookProgress.downloadBookProgress()
root_view.postDelayed({ startMainActivity() }, 500) binding.root.postDelayed({ startMainActivity() }, 500)
} }
private fun startMainActivity() { private fun startMainActivity() {

@ -2,15 +2,15 @@ package io.legado.app.ui.widget
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.SeekBar import android.widget.SeekBar
import io.legado.app.R import io.legado.app.R
import io.legado.app.databinding.ViewDetailSeekBarBinding
import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.bottomBackground
import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.lib.theme.getPrimaryTextColor
import io.legado.app.utils.ColorUtils import io.legado.app.utils.ColorUtils
import io.legado.app.utils.progressAdd import io.legado.app.utils.progressAdd
import kotlinx.android.synthetic.main.view_detail_seek_bar.view.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
class DetailSeekBar @JvmOverloads constructor( class DetailSeekBar @JvmOverloads constructor(
@ -18,53 +18,54 @@ class DetailSeekBar @JvmOverloads constructor(
attrs: AttributeSet? = null attrs: AttributeSet? = null
) : FrameLayout(context, attrs), ) : FrameLayout(context, attrs),
SeekBar.OnSeekBarChangeListener { SeekBar.OnSeekBarChangeListener {
private var binding: ViewDetailSeekBarBinding =
ViewDetailSeekBarBinding.inflate(LayoutInflater.from(context), this, true)
private val isBottomBackground: Boolean private val isBottomBackground: Boolean
var valueFormat: ((progress: Int) -> String)? = null var valueFormat: ((progress: Int) -> String)? = null
var onChanged: ((progress: Int) -> Unit)? = null var onChanged: ((progress: Int) -> Unit)? = null
var progress: Int var progress: Int
get() = seek_bar.progress get() = binding.seekBar.progress
set(value) { set(value) {
seek_bar.progress = value binding.seekBar.progress = value
} }
var max: Int var max: Int
get() = seek_bar.max get() = binding.seekBar.max
set(value) { set(value) {
seek_bar.max = value binding.seekBar.max = value
} }
init { init {
View.inflate(context, R.layout.view_detail_seek_bar, this)
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar) val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar)
isBottomBackground = isBottomBackground =
typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false) typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false)
tv_seek_title.text = typedArray.getText(R.styleable.DetailSeekBar_title) binding.tvSeekTitle.text = typedArray.getText(R.styleable.DetailSeekBar_title)
seek_bar.max = typedArray.getInteger(R.styleable.DetailSeekBar_max, 0) binding.seekBar.max = typedArray.getInteger(R.styleable.DetailSeekBar_max, 0)
typedArray.recycle() typedArray.recycle()
if (isBottomBackground && !isInEditMode) { if (isBottomBackground && !isInEditMode) {
val isLight = ColorUtils.isColorLight(context.bottomBackground) val isLight = ColorUtils.isColorLight(context.bottomBackground)
val textColor = context.getPrimaryTextColor(isLight) val textColor = context.getPrimaryTextColor(isLight)
tv_seek_title.setTextColor(textColor) binding.tvSeekTitle.setTextColor(textColor)
iv_seek_plus.setColorFilter(textColor) binding.ivSeekPlus.setColorFilter(textColor)
iv_seek_reduce.setColorFilter(textColor) binding.ivSeekReduce.setColorFilter(textColor)
tv_seek_value.setTextColor(textColor) binding.tvSeekValue.setTextColor(textColor)
} }
iv_seek_plus.onClick { binding.ivSeekPlus.onClick {
seek_bar.progressAdd(1) binding.seekBar.progressAdd(1)
onChanged?.invoke(seek_bar.progress) onChanged?.invoke(binding.seekBar.progress)
} }
iv_seek_reduce.onClick { binding.ivSeekReduce.onClick {
seek_bar.progressAdd(-1) binding.seekBar.progressAdd(-1)
onChanged?.invoke(seek_bar.progress) onChanged?.invoke(binding.seekBar.progress)
} }
seek_bar.setOnSeekBarChangeListener(this) binding.seekBar.setOnSeekBarChangeListener(this)
} }
private fun upValue(progress: Int = seek_bar.progress) { private fun upValue(progress: Int = binding.seekBar.progress) {
valueFormat?.let { valueFormat?.let {
tv_seek_value.text = it.invoke(progress) binding.tvSeekValue.text = it.invoke(progress)
} ?: let { } ?: let {
tv_seek_value.text = progress.toString() binding.tvSeekValue.text = progress.toString()
} }
} }
@ -77,7 +78,7 @@ class DetailSeekBar @JvmOverloads constructor(
} }
override fun onStopTrackingTouch(seekBar: SeekBar?) { override fun onStopTrackingTouch(seekBar: SeekBar?) {
onChanged?.invoke(seek_bar.progress) onChanged?.invoke(binding.seekBar.progress)
} }
} }

@ -9,11 +9,13 @@ import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.R import io.legado.app.R
import kotlinx.android.synthetic.main.view_refresh_recycler.view.* import io.legado.app.databinding.ViewRefreshRecyclerBinding
import io.legado.app.lib.theme.ATH
@SuppressLint("ClickableViewAccessibility")
class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
private var binding: ViewRefreshRecyclerBinding
private var durTouchX = -1000000f private var durTouchX = -1000000f
private var durTouchY = -1000000f private var durTouchY = -1000000f
@ -21,8 +23,10 @@ class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayou
init { init {
orientation = VERTICAL orientation = VERTICAL
LayoutInflater.from(context).inflate(R.layout.view_refresh_recycler, this, true) val view = LayoutInflater.from(context).inflate(R.layout.view_refresh_recycler, this, true)
recycler_view.setOnTouchListener(object : OnTouchListener { binding = ViewRefreshRecyclerBinding.bind(view)
ATH.applyEdgeEffectColor(binding.recyclerView)
binding.recyclerView.setOnTouchListener(object : OnTouchListener {
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean { override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (event?.action) { when (event?.action) {
@ -39,26 +43,31 @@ class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayou
val dY = event.y - durTouchY //>0下拉 val dY = event.y - durTouchY //>0下拉
durTouchY = event.y durTouchY = event.y
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.getSecondDurProgress() == refresh_progress_bar.secondFinalProgress) { if (!binding.refreshProgressBar.isAutoLoading &&
recycler_view.adapter?.let { binding.refreshProgressBar.getSecondDurProgress() == binding.refreshProgressBar.secondFinalProgress
) {
binding.recyclerView.adapter?.let {
if (it.itemCount > 0) { if (it.itemCount > 0) {
if (0 == (recycler_view.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()) { if (0 == (binding.recyclerView.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()) {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt()) binding.refreshProgressBar.setSecondDurProgress((binding.refreshProgressBar.getSecondDurProgress() + dY / 2).toInt())
} }
} else { } else {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt()) binding.refreshProgressBar.setSecondDurProgress((binding.refreshProgressBar.getSecondDurProgress() + dY / 2).toInt())
} }
} }
return refresh_progress_bar.getSecondDurProgress() > 0 return binding.refreshProgressBar.getSecondDurProgress() > 0
} }
} }
MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> {
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.secondMaxProgress > 0 && refresh_progress_bar.getSecondDurProgress() > 0) { if (!binding.refreshProgressBar.isAutoLoading &&
if (refresh_progress_bar.getSecondDurProgress() >= refresh_progress_bar.secondMaxProgress) { binding.refreshProgressBar.secondMaxProgress > 0 &&
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.getSecondDurProgress() > 0
) {
if (binding.refreshProgressBar.getSecondDurProgress() >= binding.refreshProgressBar.secondMaxProgress) {
binding.refreshProgressBar.isAutoLoading = true
onRefreshStart?.invoke() onRefreshStart?.invoke()
} else { } else {
refresh_progress_bar.setSecondDurProgressWithAnim(0) binding.refreshProgressBar.setSecondDurProgressWithAnim(0)
} }
} }
durTouchX = -1000000f durTouchX = -1000000f
@ -70,12 +79,14 @@ class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayou
}) })
} }
val recyclerView get() = binding.recyclerView
fun startLoading() { fun startLoading() {
refresh_progress_bar.isAutoLoading = true binding.refreshProgressBar.isAutoLoading = true
onRefreshStart?.invoke() onRefreshStart?.invoke()
} }
fun stopLoading() { fun stopLoading() {
refresh_progress_bar.isAutoLoading = false binding.refreshProgressBar.isAutoLoading = false
} }
} }

@ -0,0 +1,58 @@
@file:Suppress("RedundantVisibilityModifier", "unused")
package io.legado.app.utils.viewbindingdelegate
import android.view.View
import androidx.annotation.IdRes
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
private class DialogFragmentViewBindingProperty<F : DialogFragment, T : ViewBinding>(
viewBinder: (F) -> T
) : ViewBindingProperty<F, T>(viewBinder) {
override fun getLifecycleOwner(thisRef: F): LifecycleOwner {
return if (thisRef.view == null) thisRef.viewLifecycleOwner else thisRef
}
}
/**
* Create new [ViewBinding] associated with the [DialogFragment]
*/
@JvmName("viewBindingDialogFragment")
public fun <F : DialogFragment, T : ViewBinding> DialogFragment.dialogViewBinding(
viewBinder: (F) -> T
): ViewBindingProperty<F, T> {
return DialogFragmentViewBindingProperty(viewBinder)
}
/**
* Create new [ViewBinding] associated with the [DialogFragment]
*
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used
*/
@JvmName("viewBindingDialogFragment")
public inline fun <F : DialogFragment, T : ViewBinding> DialogFragment.dialogViewBinding(
crossinline vbFactory: (View) -> T,
crossinline viewProvider: (F) -> View
): ViewBindingProperty<F, T> {
return dialogViewBinding { fragment -> vbFactory(viewProvider(fragment)) }
}
/**
* Create new [ViewBinding] associated with the [DialogFragment][this]
*
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used
* @param viewBindingRootId Id of the root view from your custom view
*/
@Suppress("unused")
@JvmName("viewBindingDialogFragment")
public inline fun <T : ViewBinding> DialogFragment.dialogViewBinding(
crossinline vbFactory: (View) -> T,
@IdRes viewBindingRootId: Int
): ViewBindingProperty<DialogFragment, T> {
return viewBinding(vbFactory) { fragment: DialogFragment ->
fragment.dialog!!.window!!.decorView.findViewById(viewBindingRootId)
}
}

@ -0,0 +1,54 @@
@file:Suppress("RedundantVisibilityModifier", "unused")
@file:JvmName("ReflectionFragmentViewBindings")
package io.legado.app.utils.viewbindingdelegate
import android.view.View
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
private class FragmentViewBindingProperty<F : Fragment, T : ViewBinding>(
viewBinder: (F) -> T
) : ViewBindingProperty<F, T>(viewBinder) {
override fun getLifecycleOwner(thisRef: F) = thisRef.viewLifecycleOwner
}
/**
* Create new [ViewBinding] associated with the [Fragment]
*/
@JvmName("viewBindingFragment")
public fun <F : Fragment, T : ViewBinding> Fragment.viewBinding(viewBinder: (F) -> T): ViewBindingProperty<F, T> {
return FragmentViewBindingProperty(viewBinder)
}
/**
* Create new [ViewBinding] associated with the [Fragment]
*
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used
* @param viewProvider Provide a [View] from the Fragment. By default call [Fragment.requireView]
*/
@JvmName("viewBindingFragment")
public inline fun <F : Fragment, T : ViewBinding> Fragment.viewBinding(
crossinline vbFactory: (View) -> T,
crossinline viewProvider: (F) -> View = Fragment::requireView
): ViewBindingProperty<F, T> {
return viewBinding { fragment: F -> vbFactory(viewProvider(fragment)) }
}
/**
* Create new [ViewBinding] associated with the [Fragment]
*
* @param vbFactory Function that create new instance of [ViewBinding]. `MyViewBinding::bind` can be used
* @param viewBindingRootId Root view's id that will be used as root for the view binding
*/
@JvmName("viewBindingFragment")
public inline fun <T : ViewBinding> Fragment.viewBinding(
crossinline vbFactory: (View) -> T,
@IdRes viewBindingRootId: Int
): ViewBindingProperty<Fragment, T> {
return viewBinding(vbFactory) { fragment: Fragment ->
fragment.requireView().findViewById(viewBindingRootId)
}
}

@ -0,0 +1,57 @@
@file:Suppress("RedundantVisibilityModifier")
package io.legado.app.utils.viewbindingdelegate
import android.os.Handler
import android.os.Looper
import androidx.annotation.MainThread
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
public abstract class ViewBindingProperty<in R : Any, T : ViewBinding>(
private val viewBinder: (R) -> T
) : ReadOnlyProperty<R, T> {
private var viewBinding: T? = null
private val lifecycleObserver = ClearOnDestroyLifecycleObserver()
private var thisRef: R? = null
protected abstract fun getLifecycleOwner(thisRef: R): LifecycleOwner
@MainThread
public override fun getValue(thisRef: R, property: KProperty<*>): T {
viewBinding?.let { return it }
this.thisRef = thisRef
val lifecycle = getLifecycleOwner(thisRef).lifecycle
if (lifecycle.currentState == Lifecycle.State.DESTROYED) {
mainHandler.post { viewBinding = null }
} else {
lifecycle.addObserver(lifecycleObserver)
}
return viewBinder(thisRef).also { viewBinding = it }
}
@MainThread
public fun clear() {
val thisRef = thisRef ?: return
this.thisRef = null
getLifecycleOwner(thisRef).lifecycle.removeObserver(lifecycleObserver)
mainHandler.post { viewBinding = null }
}
private inner class ClearOnDestroyLifecycleObserver : DefaultLifecycleObserver {
@MainThread
override fun onDestroy(owner: LifecycleOwner): Unit = clear()
}
private companion object {
private val mainHandler = Handler(Looper.getMainLooper())
}
}

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">

@ -2,7 +2,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">

@ -5,7 +5,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<cn.bingoogolapple.qrcode.zxing.ZXingView <cn.bingoogolapple.qrcode.zxing.ZXingView
android:id="@+id/zxingview" android:id="@+id/z_xing_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="gone" android:visibility="gone"

@ -17,7 +17,9 @@
android:paddingTop="10dp" android:paddingTop="10dp"
android:paddingBottom="10dp"> android:paddingBottom="10dp">
<include layout="@layout/item_read_record" /> <include
android:id="@+id/read_record"
layout="@layout/item_read_record" />
</FrameLayout> </FrameLayout>

@ -2,7 +2,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">

@ -2,7 +2,6 @@
<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"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_view"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.4.10' ext.kotlin_version = '1.4.20'
repositories { repositories {
google() google()
jcenter() jcenter()

Loading…
Cancel
Save