viewBinding

This commit is contained in:
gedoor 2020-12-01 14:00:41 +08:00
parent 3478f2210a
commit 6852689604
70 changed files with 1130 additions and 930 deletions

View File

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

View File

@ -5,11 +5,13 @@ import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import io.legado.app.App
import io.legado.app.R
import io.legado.app.constant.AppConst
@ -22,10 +24,10 @@ import io.legado.app.utils.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import java.lang.reflect.ParameterizedType
abstract class BaseActivity(
private val layoutID: Int,
abstract class BaseActivity<VB : ViewBinding>(
val fullScreen: Boolean = true,
private val theme: Theme = Theme.Auto,
private val toolBarTheme: Theme = Theme.Auto,
@ -33,6 +35,16 @@ abstract class BaseActivity(
) : AppCompatActivity(),
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
get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -63,7 +75,7 @@ abstract class BaseActivity(
initTheme()
setupSystemBar()
super.onCreate(savedInstanceState)
setContentView(layoutID)
setContentView(binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
findViewById<TitleBar>(R.id.title_bar)
?.onMultiWindowModeChanged(isInMultiWindowMode, fullScreen)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ import io.legado.app.constant.AppConst
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
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.theme.ATH
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.utils.getPrefInt
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,
SelectActionBar.CallBack,
ArrangeBookAdapter.CallBack,
@ -45,7 +45,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
override fun onActivityCreated(savedInstanceState: Bundle?) {
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()
initGroupData()
initBookData()
@ -75,24 +75,24 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
}
private fun initView() {
ATH.applyEdgeEffectColor(recycler_view)
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.addItemDecoration(VerticalDivider(this))
ATH.applyEdgeEffectColor(binding.recyclerView)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.addItemDecoration(VerticalDivider(this))
adapter = ArrangeBookAdapter(this, this)
recycler_view.adapter = adapter
binding.recyclerView.adapter = adapter
val itemTouchCallback = ItemTouchCallback(adapter)
itemTouchCallback.isCanDrag = getPrefInt(PreferKey.bookshelfSort) == 3
val dragSelectTouchHelper: DragSelectTouchHelper =
DragSelectTouchHelper(adapter.initDragSelectTouchHelperCallback()).setSlideArea(16, 50)
dragSelectTouchHelper.attachToRecyclerView(recycler_view)
dragSelectTouchHelper.attachToRecyclerView(binding.recyclerView)
// When this page is opened, it is in selection mode
dragSelectTouchHelper.activeSlideSelect()
// Note: need judge selection first, so add ItemTouchHelper after it.
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recycler_view)
select_action_bar.setMainActionText(R.string.move_to_group)
select_action_bar.inflateMenu(R.menu.arrange_book_sel)
select_action_bar.setOnMenuItemClickListener(this)
select_action_bar.setCallBack(this)
ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView)
binding.selectActionBar.setMainActionText(R.string.move_to_group)
binding.selectActionBar.inflateMenu(R.menu.arrange_book_sel)
binding.selectActionBar.setOnMenuItemClickListener(this)
binding.selectActionBar.setCallBack(this)
}
private fun initGroupData() {
@ -133,7 +133,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
R.id.menu_group_manage -> GroupManageDialog()
.show(supportFragmentManager, "groupManage")
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
initBookData()
}
@ -195,7 +195,7 @@ class ArrangeBookActivity : VMBaseActivity<ArrangeBookViewModel>(R.layout.activi
}
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) {

View File

@ -17,13 +17,13 @@ import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.ActivityCacheBookBinding
import io.legado.app.help.BookHelp
import io.legado.app.service.help.CacheBook
import io.legado.app.ui.filepicker.FilePicker
import io.legado.app.ui.filepicker.FilePickerDialog
import io.legado.app.ui.widget.dialog.TextListDialog
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_download.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
@ -32,7 +32,7 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download),
class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>(),
FilePickerDialog.CallBack,
CacheAdapter.CallBack {
private val exportRequestCode = 32
@ -50,7 +50,7 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
override fun onActivityCreated(savedInstanceState: Bundle?) {
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()
initGroupData()
initBookData()
@ -96,7 +96,7 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
TextListDialog.show(supportFragmentManager, getString(R.string.log), CacheBook.logs)
}
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
initBookData()
}
@ -105,9 +105,9 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
}
private fun initRecyclerView() {
recycler_view.layoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
adapter = CacheAdapter(this, this)
recycler_view.adapter = adapter
binding.recyclerView.adapter = adapter
}
private fun initBookData() {
@ -194,10 +194,10 @@ class CacheActivity : VMBaseActivity<CacheViewModel>(R.layout.activity_download)
private fun startExport(path: String) {
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()
viewModel.export(path, book) {
title_bar.snackbar(it)
binding.titleBar.snackbar(it)
}
}
}

View File

