fixed some bugs

This commit is contained in:
2026-08-24 14:25:31 +08:00
parent 8d4a81b4f5
commit 28674def97
5 changed files with 148 additions and 43 deletions

View File

@@ -28,6 +28,7 @@ class OralTrainerPlayerView @JvmOverloads constructor(
private var longPressStartY = 0f
private var longPressActive = false
private var speedBeforeLongPress: Float? = null
private var verticalSwipeListener: ((isSwipeUp: Boolean) -> Unit)? = null
private val longPressSpeedRunnable = Runnable {
val activeController = controller ?: return@Runnable
@@ -70,6 +71,11 @@ class OralTrainerPlayerView @JvmOverloads constructor(
val dy = e2.y - start.y
val minDistancePx = gestureControls.minSwipeDistanceDp * density
val minVelocityPx = gestureControls.minSwipeVelocityDpPerSecond * density
if (abs(dy) > minDistancePx && abs(dy) > abs(dx) && abs(velocityY) >= minVelocityPx) {
val isSwipeUp = dy < 0
verticalSwipeListener?.invoke(isSwipeUp)
return true
}
if (abs(dx) < abs(dy) || abs(dx) < minDistancePx || abs(velocityX) < minVelocityPx) {
return false
}
@@ -112,6 +118,10 @@ class OralTrainerPlayerView @JvmOverloads constructor(
gestureControls = config
}
fun setVerticalSwipeListener(listener: ((isSwipeUp: Boolean) -> Unit)?) {
verticalSwipeListener = listener
}
override fun onTouchEvent(event: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event)
}

View File

@@ -19,7 +19,7 @@ android {
minSdk = 26
targetSdk = 35
versionCode = 1
versionName = "0.1.0"
versionName = "0.1.1"
}
compileOptions {

View File

@@ -2,8 +2,11 @@ package cn.learningpad.oraltrainer.sample
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.pm.ActivityInfo
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.content.res.Configuration
@@ -17,11 +20,13 @@ import android.os.Bundle
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.TranslateAnimation
import android.widget.Button
import android.widget.FrameLayout
import android.widget.HorizontalScrollView
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import android.widget.SeekBar
import android.widget.Switch
@@ -75,6 +80,15 @@ class MainActivity : Activity() {
private var catalogStatusTextValue = "正在同步"
private var activeModule = Module.TRAIN
private var continuousPlaybackEnabled = false
private var landscapeSubtitleVisible = true
private val screenActionReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == Intent.ACTION_SCREEN_OFF) {
controller.pause()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -104,6 +118,11 @@ class MainActivity : Activity() {
setContentView(createContentView())
loadCatalog()
refreshCurrentUi()
registerReceiver(
screenActionReceiver,
IntentFilter(Intent.ACTION_SCREEN_OFF),
)
}
override fun onConfigurationChanged(newConfig: Configuration) {
@@ -132,6 +151,33 @@ class MainActivity : Activity() {
}
}
override fun onPause() {
super.onPause()
controller.pause()
}
override fun onResume() {
super.onResume()
registerReceiver(
screenActionReceiver,
IntentFilter(Intent.ACTION_SCREEN_OFF),
)
}
override fun onStop() {
runCatching { unregisterReceiver(screenActionReceiver) }
super.onStop()
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
} else {
moveTaskToBack(true)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode != PICK_VIDEO_REQUEST || resultCode != RESULT_OK) {
@@ -277,26 +323,82 @@ class MainActivity : Activity() {
setBackgroundColor(Color.BLACK)
addView(createPlayerView())
addView(createPlayerOverlay())
addView(
LinearLayout(this@MainActivity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = FrameLayout.LayoutParams(
val subtitleContainer = LinearLayout(this@MainActivity).apply {
orientation = LinearLayout.VERTICAL
layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM,
)
addView(createLandscapeSentencePanel().apply {
layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM,
)
addView(createLandscapeSentencePanel().apply {
layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
)
})
addView(createRotationButtonRow())
}
)
})
}
addView(subtitleContainer)
applyLandscapeSubtitleState(subtitleContainer, animate = false)
installLandscapeSwipeGesture(subtitleContainer)
}
}
private fun installLandscapeSwipeGesture(subtitleContainer: View) {
playerView.setVerticalSwipeListener { isSwipeUp ->
if (isSwipeUp == landscapeSubtitleVisible) {
return@setVerticalSwipeListener
}
landscapeSubtitleVisible = isSwipeUp
applyLandscapeSubtitleState(subtitleContainer, animate = true)
}
}
private fun applyLandscapeSubtitleState(container: View, animate: Boolean) {
if (!animate || container.visibility == View.GONE) {
container.clearAnimation()
if (landscapeSubtitleVisible) {
container.visibility = View.VISIBLE
} else {
container.visibility = View.GONE
}
return
}
if (landscapeSubtitleVisible) {
container.visibility = View.VISIBLE
container.post {
if (landscapeSubtitleVisible && container.visibility == View.VISIBLE) {
startSlideAnimation(container, fromYDelta = 1f, toYDelta = 0f) {
container.visibility = View.VISIBLE
}
}
}
} else {
startSlideAnimation(container, fromYDelta = 0f, toYDelta = 1f) {
container.visibility = View.GONE
}
}
}
private fun startSlideAnimation(
view: View,
fromYDelta: Float,
toYDelta: Float,
onEnd: () -> Unit,
) {
val animation = TranslateAnimation(0f, 0f, view.height * fromYDelta, view.height * toYDelta).apply {
duration = 220L
fillAfter = true
setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation?) = Unit
override fun onAnimationRepeat(animation: Animation?) = Unit
override fun onAnimationEnd(animation: Animation?) {
view.post(onEnd)
}
})
}
view.startAnimation(animation)
}
private fun createLandscapeSentencePanel(): View {
return createSentenceContent(translucent = true).apply {
layoutParams = FrameLayout.LayoutParams(
@@ -391,35 +493,18 @@ class MainActivity : Activity() {
return overlay
}
private fun createRotationButtonRow(): View {
return LinearLayout(this).apply {
orientation = LinearLayout.HORIZONTAL
gravity = Gravity.END
setPadding(0, 0, 12.dp, 12.dp)
addView(createRotationButton())
}
}
private fun createRotationButton(): ImageButton {
val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
return ImageButton(this).apply {
setImageResource(R.drawable.ic_screen_rotation)
imageTintList = ColorStateList.valueOf(Color.WHITE)
background = rounded(Color.argb(178, 9, 12, 16), 22.dp.toFloat())
scaleType = ImageView.ScaleType.CENTER_INSIDE
setPadding(10.dp, 10.dp, 10.dp, 10.dp)
contentDescription = if (isLandscape) "竖屏" else "横屏"
contentDescription = "横屏"
layoutParams = LinearLayout.LayoutParams(44.dp, 44.dp)
setOnClickListener { toggleOrientation() }
}
}
private fun toggleOrientation() {
val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
requestedOrientation = if (isLandscape) {
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
} else {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
setOnClickListener {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
}
}

View File

@@ -1,9 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M16.48,2.52c3,2.02 5.02,5.27 5.02,9.48 0,1.77 -0.38,3.45 -1.06,4.97L10.02,2.94C11.39,2.51 12.86,2.28 14.4,2.28c0.74,0 1.47,0.08 2.08,0.24zM10.02,21.06L1.56,7.43C0.56,8.82 0,10.36 0,12c0,4.97 4.03,9 9,9h0.51C9.73,21.06 9.87,21.06 10.02,21.06zM9,22.06C3.96,22.06 -0.03,18.08 -0.03,13.04c0,-1.6 0.39,-3.11 1.07,-4.44l8.57,13.12C9.63,21.72 9.6,21.88 9.6,22.06 9.6,22.06 9.6,22.06 9,22.06zM20.93,5.44c0.68,1.33 1.07,2.84 1.07,4.44 0,5.04 -3.99,9.02 -9.03,9.02 -0.2,0 -0.4,-0.01 -0.6,-0.02l8.56,-13.44L20.93,5.44z"/>
android:strokeColor="@android:color/white"
android:strokeWidth="3.2"
android:pathData="M15,15h10v20h-10z"/>
<path
android:strokeColor="@android:color/white"
android:strokeWidth="3.2"
android:strokeLineCap="round"
android:pathData="M25,11a12,12 0 0 1 11,7.3"/>
<path
android:fillColor="@android:color/white"
android:pathData="M40.8,14.6L37.2,20.4L34.1,13.8Z"/>
</vector>

View File

@@ -2,7 +2,8 @@
<style name="AppTheme" parent="android:style/Theme.Material.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
<item name="android:fontFamily">sans</item>
<item name="android:colorAccent">#2563EB</item>
</style>