diff options
| author | Charles Lombardo <clombardo169@gmail.com> | 2023-03-20 00:21:52 -0400 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2023-06-03 00:05:44 -0700 | 
| commit | 72679c7baeb64c96bfa7423e41afe95a79d51bf5 (patch) | |
| tree | e554fa572f69786815475ad2a2d78b7ea6659f5b | |
| parent | e49e6cac7e890832500da1d371ca62eceea0c9a1 (diff) | |
android: Use view binding
16 files changed, 189 insertions, 284 deletions
| diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 44d002016..b222344c3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -8,11 +8,9 @@ import android.content.DialogInterface  import android.content.Intent  import android.graphics.Rect  import android.os.Bundle -import android.view.LayoutInflater  import android.view.MotionEvent  import android.view.View  import android.view.WindowManager -import android.widget.TextView  import androidx.activity.OnBackPressedCallback  import androidx.annotation.IntDef  import androidx.appcompat.app.AppCompatActivity @@ -21,10 +19,10 @@ import androidx.fragment.app.FragmentActivity  import androidx.fragment.app.FragmentManager  import androidx.preference.PreferenceManager  import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.slider.Slider  import com.google.android.material.slider.Slider.OnChangeListener  import org.yuzu.yuzu_emu.NativeLibrary  import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.DialogSliderBinding  import org.yuzu.yuzu_emu.features.settings.model.Settings  import org.yuzu.yuzu_emu.fragments.EmulationFragment  import org.yuzu.yuzu_emu.fragments.MenuFragment @@ -139,27 +137,22 @@ open class EmulationActivity : AppCompatActivity() {      }      private fun adjustScale() { -        val inflater = LayoutInflater.from(this) -        val view = inflater.inflate(R.layout.dialog_slider, null) -        val slider = view.findViewById<Slider>(R.id.slider) -        val textValue = view.findViewById<TextView>(R.id.text_value) -        val units = view.findViewById<TextView>(R.id.text_units) - -        slider.valueTo = 150F -        slider.value = PreferenceManager.getDefaultSharedPreferences(applicationContext) +        val sliderBinding = DialogSliderBinding.inflate(layoutInflater) +        sliderBinding.slider.valueTo = 150F +        sliderBinding.slider.value = PreferenceManager.getDefaultSharedPreferences(applicationContext)              .getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat() -        slider.addOnChangeListener(OnChangeListener { _, value, _ -> -            textValue.text = value.toString() +        sliderBinding.slider.addOnChangeListener(OnChangeListener { _, value, _ -> +            sliderBinding.textValue.text = value.toString()              setControlScale(value.toInt())          }) -        textValue.text = slider.value.toString() -        units.text = "%" +        sliderBinding.textValue.text = sliderBinding.slider.value.toString() +        sliderBinding.textUnits.text = "%"          MaterialAlertDialogBuilder(this)              .setTitle(R.string.emulation_control_scale) -            .setView(view) +            .setView(sliderBinding.root)              .setNegativeButton(android.R.string.cancel, null)              .setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> -                setControlScale(slider.value.toInt()) +                setControlScale(sliderBinding.slider.value.toInt())              }              .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->                  setControlScale(50) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index 8891705a5..4114f3fdc 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt @@ -24,6 +24,8 @@ import kotlinx.coroutines.withContext  import org.yuzu.yuzu_emu.NativeLibrary  import org.yuzu.yuzu_emu.R  import org.yuzu.yuzu_emu.activities.EmulationActivity.Companion.launch +import org.yuzu.yuzu_emu.databinding.CardGameBinding +import org.yuzu.yuzu_emu.model.Game  import org.yuzu.yuzu_emu.model.GameDatabase  import org.yuzu.yuzu_emu.utils.Log  import org.yuzu.yuzu_emu.viewholders.GameViewHolder @@ -51,25 +53,24 @@ class GameAdapter(private val activity: AppCompatActivity) : RecyclerView.Adapte      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder {          // Create a new view. -        val gameCard = LayoutInflater.from(parent.context) -            .inflate(R.layout.card_game, parent, false) -        gameCard.setOnClickListener(this) +        val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context)) +        binding.root.setOnClickListener(this)          // Use that view to create a ViewHolder. -        return GameViewHolder(gameCard) +        return GameViewHolder(binding)      }      override fun onBindViewHolder(holder: GameViewHolder, position: Int) {          if (isDatasetValid) {              if (cursor!!.moveToPosition(position)) { -                holder.imageIcon.scaleType = ImageView.ScaleType.CENTER_CROP +                holder.binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP                  activity.lifecycleScope.launch {                      withContext(Dispatchers.IO) {                          val uri =                              Uri.parse(cursor!!.getString(GameDatabase.GAME_COLUMN_PATH)).toString()                          val bitmap = decodeGameIcon(uri)                          withContext(Dispatchers.Main) { -                            holder.imageIcon.load(bitmap) { +                            holder.binding.imageGameScreen.load(bitmap) {                                  error(R.drawable.no_icon)                                  crossfade(true)                              } @@ -77,20 +78,23 @@ class GameAdapter(private val activity: AppCompatActivity) : RecyclerView.Adapte                      }                  } -                holder.textGameTitle.text = +                holder.binding.textGameTitle.text =                      cursor!!.getString(GameDatabase.GAME_COLUMN_TITLE)                          .replace("[\\t\\n\\r]+".toRegex(), " ") -                holder.textGameCaption.text = cursor!!.getString(GameDatabase.GAME_COLUMN_CAPTION) +                holder.binding.textGameCaption.text = cursor!!.getString(GameDatabase.GAME_COLUMN_CAPTION)                  // TODO These shouldn't be necessary once the move to a DB-based model is complete. -                holder.gameId = cursor!!.getString(GameDatabase.GAME_COLUMN_GAME_ID) -                holder.path = cursor!!.getString(GameDatabase.GAME_COLUMN_PATH) -                holder.title = cursor!!.getString(GameDatabase.GAME_COLUMN_TITLE) -                holder.description = cursor!!.getString(GameDatabase.GAME_COLUMN_DESCRIPTION) -                holder.regions = cursor!!.getString(GameDatabase.GAME_COLUMN_REGIONS) -                holder.company = cursor!!.getString(GameDatabase.GAME_COLUMN_CAPTION) +                val game = Game( +                    cursor!!.getString(GameDatabase.GAME_COLUMN_TITLE), +                    cursor!!.getString(GameDatabase.GAME_COLUMN_DESCRIPTION), +                    cursor!!.getString(GameDatabase.GAME_COLUMN_REGIONS), +                    cursor!!.getString(GameDatabase.GAME_COLUMN_PATH), +                    cursor!!.getString(GameDatabase.GAME_COLUMN_GAME_ID), +                    cursor!!.getString(GameDatabase.GAME_COLUMN_CAPTION) +                ) +                holder.game = game                  val backgroundColorId = -                    if (isValidGame(holder.path!!)) R.attr.colorSurface else R.attr.colorErrorContainer +                    if (isValidGame(holder.game.path)) R.attr.colorSurface else R.attr.colorErrorContainer                  val itemView = holder.itemView                  itemView.setBackgroundColor(                      MaterialColors.getColor( @@ -177,7 +181,7 @@ class GameAdapter(private val activity: AppCompatActivity) : RecyclerView.Adapte       */      override fun onClick(view: View) {          val holder = view.tag as GameViewHolder -        launch((view.context as FragmentActivity), holder.path, holder.title) +        launch((view.context as FragmentActivity), holder.game.path, holder.game.title)      }      private fun isValidGame(path: String): Boolean { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt index 1fa7b2e0b..fca2f2155 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt @@ -9,7 +9,6 @@ import android.content.IntentFilter  import android.os.Bundle  import android.view.Menu  import android.view.View -import android.widget.FrameLayout  import android.widget.Toast  import androidx.appcompat.app.AlertDialog  import androidx.appcompat.app.AppCompatActivity @@ -18,11 +17,11 @@ import androidx.core.view.WindowCompat  import androidx.core.view.WindowInsetsCompat  import androidx.core.view.updatePadding  import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.google.android.material.appbar.AppBarLayout  import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.progressindicator.LinearProgressIndicator  import org.yuzu.yuzu_emu.NativeLibrary  import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding +import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding  import org.yuzu.yuzu_emu.features.settings.model.Settings  import org.yuzu.yuzu_emu.features.settings.ui.SettingsFragment.Companion.newInstance  import org.yuzu.yuzu_emu.utils.* @@ -31,11 +30,15 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {      private val presenter = SettingsActivityPresenter(this)      private var dialog: AlertDialog? = null +    private lateinit var binding: ActivitySettingsBinding +      override fun onCreate(savedInstanceState: Bundle?) {          ThemeHelper.setTheme(this)          super.onCreate(savedInstanceState) -        setContentView(R.layout.activity_settings) + +        binding = ActivitySettingsBinding.inflate(layoutInflater) +        setContentView(binding.root)          WindowCompat.setDecorFitsSystemWindows(window, false) @@ -45,7 +48,7 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {          presenter.onCreate(savedInstanceState, menuTag!!, gameID!!)          // Show "Back" button in the action bar for navigation -        setSupportActionBar(findViewById(R.id.toolbar_settings)) +        setSupportActionBar(binding.toolbarSettings)          supportActionBar!!.setDisplayHomeAsUpEnabled(true)          setInsets() @@ -138,13 +141,12 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {      override fun showLoading() {          if (dialog == null) { -            val root = layoutInflater.inflate(R.layout.dialog_progress_bar, null) -            val progressBar = root.findViewById<LinearProgressIndicator>(R.id.progress_bar) -            progressBar.isIndeterminate = true +            val loadingBinding = DialogProgressBarBinding.inflate(layoutInflater) +            loadingBinding.progressBar.isIndeterminate = true              dialog = MaterialAlertDialogBuilder(this)                  .setTitle(R.string.load_settings) -                .setView(root) +                .setView(loadingBinding.root)                  .setCancelable(false)                  .create()          } @@ -195,12 +197,10 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {          get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?      private fun setInsets() { -        val appBar = findViewById<AppBarLayout>(R.id.appbar_settings) -        val frame = findViewById<FrameLayout>(R.id.frame_content) -        ViewCompat.setOnApplyWindowInsetsListener(frame) { view: View, windowInsets: WindowInsetsCompat -> +        ViewCompat.setOnApplyWindowInsetsListener(binding.frameContent) { view: View, windowInsets: WindowInsetsCompat ->              val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())              view.updatePadding(left = insets.left, right = insets.right) -            InsetsHelper.insetAppBar(insets, appBar) +            InsetsHelper.insetAppBar(insets, binding.appbarSettings)              windowInsets          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index 1b8a0a5ea..1f81f6e62 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt @@ -9,7 +9,6 @@ import android.icu.util.Calendar  import android.icu.util.TimeZone  import android.text.format.DateFormat  import android.view.LayoutInflater -import android.view.View  import android.view.ViewGroup  import android.widget.TextView  import androidx.appcompat.app.AlertDialog @@ -20,6 +19,10 @@ import com.google.android.material.slider.Slider  import com.google.android.material.timepicker.MaterialTimePicker  import com.google.android.material.timepicker.TimeFormat  import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.DialogSliderBinding +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding +import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding +import org.yuzu.yuzu_emu.databinding.ListItemSettingsHeaderBinding  import org.yuzu.yuzu_emu.features.settings.model.FloatSetting  import org.yuzu.yuzu_emu.features.settings.model.view.*  import org.yuzu.yuzu_emu.features.settings.ui.viewholder.* @@ -43,37 +46,29 @@ class SettingsAdapter(      }      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingViewHolder { -        val view: View          val inflater = LayoutInflater.from(parent.context)          return when (viewType) {              SettingsItem.TYPE_HEADER -> { -                view = inflater.inflate(R.layout.list_item_settings_header, parent, false) -                HeaderViewHolder(view, this) +                HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)              } -            SettingsItem.TYPE_CHECKBOX -> { -                view = inflater.inflate(R.layout.list_item_setting_switch, parent, false) -                SwitchSettingViewHolder(view, this) +            SettingsItem.TYPE_SWITCH -> { +                SwitchSettingViewHolder(ListItemSettingSwitchBinding.inflate(inflater), this)              }              SettingsItem.TYPE_SINGLE_CHOICE, SettingsItem.TYPE_STRING_SINGLE_CHOICE -> { -                view = inflater.inflate(R.layout.list_item_setting, parent, false) -                SingleChoiceViewHolder(view, this) +                SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)              }              SettingsItem.TYPE_SLIDER -> { -                view = inflater.inflate(R.layout.list_item_setting, parent, false) -                SliderViewHolder(view, this) +                SliderViewHolder(ListItemSettingBinding.inflate(inflater), this)              }              SettingsItem.TYPE_SUBMENU -> { -                view = inflater.inflate(R.layout.list_item_setting, parent, false) -                SubmenuViewHolder(view, this) +                SubmenuViewHolder(ListItemSettingBinding.inflate(inflater), this)              }              SettingsItem.TYPE_DATETIME_SETTING -> { -                view = inflater.inflate(R.layout.list_item_setting, parent, false) -                DateTimeViewHolder(view, this) +                DateTimeViewHolder(ListItemSettingBinding.inflate(inflater), this)              }              else -> {                  // TODO: Create an error view since we can't return null now -                view = inflater.inflate(R.layout.list_item_settings_header, parent, false) -                HeaderViewHolder(view, this) +                HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)              }          }      } @@ -191,15 +186,13 @@ class SettingsAdapter(          sliderProgress = item.selectedValue          val inflater = LayoutInflater.from(context) -        val sliderLayout = inflater.inflate(R.layout.dialog_slider, null) -        val sliderView = sliderLayout.findViewById<Slider>(R.id.slider) +        val sliderBinding = DialogSliderBinding.inflate(inflater) -        textSliderValue = sliderLayout.findViewById(R.id.text_value) +        textSliderValue = sliderBinding.textValue          textSliderValue!!.text = sliderProgress.toString() -        val units = sliderLayout.findViewById<TextView>(R.id.text_units) -        units.text = item.units +        sliderBinding.textUnits.text = item.units -        sliderView.apply { +        sliderBinding.slider.apply {              valueFrom = item.min.toFloat()              valueTo = item.max.toFloat()              value = sliderProgress.toFloat() @@ -211,11 +204,11 @@ class SettingsAdapter(          dialog = MaterialAlertDialogBuilder(context)              .setTitle(item.nameId) -            .setView(sliderLayout) +            .setView(sliderBinding.root)              .setPositiveButton(android.R.string.ok, this)              .setNegativeButton(android.R.string.cancel, defaultCancelListener)              .setNeutralButton(R.string.slider_default) { dialog: DialogInterface, which: Int -> -                sliderView.value = item.defaultValue.toFloat() +                sliderBinding.slider.value = item.defaultValue.toFloat()                  onClick(dialog, which)              }              .show() diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt index bef5b9705..e2e07ee8b 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragment.kt @@ -14,9 +14,8 @@ import androidx.core.view.updatePadding  import androidx.fragment.app.Fragment  import androidx.fragment.app.FragmentActivity  import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView  import com.google.android.material.divider.MaterialDividerItemDecoration -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.FragmentSettingsBinding  import org.yuzu.yuzu_emu.features.settings.model.Setting  import org.yuzu.yuzu_emu.features.settings.model.Settings  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem @@ -26,9 +25,10 @@ class SettingsFragment : Fragment(), SettingsFragmentView {      private val presenter = SettingsFragmentPresenter(this)      private var activityView: SettingsActivityView? = null -    private var adapter: SettingsAdapter? = null +    private var settingsAdapter: SettingsAdapter? = null -    private lateinit var recyclerView: RecyclerView +    private var _binding: FragmentSettingsBinding? = null +    private val binding get() = _binding!!      override fun onAttach(context: Context) {          super.onAttach(context) @@ -41,7 +41,6 @@ class SettingsFragment : Fragment(), SettingsFragmentView {          super.onCreate(savedInstanceState)          val menuTag = requireArguments().getString(ARGUMENT_MENU_TAG)          val gameId = requireArguments().getString(ARGUMENT_GAME_ID) -        adapter = SettingsAdapter(this, requireActivity())          presenter.onCreate(menuTag!!, gameId!!)      } @@ -49,18 +48,20 @@ class SettingsFragment : Fragment(), SettingsFragmentView {          inflater: LayoutInflater,          container: ViewGroup?,          savedInstanceState: Bundle? -    ): View? { -        return inflater.inflate(R.layout.fragment_settings, container, false) +    ): View { +        _binding = FragmentSettingsBinding.inflate(layoutInflater) +        return binding.root      }      override fun onViewCreated(view: View, savedInstanceState: Bundle?) { -        val manager = LinearLayoutManager(activity) -        recyclerView = view.findViewById(R.id.list_settings) -        recyclerView.adapter = adapter -        recyclerView.layoutManager = manager +        settingsAdapter = SettingsAdapter(this, requireActivity())          val dividerDecoration = MaterialDividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)          dividerDecoration.isLastItemDecorated = false -        recyclerView.addItemDecoration(dividerDecoration) +        binding.listSettings.apply { +            adapter = settingsAdapter +            layoutManager = LinearLayoutManager(activity) +            addItemDecoration(dividerDecoration) +        }          val activity = activity as SettingsActivityView?          presenter.onViewCreated(activity!!.settings) @@ -70,8 +71,8 @@ class SettingsFragment : Fragment(), SettingsFragmentView {      override fun onDetach() {          super.onDetach()          activityView = null -        if (adapter != null) { -            adapter!!.closeDialog() +        if (settingsAdapter != null) { +            settingsAdapter!!.closeDialog()          }      } @@ -86,7 +87,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {      }      override fun showSettingsList(settingsList: ArrayList<SettingsItem>) { -        adapter!!.setSettings(settingsList) +        settingsAdapter!!.setSettings(settingsList)      }      override fun loadDefaultSettings() { @@ -114,7 +115,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {      }      private fun setInsets() { -        ViewCompat.setOnApplyWindowInsetsListener(recyclerView) { view: View, windowInsets: WindowInsetsCompat -> +        ViewCompat.setOnApplyWindowInsetsListener(binding.listSettings) { view: View, windowInsets: WindowInsetsCompat ->              val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())              view.updatePadding(bottom = insets.bottom)              windowInsets diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt index ddbeb3487..5702fc0eb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt @@ -4,31 +4,23 @@  package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View -import android.widget.TextView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class DateTimeViewHolder(itemView: View, adapter: SettingsAdapter) : -    SettingViewHolder(itemView, adapter) { +class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      private lateinit var item: DateTimeSetting -    private lateinit var textSettingName: TextView -    private lateinit var textSettingDescription: TextView - -    override fun findViews(root: View) { -        textSettingName = root.findViewById(R.id.text_setting_name) -        textSettingDescription = root.findViewById(R.id.text_setting_description) -    }      override fun bind(item: SettingsItem) {          this.item = item as DateTimeSetting -        textSettingName.setText(item.nameId) +        binding.textSettingName.setText(item.nameId)          if (item.descriptionId!! > 0) { -            textSettingDescription.setText(item.descriptionId) -            textSettingDescription.visibility = View.VISIBLE +            binding.textSettingDescription.setText(item.descriptionId) +            binding.textSettingDescription.visibility = View.VISIBLE          } else { -            textSettingDescription.visibility = View.GONE +            binding.textSettingDescription.visibility = View.GONE          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt index dd186552a..1ac00dbfc 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt @@ -4,25 +4,19 @@  package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View -import android.widget.TextView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingsHeaderBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class HeaderViewHolder(itemView: View, adapter: SettingsAdapter) : -    SettingViewHolder(itemView, adapter) { -    private lateinit var headerName: TextView +class HeaderViewHolder(val binding: ListItemSettingsHeaderBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      init {          itemView.setOnClickListener(null)      } -    override fun findViews(root: View) { -        headerName = root.findViewById(R.id.text_header_name) -    } -      override fun bind(item: SettingsItem) { -        headerName.setText(item.nameId) +        binding.textHeaderName.setText(item.nameId)      }      override fun onClick(clicked: View) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SettingViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SettingViewHolder.kt index 6468af331..73375e757 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SettingViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SettingViewHolder.kt @@ -13,17 +13,9 @@ abstract class SettingViewHolder(itemView: View, protected val adapter: Settings      init {          itemView.setOnClickListener(this) -        findViews(itemView)      }      /** -     * Gets handles to all this ViewHolder's child views using their XML-defined identifiers. -     * -     * @param root The newly inflated top-level view. -     */ -    protected abstract fun findViews(root: View) - -    /**       * Called by the adapter to set this ViewHolder's child views to display the list item       * it must now represent.       * diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt index f6c8e3a7d..a82f49f44 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt @@ -4,40 +4,32 @@  package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View -import android.widget.TextView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class SingleChoiceViewHolder(itemView: View, adapter: SettingsAdapter) : -    SettingViewHolder(itemView, adapter) { +class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      private lateinit var item: SettingsItem -    private lateinit var textSettingName: TextView -    private lateinit var textSettingDescription: TextView - -    override fun findViews(root: View) { -        textSettingName = root.findViewById(R.id.text_setting_name) -        textSettingDescription = root.findViewById(R.id.text_setting_description) -    }      override fun bind(item: SettingsItem) {          this.item = item -        textSettingName.setText(item.nameId) -        textSettingDescription.visibility = View.VISIBLE +        binding.textSettingName.setText(item.nameId) +        binding.textSettingDescription.visibility = View.VISIBLE          if (item.descriptionId!! > 0) { -            textSettingDescription.setText(item.descriptionId) +            binding.textSettingDescription.setText(item.descriptionId)          } else if (item is SingleChoiceSetting) { -            val resMgr = textSettingDescription.context.resources +            val resMgr = binding.textSettingDescription.context.resources              val values = resMgr.getIntArray(item.valuesId)              for (i in values.indices) {                  if (values[i] == item.selectedValue) { -                    textSettingDescription.text = resMgr.getStringArray(item.choicesId)[i] +                    binding.textSettingDescription.text = resMgr.getStringArray(item.choicesId)[i]                  }              }          } else { -            textSettingDescription.visibility = View.GONE +            binding.textSettingDescription.visibility = View.GONE          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt index 2213f3c16..2d9fd11f9 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt @@ -4,30 +4,23 @@  package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View -import android.widget.TextView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class SliderViewHolder(itemView: View, adapter: SettingsAdapter) : SettingViewHolder(itemView, adapter) { +class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      private lateinit var item: SliderSetting -    private lateinit var textSettingName: TextView -    private lateinit var textSettingDescription: TextView - -    override fun findViews(root: View) { -        textSettingName = root.findViewById(R.id.text_setting_name) -        textSettingDescription = root.findViewById(R.id.text_setting_description) -    }      override fun bind(item: SettingsItem) {          this.item = item as SliderSetting -        textSettingName.setText(item.nameId) +        binding.textSettingName.setText(item.nameId)          if (item.descriptionId!! > 0) { -            textSettingDescription.setText(item.descriptionId) -            textSettingDescription.visibility = View.VISIBLE +            binding.textSettingDescription.setText(item.descriptionId) +            binding.textSettingDescription.visibility = View.VISIBLE          } else { -            textSettingDescription.visibility = View.GONE +            binding.textSettingDescription.visibility = View.GONE          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt index 75656215a..8125fd865 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt @@ -4,31 +4,23 @@  package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View -import android.widget.TextView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.model.view.SubmenuSetting  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class SubmenuViewHolder(itemView: View, adapter: SettingsAdapter) : -    SettingViewHolder(itemView, adapter) { +class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      private lateinit var item: SubmenuSetting -    private lateinit var textSettingName: TextView -    private lateinit var textSettingDescription: TextView - -    override fun findViews(root: View) { -        textSettingName = root.findViewById(R.id.text_setting_name) -        textSettingDescription = root.findViewById(R.id.text_setting_description) -    }      override fun bind(item: SettingsItem) {          this.item = item as SubmenuSetting -        textSettingName.setText(item.nameId) +        binding.textSettingName.setText(item.nameId)          if (item.descriptionId!! > 0) { -            textSettingDescription.setText(item.descriptionId) -            textSettingDescription.visibility = View.VISIBLE +            binding.textSettingDescription.setText(item.descriptionId) +            binding.textSettingDescription.visibility = View.VISIBLE          } else { -            textSettingDescription.visibility = View.GONE +            binding.textSettingDescription.visibility = View.GONE          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt index f8b229830..3fedb4969 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt @@ -5,43 +5,31 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder  import android.view.View  import android.widget.CompoundButton -import android.widget.TextView -import com.google.android.material.materialswitch.MaterialSwitch -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding  import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting  import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem  import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -class SwitchSettingViewHolder(itemView: View, adapter: SettingsAdapter) : -    SettingViewHolder(itemView, adapter) { -    private lateinit var item: SwitchSetting -    private lateinit var textSettingName: TextView -    private lateinit var textSettingDescription: TextView -    private lateinit var switch: MaterialSwitch - -    override fun findViews(root: View) { -        textSettingName = root.findViewById(R.id.text_setting_name) -        textSettingDescription = root.findViewById(R.id.text_setting_description) -        switch = root.findViewById(R.id.switch_widget) -    } +class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) : +    SettingViewHolder(binding.root, adapter) {      override fun bind(item: SettingsItem) { -        this.item = item as SwitchSetting -        textSettingName.setText(item.nameId) +        val setting = item as SwitchSetting +        binding.textSettingName.setText(item.nameId)          if (item.descriptionId!! > 0) { -            textSettingDescription.setText(item.descriptionId) -            textSettingDescription.visibility = View.VISIBLE +            binding.textSettingDescription.setText(item.descriptionId) +            binding.textSettingDescription.visibility = View.VISIBLE          } else { -            textSettingDescription.text = "" -            textSettingDescription.visibility = View.GONE +            binding.textSettingDescription.text = "" +            binding.textSettingDescription.visibility = View.GONE          } -        switch.isChecked = this.item.isChecked -        switch.setOnCheckedChangeListener { _: CompoundButton, _: Boolean -> -            adapter.onBooleanClick(item, bindingAdapterPosition, switch.isChecked) +        binding.switchWidget.isChecked = setting.isChecked +        binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean -> +            adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)          }      }      override fun onClick(clicked: View) { -        switch.toggle() +        binding.switchWidget.toggle()      }  } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index c75ad580e..37469302d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -10,8 +10,6 @@ import android.graphics.Color  import android.os.Bundle  import android.os.Handler  import android.view.* -import android.widget.Button -import android.widget.TextView  import android.widget.Toast  import androidx.fragment.app.Fragment  import androidx.localbroadcastmanager.content.LocalBroadcastManager @@ -20,8 +18,8 @@ import org.yuzu.yuzu_emu.NativeLibrary  import org.yuzu.yuzu_emu.R  import org.yuzu.yuzu_emu.YuzuApplication  import org.yuzu.yuzu_emu.activities.EmulationActivity +import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding  import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.overlay.InputOverlay  import org.yuzu.yuzu_emu.utils.DirectoryInitialization  import org.yuzu.yuzu_emu.utils.DirectoryInitialization.DirectoryInitializationState  import org.yuzu.yuzu_emu.utils.DirectoryStateReceiver @@ -29,13 +27,14 @@ import org.yuzu.yuzu_emu.utils.Log  class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.FrameCallback {      private lateinit var preferences: SharedPreferences -    private var inputOverlay: InputOverlay? = null      private lateinit var emulationState: EmulationState      private var directoryStateReceiver: DirectoryStateReceiver? = null      private var emulationActivity: EmulationActivity? = null -    private lateinit var perfStats: TextView      private var perfStatsUpdater: (() -> Unit)? = null +    private var _binding: FragmentEmulationBinding? = null +    private val binding get() = _binding!! +      override fun onAttach(context: Context) {          super.onAttach(context)          if (context is EmulationActivity) { @@ -66,22 +65,19 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram          inflater: LayoutInflater,          container: ViewGroup?,          savedInstanceState: Bundle? -    ): View? { -        val contents = inflater.inflate(R.layout.fragment_emulation, container, false) -        val surfaceView = contents.findViewById<SurfaceView>(R.id.surface_emulation) -        surfaceView.holder.addCallback(this) -        inputOverlay = contents.findViewById(R.id.surface_input_overlay) -        perfStats = contents.findViewById(R.id.show_fps_text) -        perfStats.setTextColor(Color.YELLOW) -        val doneButton = contents.findViewById<Button>(R.id.done_control_config) -        doneButton?.setOnClickListener { stopConfiguringControls() } +    ): View { +        _binding = FragmentEmulationBinding.inflate(layoutInflater) +        return binding.root +    } + +    override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +        binding.surfaceEmulation.holder.addCallback(this) +        binding.showFpsText.setTextColor(Color.YELLOW) +        binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }          // Setup overlay.          resetInputOverlay()          updateShowFpsOverlay() - -        // The new Surface created here will get passed to the native code via onSurfaceChanged. -        return contents      }      override fun onResume() { @@ -108,6 +104,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram          super.onPause()      } +    override fun onDestroyView() { +        super.onDestroyView() +        _binding = null +    } +      override fun onDetach() {          NativeLibrary.clearEmulationActivity()          super.onDetach() @@ -144,7 +145,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram      }      fun refreshInputOverlay() { -        inputOverlay!!.refreshControls() +        binding.surfaceInputOverlay.refreshControls()      }      fun resetInputOverlay() { @@ -152,7 +153,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram          preferences.edit()              .putInt(Settings.PREF_CONTROL_SCALE, 50)              .apply() -        inputOverlay!!.resetButtonPlacement() +        binding.surfaceInputOverlay.resetButtonPlacement()      }      private fun updateShowFpsOverlay() { @@ -165,17 +166,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram              perfStatsUpdater = {                  val perfStats = NativeLibrary.GetPerfStats()                  if (perfStats[FPS] > 0) { -                    this.perfStats.text = String.format("FPS: %.1f", perfStats[FPS]) +                    binding.showFpsText.text = String.format("FPS: %.1f", perfStats[FPS])                  }                  perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 100)              }              perfStatsUpdateHandler.post(perfStatsUpdater!!) -            perfStats.visibility = View.VISIBLE +            binding.showFpsText.visibility = View.VISIBLE          } else {              if (perfStatsUpdater != null) {                  perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)              } -            perfStats.visibility = View.GONE +            binding.showFpsText.visibility = View.GONE          }      } @@ -203,18 +204,17 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram      }      fun startConfiguringControls() { -        requireView().findViewById<View>(R.id.done_control_config).visibility = -            View.VISIBLE -        inputOverlay!!.setIsInEditMode(true) +        binding.doneControlConfig.visibility = View.VISIBLE +        binding.surfaceInputOverlay.setIsInEditMode(true)      }      fun stopConfiguringControls() { -        requireView().findViewById<View>(R.id.done_control_config).visibility = View.GONE -        inputOverlay!!.setIsInEditMode(false) +        binding.doneControlConfig.visibility = View.GONE +        binding.surfaceInputOverlay.setIsInEditMode(false)      }      val isConfiguringControls: Boolean -        get() = inputOverlay!!.isInEditMode +        get() = binding.surfaceInputOverlay.isInEditMode      private class EmulationState(private val mGamePath: String?) {          private var state: State diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index f87f13463..c5259a13d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -10,30 +10,29 @@ import android.os.Bundle  import android.view.Menu  import android.view.MenuItem  import android.view.View -import android.widget.FrameLayout  import android.widget.Toast  import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.Toolbar  import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen  import androidx.core.view.ViewCompat  import androidx.core.view.WindowCompat  import androidx.core.view.WindowInsetsCompat  import androidx.core.view.updatePadding -import com.google.android.material.appbar.AppBarLayout  import com.google.android.material.dialog.MaterialAlertDialogBuilder  import org.yuzu.yuzu_emu.NativeLibrary  import org.yuzu.yuzu_emu.R  import org.yuzu.yuzu_emu.activities.EmulationActivity +import org.yuzu.yuzu_emu.databinding.ActivityMainBinding  import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity  import org.yuzu.yuzu_emu.model.GameProvider  import org.yuzu.yuzu_emu.ui.platform.PlatformGamesFragment  import org.yuzu.yuzu_emu.utils.*  class MainActivity : AppCompatActivity(), MainView { -    private lateinit var toolbar: Toolbar      private var platformGamesFragment: PlatformGamesFragment? = null      private val presenter = MainPresenter(this) +    private lateinit var binding: ActivityMainBinding +      override fun onCreate(savedInstanceState: Bundle?) {          val splashScreen = installSplashScreen()          splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady() } @@ -41,12 +40,13 @@ class MainActivity : AppCompatActivity(), MainView {          ThemeHelper.setTheme(this)          super.onCreate(savedInstanceState) -        setContentView(R.layout.activity_main) + +        binding = ActivityMainBinding.inflate(layoutInflater) +        setContentView(binding.root)          WindowCompat.setDecorFitsSystemWindows(window, false) -        findViews() -        setSupportActionBar(toolbar) +        setSupportActionBar(binding.toolbarMain)          presenter.onCreate()          if (savedInstanceState == null) {              StartupHandler.handleInit(this) @@ -81,11 +81,6 @@ class MainActivity : AppCompatActivity(), MainView {          presenter.addDirIfNeeded(AddDirectoryHelper(this))      } -    // TODO: Replace with view binding -    private fun findViews() { -        toolbar = findViewById(R.id.toolbar_main) -    } -      override fun onCreateOptionsMenu(menu: Menu): Boolean {          menuInflater.inflate(R.menu.menu_game_grid, menu)          return true @@ -95,7 +90,7 @@ class MainActivity : AppCompatActivity(), MainView {       * MainView       */      override fun setVersionString(version: String) { -        toolbar.subtitle = version +        binding.toolbarMain.subtitle = version      }      override fun refresh() { @@ -247,12 +242,10 @@ class MainActivity : AppCompatActivity(), MainView {      }      private fun setInsets() { -        val appBar = findViewById<AppBarLayout>(R.id.appbar_main) -        val frame = findViewById<FrameLayout>(R.id.games_platform_frame) -        ViewCompat.setOnApplyWindowInsetsListener(frame) { view: View, windowInsets: WindowInsetsCompat -> +        ViewCompat.setOnApplyWindowInsetsListener(binding.gamesPlatformFrame) { view: View, windowInsets: WindowInsetsCompat ->              val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())              view.updatePadding(left = insets.left, right = insets.right) -            InsetsHelper.insetAppBar(insets, appBar) +            InsetsHelper.insetAppBar(insets, binding.appbarMain)              windowInsets          }      } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt index 40e902a37..775f4ed9e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/platform/PlatformGamesFragment.kt @@ -9,35 +9,33 @@ import android.view.LayoutInflater  import android.view.View  import android.view.ViewGroup  import android.view.ViewTreeObserver.OnGlobalLayoutListener -import android.widget.TextView  import androidx.appcompat.app.AppCompatActivity  import androidx.core.view.ViewCompat  import androidx.core.view.WindowInsetsCompat  import androidx.core.view.updatePadding  import androidx.fragment.app.Fragment  import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout  import com.google.android.material.color.MaterialColors  import org.yuzu.yuzu_emu.R  import org.yuzu.yuzu_emu.YuzuApplication  import org.yuzu.yuzu_emu.adapters.GameAdapter +import org.yuzu.yuzu_emu.databinding.FragmentGridBinding  class PlatformGamesFragment : Fragment(), PlatformGamesView {      private val presenter = PlatformGamesPresenter(this)      private var adapter: GameAdapter? = null -    private lateinit var recyclerView: RecyclerView -    private lateinit var textView: TextView + +    private var _binding: FragmentGridBinding? = null +    private val binding get() = _binding!!      override fun onCreateView(          inflater: LayoutInflater,          container: ViewGroup?,          savedInstanceState: Bundle? -    ): View? { -        val rootView = inflater.inflate(R.layout.fragment_grid, container, false) -        findViews(rootView) +    ): View {          presenter.onCreateView() -        return rootView +        _binding = FragmentGridBinding.inflate(inflater) +        return binding.root      }      override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -58,30 +56,34 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {                          }                          view.viewTreeObserver.removeOnGlobalLayoutListener(this)                          val layoutManager = GridLayoutManager(activity, columns) -                        recyclerView.layoutManager = layoutManager -                        recyclerView.adapter = adapter +                        binding.gridGames.layoutManager = layoutManager +                        binding.gridGames.adapter = adapter                      }                  })          }          // Add swipe down to refresh gesture -        val pullToRefresh = view.findViewById<SwipeRefreshLayout>(R.id.swipe_refresh) -        pullToRefresh.setOnRefreshListener { +        binding.swipeRefresh.setOnRefreshListener {              refresh() -            pullToRefresh.isRefreshing = false +            binding.swipeRefresh.isRefreshing = false          }          // Set theme color to the refresh animation's background -        pullToRefresh.setProgressBackgroundColorSchemeColor( -            MaterialColors.getColor(pullToRefresh, R.attr.colorPrimary) +        binding.swipeRefresh.setProgressBackgroundColorSchemeColor( +            MaterialColors.getColor(binding.swipeRefresh, R.attr.colorPrimary)          ) -        pullToRefresh.setColorSchemeColors( -            MaterialColors.getColor(pullToRefresh, R.attr.colorOnPrimary) +        binding.swipeRefresh.setColorSchemeColors( +            MaterialColors.getColor(binding.swipeRefresh, R.attr.colorOnPrimary)          )          setInsets()      } +    override fun onDestroyView() { +        super.onDestroyView() +        _binding = null +    } +      override fun refresh() {          val databaseHelper = YuzuApplication.databaseHelper          databaseHelper!!.scanLibrary(databaseHelper.writableDatabase) @@ -97,17 +99,12 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {      }      private fun updateTextView() { -        textView.visibility = +        binding.gamelistEmptyText.visibility =              if (adapter!!.itemCount == 0) View.VISIBLE else View.GONE      } -    private fun findViews(root: View) { -        recyclerView = root.findViewById(R.id.grid_games) -        textView = root.findViewById(R.id.gamelist_empty_text) -    } -      private fun setInsets() { -        ViewCompat.setOnApplyWindowInsetsListener(recyclerView) { view: View, windowInsets: WindowInsetsCompat -> +        ViewCompat.setOnApplyWindowInsetsListener(binding.gridGames) { view: View, windowInsets: WindowInsetsCompat ->              val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())              view.updatePadding(bottom = insets.bottom)              windowInsets diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholders/GameViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholders/GameViewHolder.kt index cef4e49d6..51420448f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholders/GameViewHolder.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/viewholders/GameViewHolder.kt @@ -3,33 +3,14 @@  package org.yuzu.yuzu_emu.viewholders -import android.view.View -import android.widget.ImageView -import android.widget.TextView  import androidx.recyclerview.widget.RecyclerView -import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.databinding.CardGameBinding +import org.yuzu.yuzu_emu.model.Game -/** - * A simple class that stores references to views so that the GameAdapter doesn't need to - * keep calling findViewById(), which is expensive. - */ -class GameViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { -    var imageIcon: ImageView -    var textGameTitle: TextView -    var textGameCaption: TextView -    var gameId: String? = null - -    // TODO Not need any of this stuff. Currently only the properties dialog needs it. -    var path: String? = null -    var title: String? = null -    var description: String? = null -    var regions: String? = null -    var company: String? = null +class GameViewHolder(val binding: CardGameBinding) : RecyclerView.ViewHolder(binding.root) { +    lateinit var game: Game      init {          itemView.tag = this -        imageIcon = itemView.findViewById(R.id.image_game_screen) -        textGameTitle = itemView.findViewById(R.id.text_game_title) -        textGameCaption = itemView.findViewById(R.id.text_game_caption)      }  } | 