@ -5,16 +5,16 @@ import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter
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
class CoverAdapter(context: Context, val callBack: CallBack) :
SimpleRecyclerAdapter<SearchBook>(context, R.layout.item_cover) {
override fun convert(holder: ItemViewHolder, item: SearchBook, payloads: MutableList<Any>) {
with(holder.itemView) {
iv_cover.load(item.coverUrl, item.name, item.author)
tv_source.text = item.originName
ItemCoverBinding.bind(holder.itemView).apply {
ivCover.load(item.coverUrl, item.name, item.author)
tvSource.text = item.originName
}
}

View File

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

View File

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

View File

@ -10,17 +10,17 @@ import androidx.documentfile.provider.DocumentFile
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
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.PermissionsCompat
import io.legado.app.ui.book.changecover.ChangeCoverDialog
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.toast
import java.io.File
class BookInfoEditActivity :
VMBaseActivity<BookInfoEditViewModel>(R.layout.activity_book_info_edit),
VMBaseActivity<ActivityBookInfoEditBinding, BookInfoEditViewModel>(),
ChangeCoverDialog.CallBack {
private val resultSelectCover = 132
@ -51,41 +51,41 @@ class BookInfoEditActivity :
}
private fun initEvent() {
tv_change_cover.onClick {
binding.tvChangeCover.onClick {
viewModel.bookData.value?.let {
ChangeCoverDialog.show(supportFragmentManager, it.name, it.author)
}
}
tv_select_cover.onClick {
binding.tvSelectCover.onClick {
selectImage()
}
tv_refresh_cover.onClick {
viewModel.book?.customCoverUrl = tie_cover_url.text?.toString()
binding.tvRefreshCover.onClick {
viewModel.book?.customCoverUrl = binding.tieCoverUrl.text?.toString()
upCover()
}
}
private fun upView(book: Book) {
tie_book_name.setText(book.name)
tie_book_author.setText(book.author)
tie_cover_url.setText(book.getDisplayCover())
tie_book_intro.setText(book.getDisplayIntro())
binding.tieBookName.setText(book.name)
binding.tieBookAuthor.setText(book.author)
binding.tieCoverUrl.setText(book.getDisplayCover())
binding.tieBookIntro.setText(book.getDisplayIntro())
upCover()
}
private fun upCover() {
viewModel.book.let {
iv_cover.load(it?.getDisplayCover(), it?.name, it?.author)
binding.ivCover.load(it?.getDisplayCover(), it?.name, it?.author)
}
}
private fun saveData() {
viewModel.book?.let { book ->
book.name = tie_book_name.text?.toString() ?: ""
book.author = tie_book_author.text?.toString() ?: ""
val customCoverUrl = tie_cover_url.text?.toString()
book.name = binding.tieBookName.text?.toString() ?: ""
book.author = binding.tieBookAuthor.text?.toString() ?: ""
val customCoverUrl = binding.tieCoverUrl.text?.toString()
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) {
setResult(Activity.RESULT_OK)
finish()
@ -102,7 +102,7 @@ class BookInfoEditActivity :
override fun coverChangeTo(coverUrl: String) {
viewModel.book?.customCoverUrl = coverUrl
tie_cover_url.setText(coverUrl)
binding.tieCoverUrl.setText(coverUrl)
upCover()
}

View File

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

View File

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

View File

@ -1,11 +1,8 @@
package io.legado.app.ui.book.read
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.*
@ -16,6 +13,8 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.PreferKey
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.LocalConfig
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.ClickActionConfigDialog
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.utils.getPrefString
import io.legado.app.utils.getViewModel
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 :
VMBaseActivity<ReadBookViewModel>(R.layout.activity_book_read) {
VMBaseActivity<ActivityBookReadBinding, ReadBookViewModel>() {
override val viewModel: ReadBookViewModel
get() = getViewModel(ReadBookViewModel::class.java)
private val requestCodeEditSource = 111
var bottomDialog = 0
override fun onCreate(savedInstanceState: Bundle?) {
@ -62,43 +53,11 @@ abstract class ReadBookBaseActivity :
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
initView()
if (LocalConfig.isFirstRead) {
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() {
PaddingConfigDialog().show(supportFragmentManager, "paddingConfig")
}
@ -182,8 +141,7 @@ abstract class ReadBookBaseActivity :
override fun upNavigationBarColor() {
when {
read_menu == null -> return
read_menu.isVisible -> ATH.setNavigationBarColorAuto(this)
binding.readMenu.isVisible -> ATH.setNavigationBarColorAuto(this)
bottomDialog > 0 -> ATH.setNavigationBarColorAuto(this, bottomBackground)
else -> {
ATH.setNavigationBarColorAuto(this, Color.TRANSPARENT)
@ -218,23 +176,22 @@ abstract class ReadBookBaseActivity :
fun showDownloadDialog() {
ReadBook.book?.let { book ->
alert(titleResource = R.string.offline_cache) {
var view: View? = null
var dialogBinding: DialogDownloadChoiceBinding? = null
customView {
LayoutInflater.from(this@ReadBookBaseActivity)
.inflate(R.layout.dialog_download_choice, null)
.apply {
view = this
dialogBinding = DialogDownloadChoiceBinding.bind(this)
setBackgroundColor(context.backgroundColor)
edit_start.setText((book.durChapterIndex + 1).toString())
edit_end.setText(book.totalChapterNum.toString())
dialogBinding!!.editStart.setText((book.durChapterIndex + 1).toString())
dialogBinding!!.editEnd.setText(book.totalChapterNum.toString())
}
}
yesButton {
view?.apply {
val start = edit_start?.text?.toString()?.toInt() ?: 0
val end = edit_end?.text?.toString()?.toInt() ?: book.totalChapterNum
CacheBook.start(context, book.bookUrl, start - 1, end - 1)
}
val start = dialogBinding!!.editStart.text?.toString()?.toInt() ?: 0
val end =
dialogBinding!!.editEnd.text?.toString()?.toInt() ?: book.totalChapterNum
CacheBook.start(this@ReadBookBaseActivity, book.bookUrl, start - 1, end - 1)
}
noButton()
}.show()
@ -250,9 +207,8 @@ abstract class ReadBookBaseActivity :
message = book.name + "" + textChapter.title
customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view.apply {
setHint(R.string.note_content)
}
editText = findViewById(R.id.edit_view)
editText!!.setHint(R.string.note_content)
}
}
yesButton {
@ -282,9 +238,9 @@ abstract class ReadBookBaseActivity :
var editText: AutoCompleteTextView? = null
customView {
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view
edit_view.setFilterValues(charsets)
edit_view.setText(ReadBook.book?.charset)
editText = findViewById(R.id.edit_view)
editText?.setFilterValues(charsets)
editText?.setText(ReadBook.book?.charset)
}
}
okButton {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,8 +7,8 @@ import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.SimpleRecyclerAdapter
import io.legado.app.data.entities.RssSource
import io.legado.app.databinding.ItemRssBinding
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.onLongClick
@ -16,27 +16,29 @@ class RssAdapter(context: Context, val callBack: CallBack) :
SimpleRecyclerAdapter<RssSource>(context, R.layout.item_rss) {
override fun convert(holder: ItemViewHolder, item: RssSource, payloads: MutableList<Any>) {
with(holder.itemView) {
tv_name.text = item.sourceName
ItemRssBinding.bind(holder.itemView).apply {
tvName.text = item.sourceName
ImageLoader.load(context, item.sourceIcon)
.centerCrop()
.placeholder(R.drawable.image_rss)
.error(R.drawable.image_rss)
.into(iv_icon)
.into(ivIcon)
}
}
override fun registerListener(holder: ItemViewHolder) {
holder.itemView.onClick {
getItem(holder.layoutPosition)?.let {
callBack.openRss(it)
ItemRssBinding.bind(holder.itemView).apply {
root.onClick {
getItem(holder.layoutPosition)?.let {
callBack.openRss(it)
}
}
}
holder.itemView.onLongClick {
getItem(holder.layoutPosition)?.let {
showMenu(holder.itemView.iv_icon, it)
root.onLongClick {
getItem(holder.layoutPosition)?.let {
showMenu(ivIcon, it)
}
true
}
true
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,19 +1,17 @@
package io.legado.app.ui.rss.source.debug
import android.os.Bundle
import io.legado.app.R
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.accentColor
import io.legado.app.utils.getViewModel
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 org.jetbrains.anko.toast
class RssSourceDebugActivity : VMBaseActivity<RssSourceDebugModel>(R.layout.activity_source_debug) {
class RssSourceDebugActivity : VMBaseActivity<ActivitySourceDebugBinding, RssSourceDebugModel>() {
override val viewModel: RssSourceDebugModel
get() = getViewModel(RssSourceDebugModel::class.java)
@ -27,7 +25,7 @@ class RssSourceDebugActivity : VMBaseActivity<RssSourceDebugModel>(R.layout.acti
launch {
adapter.addItem(msg)
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() {
ATH.applyEdgeEffectColor(recycler_view)
ATH.applyEdgeEffectColor(binding.recyclerView)
adapter = RssSourceDebugAdapter(this)
recycler_view.adapter = adapter
rotate_loading.loadingColor = accentColor
binding.recyclerView.adapter = adapter
binding.rotateLoading.loadingColor = accentColor
}
private fun initSearchView() {
search_view.gone()
binding.recyclerView.gone()
}
private fun startSearch() {
adapter.clearItems()
viewModel.startDebug({
rotate_loading.show()
binding.rotateLoading.show()
}, {
toast("未获取到源")
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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())
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,6 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_view"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

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