android: Properly adjust emulation surface aspect ratio

Previously the emulation surface wouldn't respond properly to orientation changes. This would result in the screen appearing stretched when starting in one orientation and switching to another.

The code for calculating the bounds of the view have been changed to match the expected behavior now. Before the view would just match parent in height and width. Now instead of using setLeftTopRightBottom (which is intended to be used for animations) we pass newly calculated bounds for the view into super. Now the view bounds match the emulation output.

This also means that we don't need the overload for the SettingsActivity to launch it using an ActivityResultLauncher. We can just update the view in onResume.
master
Charles Lombardo 2023-08-27 00:16:53 +07:00
parent 6c4abd23be
commit 338d6f29b1
3 changed files with 33 additions and 45 deletions

@ -11,7 +11,6 @@ import android.view.View
import android.view.ViewGroup.MarginLayoutParams import android.view.ViewGroup.MarginLayoutParams
import android.widget.Toast import android.widget.Toast
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@ -246,17 +245,5 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
settings.putExtra(ARG_GAME_ID, gameId) settings.putExtra(ARG_GAME_ID, gameId)
context.startActivity(settings) context.startActivity(settings)
} }
fun launch(
context: Context,
launcher: ActivityResultLauncher<Intent>,
menuTag: String?,
gameId: String?
) {
val settings = Intent(context, SettingsActivity::class.java)
settings.putExtra(ARG_MENU_TAG, menuTag)
settings.putExtra(ARG_GAME_ID, gameId)
launcher.launch(settings)
}
} }
} }

@ -7,7 +7,6 @@ import android.annotation.SuppressLint
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Configuration import android.content.res.Configuration
@ -19,8 +18,6 @@ import android.util.Rational
import android.view.* import android.view.*
import android.widget.TextView import android.widget.TextView
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
@ -66,8 +63,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private var isInFoldableLayout = false private var isInFoldableLayout = false
private lateinit var onReturnFromSettings: ActivityResultLauncher<Intent>
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
if (context is EmulationActivity) { if (context is EmulationActivity) {
@ -81,11 +76,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
.collect { updateFoldableLayout(context, it) } .collect { updateFoldableLayout(context, it) }
} }
} }
onReturnFromSettings = context.activityResultRegistry.register(
"SettingsResult",
ActivityResultContracts.StartActivityForResult()
) { updateScreenLayout() }
} else { } else {
throw IllegalStateException("EmulationFragment must have EmulationActivity parent") throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
} }
@ -149,12 +139,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
R.id.menu_settings -> { R.id.menu_settings -> {
SettingsActivity.launch( SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
requireContext(),
onReturnFromSettings,
SettingsFile.FILE_NAME_CONFIG,
""
)
true true
} }

@ -7,7 +7,6 @@ import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Rational import android.util.Rational
import android.view.SurfaceView import android.view.SurfaceView
import kotlin.math.roundToInt
class FixedRatioSurfaceView @JvmOverloads constructor( class FixedRatioSurfaceView @JvmOverloads constructor(
context: Context, context: Context,
@ -22,27 +21,44 @@ class FixedRatioSurfaceView @JvmOverloads constructor(
*/ */
fun setAspectRatio(ratio: Rational?) { fun setAspectRatio(ratio: Rational?) {
aspectRatio = ratio?.toFloat() ?: 0f aspectRatio = ratio?.toFloat() ?: 0f
requestLayout()
} }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec) val displayWidth: Float = MeasureSpec.getSize(widthMeasureSpec).toFloat()
val width = MeasureSpec.getSize(widthMeasureSpec) val displayHeight: Float = MeasureSpec.getSize(heightMeasureSpec).toFloat()
val height = MeasureSpec.getSize(heightMeasureSpec)
if (aspectRatio != 0f) { if (aspectRatio != 0f) {
val newWidth: Int val displayAspect = displayWidth / displayHeight
val newHeight: Int if (displayAspect < aspectRatio) {
if (height * aspectRatio < width) { // Max out width
newWidth = (height * aspectRatio).roundToInt() val halfHeight = displayHeight / 2
newHeight = height val surfaceHeight = displayWidth / aspectRatio
val newTop: Float = halfHeight - (surfaceHeight / 2)
val newBottom: Float = halfHeight + (surfaceHeight / 2)
super.onMeasure(
widthMeasureSpec,
MeasureSpec.makeMeasureSpec(
newBottom.toInt() - newTop.toInt(),
MeasureSpec.EXACTLY
)
)
return
} else { } else {
newWidth = width // Max out height
newHeight = (width / aspectRatio).roundToInt() val halfWidth = displayWidth / 2
} val surfaceWidth = displayHeight * aspectRatio
val left = (width - newWidth) / 2 val newLeft: Float = halfWidth - (surfaceWidth / 2)
val top = (height - newHeight) / 2 val newRight: Float = halfWidth + (surfaceWidth / 2)
setLeftTopRightBottom(left, top, left + newWidth, top + newHeight) super.onMeasure(
} else { MeasureSpec.makeMeasureSpec(
setLeftTopRightBottom(0, 0, width, height) newRight.toInt() - newLeft.toInt(),
MeasureSpec.EXACTLY
),
heightMeasureSpec
)
return
} }
} }
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
} }