[优化] 优化震动效果,新增正文选取时震动开关

This commit is contained in:
HapeLee
2026-03-05 01:23:47 +08:00
parent f2d02e244a
commit f1843ab732
11 changed files with 35 additions and 65 deletions
@@ -251,6 +251,7 @@ object PreferKey {
const val showTip = "showTip"
const val sliderVibrator = "sliderVibrator"
const val selectVibrator = "selectVibrator"
const val audioCacheCleanTime = "audioCacheCleanTime"
const val audioPreDownloadNum = "audioPreDownloadNum"
}
@@ -990,6 +990,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.putPrefBoolean(PreferKey.sliderVibrator, value)
}
var selectVibrator: Boolean
get() = appCtx.getPrefBoolean(PreferKey.selectVibrator, false)
set(value) {
appCtx.putPrefBoolean(PreferKey.selectVibrator, value)
}
val audioPreDownloadNum: Int
get() = appCtx.getPrefInt(PreferKey.audioPreDownloadNum, 10)
@@ -13,13 +13,13 @@ import android.graphics.drawable.TransitionDrawable
import android.icu.text.SimpleDateFormat
import android.os.Build
import android.os.Bundle
import android.view.HapticFeedbackConstants
import android.view.Menu
import android.view.MenuItem
import androidx.activity.addCallback
import androidx.activity.viewModels
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.scale
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.transition.TransitionManager
@@ -43,7 +43,6 @@ import io.legado.app.databinding.ActivityAudioPlayBinding
import io.legado.app.help.book.isAudio
import io.legado.app.help.book.removeType
import io.legado.app.help.config.AppConfig
import io.legado.app.lib.dialogs.alert
import io.legado.app.model.AudioPlay
import io.legado.app.model.BookCover
import io.legado.app.service.AudioPlayService
@@ -332,7 +331,7 @@ class AudioPlayActivity :
addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
slider.performHapticFeedback(HapticFeedbackConstantsCompat.VIRTUAL_KEY)
}
override fun onStopTrackingTouch(slider: Slider) {}
@@ -358,7 +357,7 @@ class AudioPlayActivity :
addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
slider.performHapticFeedback(HapticFeedbackConstantsCompat.VIRTUAL_KEY)
}
override fun onStopTrackingTouch(slider: Slider) {}
@@ -5,11 +5,11 @@ import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.ViewConfiguration
import android.view.animation.DecelerateInterpolator
import androidx.core.animation.doOnEnd
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.legado.app.utils.findCenterViewPosition
@@ -255,7 +255,7 @@ class WebtoonRecyclerView @JvmOverloads constructor(
override fun onLongTapConfirmed(ev: MotionEvent) {
if (longTapListener?.invoke(ev) == true) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
performHapticFeedback(HapticFeedbackConstantsCompat.LONG_PRESS)
}
}
}
@@ -8,6 +8,7 @@ import android.view.LayoutInflater
import android.view.animation.Animation
import android.widget.FrameLayout
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.google.android.material.slider.Slider
@@ -20,7 +21,6 @@ import io.legado.app.model.ReadBook
import io.legado.app.model.ReadManga
import io.legado.app.ui.browser.WebViewActivity
import io.legado.app.utils.ConstraintModify
import io.legado.app.utils.VibrationUtils
import io.legado.app.utils.activity
import io.legado.app.utils.applyNavigationBarPadding
import io.legado.app.utils.gone
@@ -242,16 +242,16 @@ class MangaMenu @JvmOverloads constructor(
ReadManga.moveToPrevChapter(true)
}
seekReadPage.addOnChangeListener { slider, value, fromUser ->
seekReadPage.addOnChangeListener { _, value, fromUser ->
if (fromUser) {
VibrationUtils.vibrate(context, 12)
HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE
callBack.skipToPage(value.toInt() - 1)
}
}
seekReadPage.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
VibrationUtils.vibrate(context, 16)
HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE
vwMenuBg.setOnClickListener(null)
}
@@ -18,6 +18,7 @@ import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.get
import androidx.core.view.size
import androidx.lifecycle.lifecycleScope
@@ -939,7 +940,8 @@ class ReadBookActivity : BaseReadBookActivity(),
textMenuPosition.x = x
textMenuPosition.y = top
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
if (AppConfig.selectVibrator)
root.performHapticFeedback(HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE)
}
/**
@@ -949,8 +951,8 @@ class ReadBookActivity : BaseReadBookActivity(),
cursorRight.x = x
cursorRight.y = y
cursorRight.visible(true)
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
if (AppConfig.selectVibrator)
root.performHapticFeedback(HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE)
}
/**
@@ -17,6 +17,7 @@ import androidx.annotation.OptIn
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.ColorUtils
import androidx.core.graphics.toColorInt
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.doOnAttach
import androidx.core.view.forEach
import androidx.core.view.isGone
@@ -42,7 +43,6 @@ import io.legado.app.model.ReadBook
import io.legado.app.ui.browser.WebViewActivity
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.ConstraintModify
import io.legado.app.utils.VibrationUtils
import io.legado.app.utils.activity
import io.legado.app.utils.applyNavigationBarPadding
import io.legado.app.utils.dpToPx
@@ -470,7 +470,7 @@ class ReadMenu @JvmOverloads constructor(
if (AppConfig.progressBarBehavior == "page")
ReadBook.skipToPage(value.toInt() - 1)
if (AppConfig.sliderVibrator)
VibrationUtils.vibrate(context, 10)
HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE
}
}
@@ -1,50 +0,0 @@
package io.legado.app.utils
import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
object VibrationUtils {
/**
* 触发单次震动
* @param context 上下文
* @param milliseconds 震动时长(毫秒)
*/
fun vibrate(context: Context, milliseconds: Long) {
val vibrator = getVibrator(context)
vibrator.vibrate(
VibrationEffect.createOneShot(
milliseconds,
VibrationEffect.DEFAULT_AMPLITUDE
)
)
}
/**
* 触发带模式的震动
* @param context 上下文
* @param pattern 震动模式数组(如 longArrayOf(0, 200, 100, 300)
* @param repeat 重复次数(-1 为不重复)
*/
fun vibratePattern(context: Context, pattern: LongArray, repeat: Int = -1) {
val vibrator = getVibrator(context)
vibrator.vibrate(VibrationEffect.createWaveform(pattern, repeat))
}
/**
* 获取 Vibrator 实例(兼容 Android 12+
*/
private fun getVibrator(context: Context): Vibrator {
return if (Build.VERSION.SDK_INT >= 31) {
val vibratorManager =
context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
@Suppress("DEPRECATION")
context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
}