更新界面
This commit is contained in:
@@ -25,7 +25,6 @@ import io.legato.kazusa.utils.compress.ZipUtils
|
||||
import io.legato.kazusa.utils.fromJsonObject
|
||||
import io.legato.kazusa.utils.getPrefString
|
||||
import io.legato.kazusa.utils.isJson
|
||||
import io.legato.kazusa.utils.removePref
|
||||
import io.legato.kazusa.utils.toastOnUi
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.runBlocking
|
||||
@@ -166,7 +165,7 @@ object AppWebDav {
|
||||
val auth = Authorization(account, password)
|
||||
checkAuthorization(auth)
|
||||
|
||||
appCtx.toastOnUi("WebDAV 服务正常")
|
||||
appCtx.toastOnUi("WebDAV 服务可用")
|
||||
true
|
||||
}.getOrElse {
|
||||
it.printStackTrace()
|
||||
|
||||
@@ -13,7 +13,10 @@ data class AppReleaseInfo(
|
||||
val downloadUrl: String,
|
||||
val assetUrl: String
|
||||
) {
|
||||
val versionName: String = name.split("_").getOrNull(2)?.dropLast(2) ?: ""
|
||||
val versionName: String = Regex("""legado_app_([\d.]+)""")
|
||||
.find(name)
|
||||
?.groupValues?.get(1)
|
||||
?: ""
|
||||
}
|
||||
|
||||
enum class AppVariant {
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package io.legato.kazusa.ui.about
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.base.BaseDialogFragment
|
||||
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
|
||||
import io.legato.kazusa.databinding.DialogUpdateBinding
|
||||
import io.legato.kazusa.help.update.AppUpdate
|
||||
//import io.legado.app.lib.theme.primaryColor
|
||||
import io.legato.kazusa.model.Download
|
||||
import io.legato.kazusa.utils.setLayout
|
||||
import io.legato.kazusa.utils.toastOnUi
|
||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||
import io.noties.markwon.Markwon
|
||||
@@ -17,7 +15,7 @@ import io.noties.markwon.ext.tables.TablePlugin
|
||||
import io.noties.markwon.html.HtmlPlugin
|
||||
import io.noties.markwon.image.glide.GlideImagesPlugin
|
||||
|
||||
class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
||||
class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) {
|
||||
|
||||
constructor(updateInfo: AppUpdate.UpdateInfo) : this() {
|
||||
arguments = Bundle().apply {
|
||||
@@ -32,7 +30,6 @@ class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setLayout(0.9f, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -57,8 +54,19 @@ class UpdateDialog() : BaseDialogFragment(R.layout.dialog_update) {
|
||||
when (it.itemId) {
|
||||
R.id.menu_download -> {
|
||||
val url = arguments?.getString("url")
|
||||
val name = arguments?.getString("name")
|
||||
if (url != null && name != null) {
|
||||
val baseName = arguments?.getString("name")
|
||||
?.removeSuffix(".apk")
|
||||
|
||||
val abi = Build.SUPPORTED_ABIS.firstOrNull() ?: "universal"
|
||||
val abiSuffix = when {
|
||||
abi.contains("arm64") -> "arm64-v8a"
|
||||
abi.contains("armeabi") -> "armeabi-v7a"
|
||||
else -> "universal"
|
||||
}
|
||||
|
||||
val name = "${baseName}_$abiSuffix.apk"
|
||||
|
||||
if (url != null && baseName != null) {
|
||||
Download.start(requireContext(), url, name)
|
||||
toastOnUi(R.string.download_start)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.base.BaseDialogFragment
|
||||
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
|
||||
import io.legato.kazusa.base.adapter.ItemViewHolder
|
||||
import io.legato.kazusa.base.adapter.RecyclerAdapter
|
||||
import io.legato.kazusa.constant.PreferKey
|
||||
@@ -33,7 +33,7 @@ import splitties.views.onClick
|
||||
/**
|
||||
* 导入书源弹出窗口
|
||||
*/
|
||||
class ImportBookSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_view),
|
||||
class ImportBookSourceDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_recycler_view),
|
||||
Toolbar.OnMenuItemClickListener,
|
||||
CodeDialog.Callback {
|
||||
|
||||
@@ -50,7 +50,6 @@ class ImportBookSourceDialog() : BaseDialogFragment(R.layout.dialog_recycler_vie
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.graphics.drawable.GradientDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.Animation
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.SeekBar
|
||||
@@ -36,6 +37,7 @@ import io.legato.kazusa.utils.modifyBegin
|
||||
import io.legato.kazusa.utils.openUrl
|
||||
import io.legato.kazusa.utils.putPrefBoolean
|
||||
import io.legato.kazusa.utils.startActivity
|
||||
import io.legato.kazusa.utils.themeColor
|
||||
import io.legato.kazusa.utils.visible
|
||||
import splitties.views.onClick
|
||||
import splitties.views.onLongClick
|
||||
@@ -52,6 +54,7 @@ class ReadMenu @JvmOverloads constructor(
|
||||
private val binding = ViewReadMenuBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
private var confirmSkipToChapter: Boolean = false
|
||||
private var isMenuOutAnimating = false
|
||||
|
||||
private val menuTopIn: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_top_in)
|
||||
}
|
||||
@@ -64,6 +67,17 @@ class ReadMenu @JvmOverloads constructor(
|
||||
private val menuBottomOut: Animation by lazy {
|
||||
loadAnimation(context, R.anim.anim_readbook_bottom_out)
|
||||
}
|
||||
|
||||
private val fadeIn = AlphaAnimation(0f, 1f).apply {
|
||||
duration = 280
|
||||
fillAfter = true
|
||||
}
|
||||
|
||||
private val fadeOut = AlphaAnimation(1f, 0f).apply {
|
||||
duration = 280
|
||||
fillAfter = true
|
||||
}
|
||||
|
||||
// private val immersiveMenu: Boolean
|
||||
// get() = AppConfig.readBarStyleFollowPage && ReadBookConfig.durConfig.curBgType() == 0
|
||||
// private var bgColor: Int = if (immersiveMenu) {
|
||||
@@ -84,11 +98,13 @@ class ReadMenu @JvmOverloads constructor(
|
||||
// .setPressedColor(ColorUtils.darkenColor(bgColor))
|
||||
// .create()
|
||||
private var onMenuOutEnd: (() -> Unit)? = null
|
||||
|
||||
private val showBrightnessView
|
||||
get() = context.getPrefBoolean(
|
||||
PreferKey.showBrightnessView,
|
||||
true
|
||||
)
|
||||
|
||||
private val sourceMenu by lazy {
|
||||
PopupMenu(context, binding.tvSourceAction).apply {
|
||||
inflate(R.menu.book_read_source)
|
||||
@@ -249,10 +265,10 @@ class ReadMenu @JvmOverloads constructor(
|
||||
|
||||
fun upBrightnessState() {
|
||||
if (brightnessAuto()) {
|
||||
//binding.ivBrightnessAuto.setColorFilter(context.accentColor)
|
||||
binding.ivBrightnessAuto.setColorFilter(context.themeColor(com.google.android.material.R.attr.colorPrimary))
|
||||
binding.seekBrightness.isEnabled = false
|
||||
} else {
|
||||
//binding.ivBrightnessAuto.setColorFilter(context.buttonDisabledColor)
|
||||
binding.ivBrightnessAuto.setColorFilter(context.themeColor(com.google.android.material.R.attr.colorOnSurface))
|
||||
binding.seekBrightness.isEnabled = true
|
||||
}
|
||||
setScreenBrightness(AppConfig.readBrightness.toFloat())
|
||||
@@ -283,6 +299,7 @@ class ReadMenu @JvmOverloads constructor(
|
||||
if (anim) {
|
||||
binding.titleBar.startAnimation(menuTopIn)
|
||||
binding.bottomMenu.startAnimation(menuBottomIn)
|
||||
updateBrightnessVisibility(true)
|
||||
} else {
|
||||
menuInListener.onAnimationStart(menuBottomIn)
|
||||
menuInListener.onAnimationEnd(menuBottomIn)
|
||||
@@ -299,6 +316,8 @@ class ReadMenu @JvmOverloads constructor(
|
||||
if (anim) {
|
||||
binding.titleBar.startAnimation(menuTopOut)
|
||||
binding.bottomMenu.startAnimation(menuBottomOut)
|
||||
updateBrightnessVisibility(false)
|
||||
|
||||
} else {
|
||||
menuOutListener.onAnimationStart(menuBottomOut)
|
||||
menuOutListener.onAnimationEnd(menuBottomOut)
|
||||
@@ -306,6 +325,16 @@ class ReadMenu @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun updateBrightnessVisibility(boolean: Boolean) {
|
||||
if (showBrightnessView) {
|
||||
if(boolean){
|
||||
binding.llBrightness.startAnimation(fadeIn)
|
||||
}else{
|
||||
binding.llBrightness.startAnimation(fadeOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun brightnessAuto(): Boolean {
|
||||
return context.getPrefBoolean("brightnessAuto", true) || !showBrightnessView
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.base.BaseDialogFragment
|
||||
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
|
||||
import io.legato.kazusa.constant.EventBus
|
||||
import io.legato.kazusa.databinding.DialogReadPaddingBinding
|
||||
import io.legato.kazusa.help.config.ReadBookConfig
|
||||
import io.legato.kazusa.utils.postEvent
|
||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
class PaddingConfigDialog : BaseDialogFragment(R.layout.dialog_read_padding) {
|
||||
class PaddingConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_padding) {
|
||||
|
||||
private val binding by viewBinding(DialogReadPaddingBinding::bind)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.legato.kazusa.ui.book.read.config
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -20,15 +19,11 @@ import io.legato.kazusa.lib.dialogs.selector
|
||||
import io.legato.kazusa.model.ReadBook
|
||||
import io.legato.kazusa.ui.book.read.ReadBookActivity
|
||||
import io.legato.kazusa.ui.font.FontSelectDialog
|
||||
import io.legato.kazusa.ui.widget.DetailSeekBar
|
||||
import io.legato.kazusa.utils.ChineseUtils
|
||||
import io.legato.kazusa.utils.postEvent
|
||||
import io.legato.kazusa.utils.showDialogFragment
|
||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||
import splitties.views.onLongClick
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.transition.TransitionManager
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import io.legato.kazusa.help.config.ThemeConfig
|
||||
|
||||
class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_style),
|
||||
@@ -38,8 +33,6 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
|
||||
private val callBack get() = activity as? ReadBookActivity
|
||||
private lateinit var styleAdapter: StyleAdapter
|
||||
|
||||
private lateinit var allSliders: List<DetailSeekBar>
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
(activity as ReadBookActivity).bottomDialog++
|
||||
initView()
|
||||
@@ -158,22 +151,6 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(1, 2, 5))
|
||||
}
|
||||
|
||||
allSliders = listOf(
|
||||
dsbTextSize,
|
||||
dsbTextLetterSpacing,
|
||||
dsbLineSize,
|
||||
dsbParagraphSpacing
|
||||
)
|
||||
|
||||
allSliders.forEach { seekBar ->
|
||||
seekBar.onStartTracking = {
|
||||
setOnlyActiveSeekBarVisible(seekBar, true)
|
||||
}
|
||||
seekBar.onStopTracking = {
|
||||
setOnlyActiveSeekBarVisible(seekBar, false)
|
||||
}
|
||||
}
|
||||
|
||||
dsbTextSize.onChanged = {
|
||||
ReadBookConfig.textSize = it + 5
|
||||
postEvent(EventBus.UP_CONFIG, arrayListOf(8, 5))
|
||||
@@ -192,24 +169,6 @@ class ReadStyleDialog : BaseBottomSheetDialogFragment(R.layout.dialog_read_book_
|
||||
}
|
||||
}
|
||||
|
||||
private fun setOnlyActiveSeekBarVisible(activeSeekBar: DetailSeekBar, visible: Boolean) {
|
||||
TransitionManager.beginDelayedTransition(binding.rootView)
|
||||
if (visible) {
|
||||
binding.setBar.visibility = View.GONE
|
||||
binding.setBottomBar.visibility = View.GONE
|
||||
} else {
|
||||
binding.setBar.visibility = View.VISIBLE
|
||||
binding.setBottomBar.visibility = View.VISIBLE
|
||||
}
|
||||
allSliders.forEach { seekBar ->
|
||||
if (seekBar != activeSeekBar) {
|
||||
seekBar.visibility = if (visible) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun changeBgTextConfig(index: Int) {
|
||||
val oldIndex = ReadBookConfig.styleSelect
|
||||
if (index != oldIndex) {
|
||||
|
||||
@@ -2,10 +2,9 @@ package io.legato.kazusa.ui.book.read.config
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.base.BaseDialogFragment
|
||||
import io.legato.kazusa.base.BaseBottomSheetDialogFragment
|
||||
import io.legato.kazusa.constant.EventBus
|
||||
import io.legato.kazusa.databinding.DialogTipConfigBinding
|
||||
import io.legato.kazusa.help.config.ReadBookConfig
|
||||
@@ -16,11 +15,10 @@ import io.legato.kazusa.utils.getIndexById
|
||||
import io.legato.kazusa.utils.hexString
|
||||
import io.legato.kazusa.utils.observeEvent
|
||||
import io.legato.kazusa.utils.postEvent
|
||||
import io.legato.kazusa.utils.setLayout
|
||||
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
|
||||
class TipConfigDialog : BaseDialogFragment(R.layout.dialog_tip_config) {
|
||||
class TipConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_tip_config) {
|
||||
|
||||
companion object {
|
||||
const val TIP_COLOR = 7897
|
||||
@@ -31,7 +29,6 @@ class TipConfigDialog : BaseDialogFragment(R.layout.dialog_tip_config) {
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
}
|
||||
|
||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package io.legato.kazusa.ui.config
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@@ -18,8 +15,6 @@ import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.dialog.MaterialDialogs
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.constant.AppLog
|
||||
import io.legato.kazusa.constant.PreferKey
|
||||
@@ -39,12 +34,10 @@ import io.legato.kazusa.lib.dialogs.selector
|
||||
import io.legato.kazusa.lib.permission.Permissions
|
||||
import io.legato.kazusa.lib.permission.PermissionsCompat
|
||||
import io.legato.kazusa.lib.prefs.fragment.PreferenceFragment
|
||||
//import io.legado.app.lib.theme.primaryColor
|
||||
import io.legato.kazusa.ui.about.AppLogDialog
|
||||
import io.legato.kazusa.ui.file.HandleFileContract
|
||||
import io.legato.kazusa.ui.widget.dialog.WaitDialog
|
||||
import io.legato.kazusa.utils.FileDoc
|
||||
import io.legato.kazusa.utils.applyTint
|
||||
import io.legato.kazusa.utils.checkWrite
|
||||
import io.legato.kazusa.utils.getPrefString
|
||||
import io.legato.kazusa.utils.isContentScheme
|
||||
@@ -222,9 +215,6 @@ class BackupConfigFragment : PreferenceFragment(),
|
||||
}
|
||||
"web_dav_auth" -> {
|
||||
showWebDavAuthDialog()
|
||||
lifecycleScope.launch {
|
||||
testWebDav()
|
||||
}
|
||||
}
|
||||
"web_dav_backup" -> backup()
|
||||
"web_dav_restore" -> restore()
|
||||
@@ -254,6 +244,9 @@ class BackupConfigFragment : PreferenceFragment(),
|
||||
|
||||
upPreferenceSummary(PreferKey.webDavAccount, account)
|
||||
upPreferenceSummary(PreferKey.webDavPassword, password)
|
||||
lifecycleScope.launch {
|
||||
testWebDav()
|
||||
}
|
||||
}
|
||||
|
||||
cancelButton()
|
||||
|
||||
@@ -2,24 +2,16 @@ package io.legato.kazusa.ui.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.SeekBar
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import com.google.android.material.slider.Slider
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.databinding.ViewDetailSeekBarBinding
|
||||
//import io.legado.app.lib.theme.bottomBackground
|
||||
//import io.legado.app.lib.theme.getPrimaryTextColor
|
||||
import io.legato.kazusa.ui.widget.seekbar.SeekBarChangeListener
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
class DetailSeekBar @JvmOverloads constructor(
|
||||
context: Context,
|
||||
@@ -31,6 +23,11 @@ class DetailSeekBar @JvmOverloads constructor(
|
||||
private val isBottomBackground: Boolean
|
||||
|
||||
var valueFormat: ((progress: Int) -> String)? = null
|
||||
set(value) {
|
||||
field = value
|
||||
upValue()
|
||||
}
|
||||
|
||||
var onStartTracking: (() -> Unit)? = null
|
||||
var onChanged: ((progress: Int) -> Unit)? = null
|
||||
var onStopTracking: (() -> Unit)? = null
|
||||
@@ -39,7 +36,6 @@ class DetailSeekBar @JvmOverloads constructor(
|
||||
get() = binding.slider.value.toInt()
|
||||
set(value) {
|
||||
binding.slider.value = value.toFloat()
|
||||
upValue()
|
||||
}
|
||||
|
||||
var max: Int
|
||||
@@ -54,7 +50,6 @@ class DetailSeekBar @JvmOverloads constructor(
|
||||
typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false)
|
||||
val title = typedArray.getText(R.styleable.DetailSeekBar_title)
|
||||
|
||||
|
||||
binding.tvSeekTitle.apply {
|
||||
text = title
|
||||
TooltipCompat.setTooltipText(this, title)
|
||||
@@ -93,23 +88,6 @@ class DetailSeekBar @JvmOverloads constructor(
|
||||
}
|
||||
})
|
||||
|
||||
binding.slider.setOnTouchListener { _, event ->
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
val slider = binding.slider
|
||||
val sliderWidth = slider.width - slider.paddingStart - slider.paddingEnd
|
||||
val touchX = event.x - slider.paddingStart
|
||||
|
||||
val proportion = (slider.value - slider.valueFrom) / (slider.valueTo - slider.valueFrom)
|
||||
val thumbCenterX = proportion * sliderWidth
|
||||
|
||||
val thumbRadiusPx = slider.thumbRadius * 2f // 可适当扩大滑块判断区域
|
||||
|
||||
val isTouchNearThumb = kotlin.math.abs(touchX - thumbCenterX) <= thumbRadiusPx
|
||||
return@setOnTouchListener !isTouchNearThumb // 拦截不是点在滑块上的点击
|
||||
}
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun upValue(progress: Int = binding.slider.value.toInt()) {
|
||||
@@ -124,4 +102,8 @@ class DetailSeekBar @JvmOverloads constructor(
|
||||
upValue(progress)
|
||||
}
|
||||
|
||||
fun setTitle(title: CharSequence?) {
|
||||
binding.tvSeekTitle.text = title
|
||||
TooltipCompat.setTooltipText(binding.tvSeekTitle, title)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package io.legato.kazusa.ui.widget
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import io.legato.kazusa.R
|
||||
import io.legato.kazusa.databinding.ViewSimpleCounterBinding
|
||||
import io.legato.kazusa.lib.dialogs.alert
|
||||
|
||||
@SuppressLint("ViewConstructor", "ClickableViewAccessibility")
|
||||
class SimpleCounterView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
private val binding = ViewSimpleCounterBinding.inflate(LayoutInflater.from(context), this)
|
||||
|
||||
private var _progress = 0
|
||||
private var _max = 100
|
||||
private val isBottomBackground: Boolean
|
||||
|
||||
var valueFormat: ((Int) -> String)? = null
|
||||
var onChanged: ((Int) -> Unit)? = null
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private var isIncrementing = false
|
||||
private var isDecrementing = false
|
||||
|
||||
private val longPressDelay = 400L
|
||||
private val repeatInterval = 320L
|
||||
|
||||
|
||||
var progress: Int
|
||||
get() = _progress
|
||||
set(value) {
|
||||
_progress = value.coerceIn(0, _max)
|
||||
updateValue()
|
||||
}
|
||||
|
||||
var max: Int
|
||||
get() = _max
|
||||
set(value) {
|
||||
_max = value
|
||||
_progress = _progress.coerceAtMost(_max)
|
||||
updateValue()
|
||||
}
|
||||
|
||||
init {
|
||||
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailSeekBar)
|
||||
isBottomBackground = typedArray.getBoolean(R.styleable.DetailSeekBar_isBottomBackground, false)
|
||||
val title = typedArray.getText(R.styleable.DetailSeekBar_title)
|
||||
_max = typedArray.getInt(R.styleable.DetailSeekBar_max, 100)
|
||||
typedArray.recycle()
|
||||
|
||||
binding.tvSeekTitle.text = title
|
||||
TooltipCompat.setTooltipText(binding.tvSeekTitle, title)
|
||||
|
||||
binding.ivSeekPlus.setOnClickListener {
|
||||
if (_progress < _max) {
|
||||
_progress++
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivSeekReduce.setOnClickListener {
|
||||
if (_progress > 0) {
|
||||
_progress--
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivSeekPlus.setOnTouchListener { _, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
isIncrementing = true
|
||||
handler.postDelayed(startIncrementRunnable, longPressDelay)
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
isIncrementing = false
|
||||
handler.removeCallbacks(startIncrementRunnable)
|
||||
handler.removeCallbacks(incrementRunnable)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
binding.ivSeekReduce.setOnTouchListener { _, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
isDecrementing = true
|
||||
handler.postDelayed(startDecrementRunnable, longPressDelay)
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
isDecrementing = false
|
||||
handler.removeCallbacks(startDecrementRunnable)
|
||||
handler.removeCallbacks(decrementRunnable)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
binding.tvSeekValue.setOnClickListener {
|
||||
showSeekBarDialog()
|
||||
}
|
||||
|
||||
updateValue()
|
||||
}
|
||||
|
||||
private fun showSeekBarDialog() {
|
||||
context.alert(title = null, message = null) {
|
||||
customView {
|
||||
val detailSeekBar = DetailSeekBar(ctx).apply {
|
||||
max = _max
|
||||
progress = _progress
|
||||
valueFormat = this@SimpleCounterView.valueFormat
|
||||
setTitle(binding.tvSeekTitle.text)
|
||||
onChanged = {
|
||||
_progress = it
|
||||
updateValue()
|
||||
this@SimpleCounterView.onChanged?.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
FrameLayout(ctx).apply {
|
||||
setPadding(64, 0, 64, 0)
|
||||
addView(detailSeekBar, LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
okButton()
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun updateValue() {
|
||||
binding.tvSeekValue.text = valueFormat?.invoke(_progress) ?: _progress.toString()
|
||||
}
|
||||
|
||||
private val startIncrementRunnable = Runnable {
|
||||
handler.post(incrementRunnable)
|
||||
}
|
||||
|
||||
private val startDecrementRunnable = Runnable {
|
||||
handler.post(decrementRunnable)
|
||||
}
|
||||
|
||||
private val incrementRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (_progress < _max) {
|
||||
_progress++
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
handler.postDelayed(this, repeatInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val decrementRunnable = object : Runnable {
|
||||
override fun run() {
|
||||
if (_progress > 0) {
|
||||
_progress--
|
||||
updateValue()
|
||||
onChanged?.invoke(_progress)
|
||||
handler.postDelayed(this, repeatInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
handler.removeCallbacks(incrementRunnable)
|
||||
handler.removeCallbacks(decrementRunnable)
|
||||
super.onDetachedFromWindow()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,15 +3,7 @@ package io.legato.kazusa.ui.widget.text
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import io.legato.kazusa.lib.theme.Selector
|
||||
import io.legato.kazusa.lib.theme.ThemeStore
|
||||
|
||||
class TextInputLayout(context: Context, attrs: AttributeSet?) : TextInputLayout(context, attrs) {
|
||||
|
||||
init {
|
||||
if (!isInEditMode) {
|
||||
defaultHintTextColor =
|
||||
Selector.colorBuild().setDefaultColor(ThemeStore.accentColor(context)).create()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user