mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-01-04 22:21:52 +01:00
android: Implemented about game dialog (#304)
This feature is accessible by long-pressing on a game card, replacing the old method of accessing the cheats menu
The cheats menu is now accessed from within the about game dialog
Adapted from 69c323289f
Co-authored-by: Ishan09811 <156402647+ishan09811@users.noreply.github.com>
Co-authored-by: kleidis <167202775+kleidis@users.noreply.github.com>
This commit is contained in:
parent
1c5ec87069
commit
a9dd78b8be
@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@ -10,6 +10,8 @@ import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.content.Context
|
||||
import android.widget.TextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@ -23,6 +25,9 @@ import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import io.github.lime3ds.android.HomeNavigationDirections
|
||||
import io.github.lime3ds.android.LimeApplication
|
||||
import io.github.lime3ds.android.R
|
||||
@ -32,8 +37,10 @@ import io.github.lime3ds.android.features.cheats.ui.CheatsFragmentDirections
|
||||
import io.github.lime3ds.android.model.Game
|
||||
import io.github.lime3ds.android.utils.GameIconUtils
|
||||
import io.github.lime3ds.android.viewmodel.GamesViewModel
|
||||
import io.github.lime3ds.android.features.settings.ui.SettingsActivity
|
||||
import io.github.lime3ds.android.features.settings.utils.SettingsFile
|
||||
|
||||
class GameAdapter(private val activity: AppCompatActivity) :
|
||||
class GameAdapter(private val activity: AppCompatActivity, private val inflater: LayoutInflater) :
|
||||
ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()),
|
||||
View.OnClickListener, View.OnLongClickListener {
|
||||
private var lastClickTime = 0L
|
||||
@ -83,7 +90,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the cheats settings for the game that was clicked on.
|
||||
* Opens the about game dialog for the game that was clicked on.
|
||||
*
|
||||
* @param view The view representing the game the user wants to play.
|
||||
*/
|
||||
@ -99,8 +106,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show()
|
||||
} else {
|
||||
val action = CheatsFragmentDirections.actionGlobalCheatsFragment(holder.game.titleId)
|
||||
view.findNavController().navigate(action)
|
||||
showAboutGameDialog(context, holder.game, holder, view)
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -156,7 +162,8 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
|
||||
binding.textGameTitle.text = game.title
|
||||
binding.textCompany.text = game.company
|
||||
binding.textFilename.text = game.filename
|
||||
binding.textGameRegion.text = game.regions
|
||||
|
||||
|
||||
val backgroundColorId =
|
||||
if (
|
||||
@ -181,14 +188,45 @@ class GameAdapter(private val activity: AppCompatActivity) :
|
||||
binding.textCompany.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||
binding.textCompany.isSelected = true
|
||||
|
||||
binding.textFilename.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||
binding.textFilename.isSelected = true
|
||||
binding.textGameRegion.ellipsize = TextUtils.TruncateAt.MARQUEE
|
||||
binding.textGameRegion.isSelected = true
|
||||
},
|
||||
3000
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showAboutGameDialog(context: Context, game: Game, holder: GameViewHolder, view: View) {
|
||||
val bottomSheetView = inflater.inflate(R.layout.dialog_about_game, null)
|
||||
|
||||
val bottomSheetDialog = BottomSheetDialog(context)
|
||||
bottomSheetDialog.setContentView(bottomSheetView)
|
||||
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_title).text = game.title
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_company).text = game.company
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_region).text = game.regions
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_id).text = "ID: " + String.format("%016X", game.titleId)
|
||||
bottomSheetView.findViewById<TextView>(R.id.about_game_filename).text = "File: " + game.filename
|
||||
GameIconUtils.loadGameIcon(activity, game, bottomSheetView.findViewById(R.id.game_icon))
|
||||
|
||||
bottomSheetView.findViewById<MaterialButton>(R.id.about_game_play).setOnClickListener {
|
||||
val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game)
|
||||
view.findNavController().navigate(action)
|
||||
}
|
||||
|
||||
bottomSheetView.findViewById<MaterialButton>(R.id.cheats).setOnClickListener {
|
||||
val action = CheatsFragmentDirections.actionGlobalCheatsFragment(holder.game.titleId)
|
||||
view.findNavController().navigate(action)
|
||||
bottomSheetDialog.dismiss()
|
||||
}
|
||||
|
||||
val bottomSheetBehavior = bottomSheetDialog.getBehavior()
|
||||
bottomSheetBehavior.skipCollapsed = true
|
||||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
|
||||
bottomSheetDialog.show()
|
||||
}
|
||||
|
||||
private fun isValidGame(extension: String): Boolean {
|
||||
return Game.badExtensions.stream()
|
||||
.noneMatch { extension == it.lowercase() }
|
||||
|
@ -60,13 +60,14 @@ class GamesFragment : Fragment() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
homeViewModel.setNavigationVisibility(visible = true, animated = true)
|
||||
homeViewModel.setStatusBarShadeVisibility(visible = true)
|
||||
val inflater = LayoutInflater.from(requireContext())
|
||||
|
||||
binding.gridGames.apply {
|
||||
layoutManager = GridLayoutManager(
|
||||
requireContext(),
|
||||
resources.getInteger(R.integer.game_grid_columns)
|
||||
)
|
||||
adapter = GameAdapter(requireActivity() as AppCompatActivity)
|
||||
adapter = GameAdapter(requireActivity() as AppCompatActivity, inflater)
|
||||
}
|
||||
|
||||
binding.swipeRefresh.apply {
|
||||
|
@ -71,12 +71,14 @@ class SearchFragment : Fragment() {
|
||||
binding.searchText.setText(savedInstanceState.getString(SEARCH_TEXT))
|
||||
}
|
||||
|
||||
val inflater = LayoutInflater.from(requireContext())
|
||||
|
||||
binding.gridGamesSearch.apply {
|
||||
layoutManager = GridLayoutManager(
|
||||
requireContext(),
|
||||
resources.getInteger(R.integer.game_grid_columns)
|
||||
)
|
||||
adapter = GameAdapter(requireActivity() as AppCompatActivity)
|
||||
adapter = GameAdapter(requireActivity() as AppCompatActivity, inflater)
|
||||
}
|
||||
|
||||
binding.chipGroup.setOnCheckedStateChangeListener { _, _ -> filterAndSearch() }
|
||||
|
@ -64,7 +64,7 @@
|
||||
tools:text="Nintendo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_filename"
|
||||
android:id="@+id/text_game_region"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -73,7 +73,7 @@
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:ellipsize="none"
|
||||
android:requiresFadingEdge="horizontal"
|
||||
tools:text="Pilotwings_Resort.cxi" />
|
||||
tools:text="Region" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
144
src/android/app/src/main/res/layout/dialog_about_game.xml
Normal file
144
src/android/app/src/main/res/layout/dialog_about_game.xml
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
|
||||
android:id="@+id/drag_handle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nextFocusRight="@id/about_game_play"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/game_icon"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:focusable="false"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/constraintLayout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/constraintLayout"
|
||||
app:shapeAppearance="?attr/shapeAppearanceCornerLarge" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/constraintLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHeight_min="140dp"
|
||||
app:layout_constraintStart_toEndOf="@id/game_icon"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_game_title"
|
||||
style="?attr/textAppearanceTitleMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Game Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_game_company"
|
||||
style="?attr/textAppearanceBodyMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="@id/about_game_filename"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_game_title"
|
||||
tools:text="Game Company" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_game_region"
|
||||
style="?attr/textAppearanceBodyMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="@id/about_game_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_game_company"
|
||||
tools:text="Game Region" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_game_id"
|
||||
style="?attr/textAppearanceBodyMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="@id/about_game_filename"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_game_region"
|
||||
tools:text="Game ID" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_game_filename"
|
||||
style="?attr/textAppearanceBodyMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="@id/about_game_title"
|
||||
app:layout_constraintTop_toBottomOf="@+id/about_game_id"
|
||||
tools:text="Game Filename" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/horizontal_layout"
|
||||
style="@style/ThemeOverlay.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="start|center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/game_icon">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/about_game_play"
|
||||
style="@style/Widget.Material3.Button.Icon"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
android:contentDescription="@string/play"
|
||||
android:focusedByDefault="true"
|
||||
android:text="@string/play"
|
||||
app:icon="@drawable/ic_play" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/game_button_tray"
|
||||
style="@style/ThemeOverlay.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="start|center"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/horizontal_layout">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cheats"
|
||||
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/cheats"
|
||||
android:text="@string/cheats" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
@ -432,10 +432,13 @@
|
||||
<string name="fatal_error">Fatal Error</string>
|
||||
<string name="fatal_error_message">A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs.</string>
|
||||
|
||||
<!-- Disk shader cache -->
|
||||
<!-- Disk Shader Cache -->
|
||||
<string name="preparing_shaders">Preparing Shaders</string>
|
||||
<string name="building_shaders">Building Shaders</string>
|
||||
|
||||
<!-- About Game Dialog -->
|
||||
<string name="play">Play</string>
|
||||
|
||||
<!-- Cheats -->
|
||||
<string name="cheats">Cheats</string>
|
||||
<string name="cheats_add">Add Cheat</string>
|
||||
|
Loading…
Reference in New Issue
Block a user