Skip to content

Commit

Permalink
Android: Implement About Game Dialog
Browse files Browse the repository at this point in the history
Co-Authored-By: OpenSauce <[email protected]>
  • Loading branch information
2 people authored and Gamer64ytb committed Jul 26, 2024
1 parent 702a332 commit 870b6b7
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 org.citra.citra_emu.HomeNavigationDirections
import org.citra.citra_emu.CitraApplication
import org.citra.citra_emu.R
Expand All @@ -32,8 +37,10 @@ import org.citra.citra_emu.features.cheats.ui.CheatsFragmentDirections
import org.citra.citra_emu.model.Game
import org.citra.citra_emu.utils.GameIconUtils
import org.citra.citra_emu.viewmodel.GamesViewModel
import org.citra.citra_emu.features.settings.ui.SettingsActivity
import org.citra.citra_emu.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
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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
}
Expand Down Expand Up @@ -143,20 +149,20 @@ class GameAdapter(private val activity: AppCompatActivity) :
binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP
GameIconUtils.loadGameIcon(activity, game, binding.imageGameScreen)

binding.textGameTitle.visibility = if (game.title.isEmpty()) {
binding.gameTitle.visibility = if (game.title.isEmpty()) {
View.GONE
} else {
View.VISIBLE
}
binding.textGameRegion.visibility = if (game.company.isEmpty()) {
binding.gameRegion.visibility = if (game.company.isEmpty()) {
View.GONE
} else {
View.VISIBLE
}

binding.textGameTitle.text = game.title
binding.textGameRegion.text = game.regions
binding.textFilename.text = game.filename
binding.gameTitle.text = game.title
binding.gameRegion.text = game.regions
binding.filename.text = game.filename

val backgroundColorId =
if (
Expand All @@ -173,22 +179,51 @@ class GameAdapter(private val activity: AppCompatActivity) :
)
)

binding.textGameTitle.postDelayed(
binding.gameTitle.postDelayed(
{
binding.textGameTitle.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.textGameTitle.isSelected = true
binding.gameTitle.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.gameTitle.isSelected = true

binding.textGameRegion.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.textGameRegion.isSelected = true
binding.gameRegion.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.gameRegion.isSelected = true

binding.textFilename.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.textFilename.isSelected = true
binding.filename.ellipsize = TextUtils.TruncateAt.MARQUEE
binding.filename.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_id).text = String.format("%016X", game.titleId)
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() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() }
Expand Down
12 changes: 6 additions & 6 deletions src/android/app/src/main/res/layout/card_game.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
app:layout_constraintTop_toTopOf="parent">

<TextView
android:id="@+id/text_game_title"
android:id="@+id/game_title"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand All @@ -49,10 +49,10 @@
android:marqueeRepeatLimit="marquee_forever"
android:ellipsize="none"
android:requiresFadingEdge="horizontal"
tools:text="The Legend of Zelda\nOcarina of Time 3D" />
tools:text="Detective Pikachu" />

<TextView
android:id="@+id/text_game_region"
android:id="@+id/game_region"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand All @@ -61,10 +61,10 @@
android:marqueeRepeatLimit="marquee_forever"
android:ellipsize="none"
android:requiresFadingEdge="horizontal"
tools:text="Europe" />
tools:text="Region free" />

<TextView
android:id="@+id/text_filename"
android:id="@+id/filename"
style="@style/TextAppearance.Material3.BodySmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Expand All @@ -73,7 +73,7 @@
android:marqueeRepeatLimit="marquee_forever"
android:ellipsize="none"
android:requiresFadingEdge="horizontal"
tools:text="Pilotwings_Resort.cxi" />
tools:text="Detective Pikachu (All) (C1) Decrypted.3ds" />

</LinearLayout>

Expand Down
126 changes: 126 additions & 0 deletions src/android/app/src/main/res/layout/dialog_about_game.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?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="Detective Pikachu" />

<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_title"
app:layout_constraintTop_toBottomOf="@id/about_game_title"
tools:text="Nintendo" />

<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_company"
app:layout_constraintTop_toBottomOf="@id/about_game_company"
tools:text="00040000001C1E00" />

</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>
5 changes: 4 additions & 1 deletion src/android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -451,10 +451,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>
Expand Down

0 comments on commit 870b6b7

Please sign in to comment.