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

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 showTip = "showTip"
const val sliderVibrator = "sliderVibrator" const val sliderVibrator = "sliderVibrator"
const val selectVibrator = "selectVibrator"
const val audioCacheCleanTime = "audioCacheCleanTime" const val audioCacheCleanTime = "audioCacheCleanTime"
const val audioPreDownloadNum = "audioPreDownloadNum" const val audioPreDownloadNum = "audioPreDownloadNum"
} }
@@ -990,6 +990,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
appCtx.putPrefBoolean(PreferKey.sliderVibrator, value) appCtx.putPrefBoolean(PreferKey.sliderVibrator, value)
} }
var selectVibrator: Boolean
get() = appCtx.getPrefBoolean(PreferKey.selectVibrator, false)
set(value) {
appCtx.putPrefBoolean(PreferKey.selectVibrator, value)
}
val audioPreDownloadNum: Int val audioPreDownloadNum: Int
get() = appCtx.getPrefInt(PreferKey.audioPreDownloadNum, 10) get() = appCtx.getPrefInt(PreferKey.audioPreDownloadNum, 10)
@@ -13,13 +13,13 @@ import android.graphics.drawable.TransitionDrawable
import android.icu.text.SimpleDateFormat import android.icu.text.SimpleDateFormat
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.HapticFeedbackConstants
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.activity.addCallback import androidx.activity.addCallback
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.graphics.scale import androidx.core.graphics.scale
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.transition.TransitionManager 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.isAudio
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.config.AppConfig 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.AudioPlay
import io.legado.app.model.BookCover import io.legado.app.model.BookCover
import io.legado.app.service.AudioPlayService import io.legado.app.service.AudioPlayService
@@ -332,7 +331,7 @@ class AudioPlayActivity :
addOnSliderTouchListener(object : Slider.OnSliderTouchListener { addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) { override fun onStartTrackingTouch(slider: Slider) {
slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) slider.performHapticFeedback(HapticFeedbackConstantsCompat.VIRTUAL_KEY)
} }
override fun onStopTrackingTouch(slider: Slider) {} override fun onStopTrackingTouch(slider: Slider) {}
@@ -358,7 +357,7 @@ class AudioPlayActivity :
addOnSliderTouchListener(object : Slider.OnSliderTouchListener { addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) { override fun onStartTrackingTouch(slider: Slider) {
slider.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) slider.performHapticFeedback(HapticFeedbackConstantsCompat.VIRTUAL_KEY)
} }
override fun onStopTrackingTouch(slider: Slider) {} override fun onStopTrackingTouch(slider: Slider) {}
@@ -5,11 +5,11 @@ import android.animation.ValueAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.HapticFeedbackConstants
import android.view.MotionEvent import android.view.MotionEvent
import android.view.ViewConfiguration import android.view.ViewConfiguration
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import androidx.core.animation.doOnEnd import androidx.core.animation.doOnEnd
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.legado.app.utils.findCenterViewPosition import io.legado.app.utils.findCenterViewPosition
@@ -255,7 +255,7 @@ class WebtoonRecyclerView @JvmOverloads constructor(
override fun onLongTapConfirmed(ev: MotionEvent) { override fun onLongTapConfirmed(ev: MotionEvent) {
if (longTapListener?.invoke(ev) == true) { 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.view.animation.Animation
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.slider.Slider 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.model.ReadManga
import io.legado.app.ui.browser.WebViewActivity import io.legado.app.ui.browser.WebViewActivity
import io.legado.app.utils.ConstraintModify import io.legado.app.utils.ConstraintModify
import io.legado.app.utils.VibrationUtils
import io.legado.app.utils.activity import io.legado.app.utils.activity
import io.legado.app.utils.applyNavigationBarPadding import io.legado.app.utils.applyNavigationBarPadding
import io.legado.app.utils.gone import io.legado.app.utils.gone
@@ -242,16 +242,16 @@ class MangaMenu @JvmOverloads constructor(
ReadManga.moveToPrevChapter(true) ReadManga.moveToPrevChapter(true)
} }
seekReadPage.addOnChangeListener { slider, value, fromUser -> seekReadPage.addOnChangeListener { _, value, fromUser ->
if (fromUser) { if (fromUser) {
VibrationUtils.vibrate(context, 12) HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE
callBack.skipToPage(value.toInt() - 1) callBack.skipToPage(value.toInt() - 1)
} }
} }
seekReadPage.addOnSliderTouchListener(object : Slider.OnSliderTouchListener { seekReadPage.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) { override fun onStartTrackingTouch(slider: Slider) {
VibrationUtils.vibrate(context, 16) HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE
vwMenuBg.setOnClickListener(null) vwMenuBg.setOnClickListener(null)
} }
@@ -18,6 +18,7 @@ import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.get import androidx.core.view.get
import androidx.core.view.size import androidx.core.view.size
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -939,7 +940,8 @@ class ReadBookActivity : BaseReadBookActivity(),
textMenuPosition.x = x textMenuPosition.x = x
textMenuPosition.y = top 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.x = x
cursorRight.y = y cursorRight.y = y
cursorRight.visible(true) cursorRight.visible(true)
if (AppConfig.selectVibrator)
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) root.performHapticFeedback(HapticFeedbackConstantsCompat.TEXT_HANDLE_MOVE)
} }
/** /**
@@ -17,6 +17,7 @@ import androidx.annotation.OptIn
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.doOnAttach import androidx.core.view.doOnAttach
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.isGone 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.browser.WebViewActivity
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.ConstraintModify import io.legado.app.utils.ConstraintModify
import io.legado.app.utils.VibrationUtils
import io.legado.app.utils.activity import io.legado.app.utils.activity
import io.legado.app.utils.applyNavigationBarPadding import io.legado.app.utils.applyNavigationBarPadding
import io.legado.app.utils.dpToPx import io.legado.app.utils.dpToPx
@@ -470,7 +470,7 @@ class ReadMenu @JvmOverloads constructor(
if (AppConfig.progressBarBehavior == "page") if (AppConfig.progressBarBehavior == "page")
ReadBook.skipToPage(value.toInt() - 1) ReadBook.skipToPage(value.toInt() - 1)
if (AppConfig.sliderVibrator) 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
}
}
}
@@ -1387,4 +1387,7 @@
<string name="click_image_way">点击图片行为</string> <string name="click_image_way">点击图片行为</string>
<string name="show_web_log">输出日志</string> <string name="show_web_log">输出日志</string>
<string name="is_blur_progressive_enable">启用渐变模糊</string> <string name="is_blur_progressive_enable">启用渐变模糊</string>
<string name="enable_select_vibrator">选择文本时震动</string>
<string name="re_sync_webdav">重新同步远程书籍</string>
<string name="underline_padding">离字间距</string>
</resources> </resources>
+3
View File
@@ -1391,4 +1391,7 @@
<string name="click_image_way">点击图片行为</string> <string name="click_image_way">点击图片行为</string>
<string name="show_web_log">输出日志</string> <string name="show_web_log">输出日志</string>
<string name="is_blur_progressive_enable">启用渐变模糊</string> <string name="is_blur_progressive_enable">启用渐变模糊</string>
<string name="enable_select_vibrator">选择文本时震动</string>
<string name="re_sync_webdav">重新同步远程书籍</string>
<string name="underline_padding">离字间距</string>
</resources> </resources>
@@ -178,6 +178,12 @@
android:title="@string/enable_slider_vibrator" android:title="@string/enable_slider_vibrator"
app:isBottomBackground="true" /> app:isBottomBackground="true" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="selectVibrator"
android:title="@string/enable_select_vibrator"
app:isBottomBackground="true" />
<io.legado.app.lib.prefs.SwitchPreference <io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="true" android:defaultValue="true"
android:key="autoChangeSource" android:key="autoChangeSource"