diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index 2786e6d7..e8a14a54 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -24,13 +24,9 @@ import androidx.core.view.size import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.chip.Chip import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint -import emu.skyline.adapter.AppViewItem -import emu.skyline.adapter.GenericAdapter -import emu.skyline.adapter.HeaderViewItem -import emu.skyline.adapter.LayoutType +import emu.skyline.adapter.* import emu.skyline.data.AppItem import emu.skyline.data.DataItem import emu.skyline.data.HeaderItem @@ -46,7 +42,7 @@ import kotlin.math.roundToInt @AndroidEntryPoint class MainActivity : AppCompatActivity() { companion object { - private val formatOrder = arrayOf(RomFormat.NSP, RomFormat.XCI, RomFormat.NRO, RomFormat.NSO, RomFormat.NCA) + private val formatOrder = listOf(RomFormat.NSP, RomFormat.XCI, RomFormat.NRO, RomFormat.NSO, RomFormat.NCA) } private val binding by lazy { MainActivityBinding.inflate(layoutInflater) } @@ -107,6 +103,18 @@ class MainActivity : AppCompatActivity() { PreferenceManager.setDefaultValues(this, R.xml.preferences, false) + adapter.apply { + setHeaderItems(listOf(HeaderRomFilterItem(formatOrder, if (settings.filter == 0) null else formatOrder[settings.filter - 1]) { romFormat -> + settings.filter = romFormat?.let { formatOrder.indexOf(romFormat) + 1 } ?: 0 + formatFilter = romFormat + populateAdapter() + })) + + setOnFilterPublishedListener { + binding.appList.post { binding.appList.smoothScrollToPosition(0) } + } + } + setupAppList() binding.swipeRefreshLayout.apply { @@ -116,21 +124,6 @@ class MainActivity : AppCompatActivity() { setOnRefreshListener { loadRoms(false) } } - for (format in formatOrder) { - binding.chipGroup.addView(Chip(this, null, R.attr.chipChoiceStyle).apply { text = format.name }) - } - binding.chipGroup.setOnCheckedChangeListener { group, checkedId -> - for (i in 0 until group.childCount) { - if (group.getChildAt(i).id == checkedId) { - settings.filter = i - formatFilter = if (i == 0) null else formatOrder[i - 1] - populateAdapter() - break - } - } - } - binding.chipGroup.check(binding.chipGroup.getChildAt(settings.filter).id) - viewModel.stateData.observe(this, ::handleState) loadRoms(!settings.refreshRequired) @@ -170,7 +163,10 @@ class MainActivity : AppCompatActivity() { } } - if (layoutParams.spanSize == gridLayoutManager.spanCount) outRect.right = padding + if (layoutParams.spanSize == gridLayoutManager.spanCount) { + outRect.left = 0 + outRect.right = 0 + } } } @@ -241,7 +237,7 @@ class MainActivity : AppCompatActivity() { private fun getDataItems() = mutableListOf().apply { appEntries?.let { entries -> - val formats = formatFilter?.let { arrayOf(it) } ?: formatOrder + val formats = formatFilter?.let { listOf(it) } ?: formatOrder for (format in formats) { entries[format]?.let { add(HeaderItem(format.name)) diff --git a/app/src/main/java/emu/skyline/RomProvider.kt b/app/src/main/java/emu/skyline/RomProvider.kt index 113092ef..b0b8ec59 100644 --- a/app/src/main/java/emu/skyline/RomProvider.kt +++ b/app/src/main/java/emu/skyline/RomProvider.kt @@ -1,5 +1,6 @@ package emu.skyline +import android.annotation.SuppressLint import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile @@ -16,12 +17,13 @@ class RomProvider @Inject constructor(@ApplicationContext private val context : /** * This adds all files in [directory] with [extension] as an entry using [RomFile] to load metadata */ + @SuppressLint("DefaultLocale") private fun addEntries(fileFormats : Map, directory : DocumentFile, entries : HashMap>) { directory.listFiles().forEach { file -> if (file.isDirectory) { addEntries(fileFormats, file, entries) } else { - fileFormats[file.name?.substringAfterLast(".")]?.let { romFormat -> + fileFormats[file.name?.substringAfterLast(".")?.toLowerCase()]?.let { romFormat-> entries.getOrPut(romFormat, { arrayListOf() }).add(RomFile(context, romFormat, file.uri).appEntry) } } @@ -29,8 +31,8 @@ class RomProvider @Inject constructor(@ApplicationContext private val context : } fun loadRoms(searchLocation : Uri) = DocumentFile.fromTreeUri(context, searchLocation)!!.let { documentFile -> - val entries = hashMapOf>() - addEntries(mapOf("nro" to NRO, "nso" to NSO, "nca" to NCA, "nsp" to NSP, "xci" to XCI), documentFile, entries) - entries + hashMapOf>().apply { + addEntries(mapOf("nro" to NRO, "nso" to NSO, "nca" to NCA, "nsp" to NSP, "xci" to XCI), documentFile, this) + } } } diff --git a/app/src/main/java/emu/skyline/adapter/AppViewItem.kt b/app/src/main/java/emu/skyline/adapter/AppViewItem.kt index 13533e4a..bc5fbc58 100644 --- a/app/src/main/java/emu/skyline/adapter/AppViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/AppViewItem.kt @@ -84,17 +84,17 @@ private typealias InteractionFunction = (appItem : AppItem) -> Unit class AppViewItem(var layoutType : LayoutType, private val item : AppItem, private val missingIcon : Bitmap, private val onClick : InteractionFunction, private val onLongClick : InteractionFunction) : GenericListItem>() { override fun getViewBindingFactory() = LayoutBindingFactory(layoutType) - override fun bind(holder : GenericViewHolder>, position : Int) { - holder.binding.textTitle.text = item.title - holder.binding.textSubtitle.text = item.subTitle ?: item.loaderResultString(holder.binding.root.context) + override fun bind(binding : LayoutBinding<*>, position : Int) { + binding.textTitle.text = item.title + binding.textSubtitle.text = item.subTitle ?: item.loaderResultString(binding.root.context) - holder.binding.icon.setImageBitmap(item.icon ?: missingIcon) + binding.icon.setImageBitmap(item.icon ?: missingIcon) if (layoutType == LayoutType.List) { - holder.binding.icon.setOnClickListener { showIconDialog(it.context, item) } + binding.icon.setOnClickListener { showIconDialog(it.context, item) } } - holder.itemView.findViewById(R.id.item_click_layout).apply { + binding.root.findViewById(R.id.item_click_layout).apply { setOnClickListener { onClick.invoke(item) } setOnLongClickListener { true.also { onLongClick.invoke(item) } } } diff --git a/app/src/main/java/emu/skyline/adapter/GenericAdapter.kt b/app/src/main/java/emu/skyline/adapter/GenericAdapter.kt index da5a7fb0..463ec610 100644 --- a/app/src/main/java/emu/skyline/adapter/GenericAdapter.kt +++ b/app/src/main/java/emu/skyline/adapter/GenericAdapter.kt @@ -16,6 +16,8 @@ import info.debatty.java.stringsimilarity.Cosine import info.debatty.java.stringsimilarity.JaroWinkler import java.util.* +typealias OnFilterPublishedListener = () -> Unit + /** * Can handle any view types with [GenericListItem] implemented, [GenericListItem] are differentiated by the return value of [GenericListItem.getViewBindingFactory] */ @@ -29,6 +31,7 @@ class GenericAdapter : RecyclerView.Adapter>(), F } private val asyncListDiffer = AsyncListDiffer(this, DIFFER) + private val headerItems = mutableListOf>() private val allItems = mutableListOf>() val currentItems : List> get() = asyncListDiffer.currentList @@ -36,12 +39,14 @@ class GenericAdapter : RecyclerView.Adapter>(), F private val viewTypesMapping = mutableMapOf() + private var onFilterPublishedListener : OnFilterPublishedListener? = null + override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) = GenericViewHolder(viewTypesMapping.filterValues { it == viewType }.keys.single().createBinding(parent)) override fun onBindViewHolder(holder : GenericViewHolder, position : Int) { currentItems[position].apply { adapter = this@GenericAdapter - bind(holder, position) + bind(holder.binding, position) } } @@ -49,12 +54,22 @@ class GenericAdapter : RecyclerView.Adapter>(), F override fun getItemViewType(position : Int) = viewTypesMapping.getOrPut(currentItems[position].getViewBindingFactory()) { viewTypesMapping.size } + fun setHeaderItems(items : List>) { + headerItems.clear() + headerItems.addAll(items) + filter.filter(currentSearchTerm) + } + fun setItems(items : List>) { allItems.clear() allItems.addAll(items) filter.filter(currentSearchTerm) } + fun setOnFilterPublishedListener(listener : OnFilterPublishedListener) { + onFilterPublishedListener = listener + } + /** * This returns an instance of the filter object which is used to search for items in the view */ @@ -84,13 +99,11 @@ class GenericAdapter : RecyclerView.Adapter>(), F /** * This performs filtering on the items in [allItems] based on similarity to [term] */ - override fun performFiltering(term : CharSequence) : FilterResults { - val results = FilterResults() - currentSearchTerm = (term as String).toLowerCase(Locale.getDefault()) + override fun performFiltering(term : CharSequence) = (term as String).toLowerCase(Locale.getDefault()).let { lowerCaseTerm -> + currentSearchTerm = lowerCaseTerm - if (term.isEmpty()) { - results.values = allItems.toMutableList() - results.count = allItems.size + with(if (term.isEmpty()) { + allItems.toMutableList() } else { val filterData = mutableListOf>() @@ -100,10 +113,13 @@ class GenericAdapter : RecyclerView.Adapter>(), F for (result in topResults) if (result.score >= avgScore) filterData.add(result.item) - results.values = filterData - results.count = filterData.size + filterData + }) { + FilterResults().apply { + values = headerItems + this@with + count = headerItems.size + size + } } - return results } /** @@ -112,6 +128,7 @@ class GenericAdapter : RecyclerView.Adapter>(), F override fun publishResults(charSequence : CharSequence, results : FilterResults) { @Suppress("UNCHECKED_CAST") asyncListDiffer.submitList(results.values as List>) + onFilterPublishedListener?.invoke() } } } \ No newline at end of file diff --git a/app/src/main/java/emu/skyline/adapter/GenericListItem.kt b/app/src/main/java/emu/skyline/adapter/GenericListItem.kt index d06a8b37..f1194449 100644 --- a/app/src/main/java/emu/skyline/adapter/GenericListItem.kt +++ b/app/src/main/java/emu/skyline/adapter/GenericListItem.kt @@ -24,7 +24,7 @@ abstract class GenericListItem { abstract fun getViewBindingFactory() : ViewBindingFactory - abstract fun bind(holder : GenericViewHolder, position : Int) + abstract fun bind(binding : V, position : Int) /** * Used for filtering @@ -33,10 +33,7 @@ abstract class GenericListItem { open fun areItemsTheSame(other : GenericListItem) = this == other - /** - * Will only be called when [areItemsTheSame] returns true, thus returning true by default - */ - open fun areContentsTheSame(other : GenericListItem) = true + open fun areContentsTheSame(other : GenericListItem) = this == other open val fullSpan : Boolean = false } diff --git a/app/src/main/java/emu/skyline/adapter/HeaderRomFilterItem.kt b/app/src/main/java/emu/skyline/adapter/HeaderRomFilterItem.kt new file mode 100644 index 00000000..91970370 --- /dev/null +++ b/app/src/main/java/emu/skyline/adapter/HeaderRomFilterItem.kt @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: MPL-2.0 + * Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + */ + +package emu.skyline.adapter + +import android.view.ViewGroup +import com.google.android.material.chip.Chip +import emu.skyline.R +import emu.skyline.databinding.HeaderRomFilterBinding +import emu.skyline.loader.RomFormat + +object HeaderRomFilterBindingFactory : ViewBindingFactory { + override fun createBinding(parent : ViewGroup) = HeaderRomFilterBinding.inflate(parent.inflater(), parent, false) +} + +typealias OnFilterClickedListener = (format : RomFormat?) -> Unit + +class HeaderRomFilterItem(private val formats : List, selectedFormat : RomFormat?, private val onFilterClickedListener : OnFilterClickedListener) : GenericListItem() { + private var selection = selectedFormat?.let { formats.indexOf(it) + 1 } ?: 0 + + override fun getViewBindingFactory() = HeaderRomFilterBindingFactory + + override fun bind(binding : HeaderRomFilterBinding, position : Int) { + binding.chipGroup.removeViews(1, binding.chipGroup.childCount - 1) + for (format in formats) { + binding.chipGroup.addView(Chip(binding.root.context, null, R.attr.chipChoiceStyle).apply { text = format.name }) + } + binding.chipGroup.setOnCheckedChangeListener { group, checkedId -> + for (i in 0 until group.childCount) { + if (group.getChildAt(i).id == checkedId) { + selection = i + onFilterClickedListener(if (i == 0) null else formats[i - 1]) + break + } + } + } + binding.chipGroup.check(binding.chipGroup.getChildAt(selection).id) + } + + override val fullSpan = true +} diff --git a/app/src/main/java/emu/skyline/adapter/HeaderViewItem.kt b/app/src/main/java/emu/skyline/adapter/HeaderViewItem.kt index 8a625837..b97fc2bb 100644 --- a/app/src/main/java/emu/skyline/adapter/HeaderViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/HeaderViewItem.kt @@ -15,8 +15,8 @@ object HeaderBindingFactory : ViewBindingFactory { class HeaderViewItem(private val text : String) : GenericListItem() { override fun getViewBindingFactory() = HeaderBindingFactory - override fun bind(holder : GenericViewHolder, position : Int) { - holder.binding.textTitle.text = text + override fun bind(binding : SectionItemBinding, position : Int) { + binding.textTitle.text = text } override fun toString() = "" diff --git a/app/src/main/java/emu/skyline/adapter/LogViewItem.kt b/app/src/main/java/emu/skyline/adapter/LogViewItem.kt index 55abdb55..86217728 100644 --- a/app/src/main/java/emu/skyline/adapter/LogViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/LogViewItem.kt @@ -47,11 +47,11 @@ class LogBinding(parent : ViewGroup) : ILogBinding { data class LogViewItem(private val compact : Boolean, private val message : String, private val level : String) : GenericListItem() { override fun getViewBindingFactory() = LogBindingFactory(compact) - override fun bind(holder : GenericViewHolder, position : Int) { - holder.binding.textTitle.text = message - holder.binding.textSubTitle?.text = level + override fun bind(binding : ILogBinding, position : Int) { + binding.textTitle.text = message + binding.textSubTitle?.text = level - holder.binding.root.setOnClickListener { + binding.root.setOnClickListener { it.context.getSystemService(ClipboardManager::class.java).setPrimaryClip(ClipData.newPlainText("Log Message", "$message ($level)")) Toast.makeText(it.context, "Copied to clipboard", Toast.LENGTH_LONG).show() } diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerButtonViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerButtonViewItem.kt index 3524e56b..26e50e06 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerButtonViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerButtonViewItem.kt @@ -6,7 +6,6 @@ package emu.skyline.adapter.controller import emu.skyline.adapter.GenericListItem -import emu.skyline.adapter.GenericViewHolder import emu.skyline.databinding.ControllerItemBinding import emu.skyline.di.getInputManager import emu.skyline.input.ButtonGuestEvent @@ -16,14 +15,14 @@ import emu.skyline.input.ButtonId * This item is used to display a particular [button] mapping for the controller */ class ControllerButtonViewItem(private val controllerId : Int, val button : ButtonId, private val onClick : (item : ControllerButtonViewItem, position : Int) -> Unit) : ControllerViewItem() { - override fun bind(holder : GenericViewHolder, position : Int) { - content = button.long?.let { holder.itemView.context.getString(it) } ?: button.toString() + override fun bind(binding : ControllerItemBinding, position : Int) { + content = button.long?.let { binding.root.context.getString(it) } ?: button.toString() val guestEvent = ButtonGuestEvent(controllerId, button) - subContent = holder.binding.root.context.getInputManager().eventMap.filter { it.value is ButtonGuestEvent && it.value == guestEvent }.keys.firstOrNull()?.toString() ?: "" + subContent = binding.root.context.getInputManager().eventMap.filter { it.value is ButtonGuestEvent && it.value == guestEvent }.keys.firstOrNull()?.toString() ?: "" - super.bind(holder, position) + super.bind(binding, position) - holder.binding.root.setOnClickListener { onClick.invoke(this, position) } + binding.root.setOnClickListener { onClick.invoke(this, position) } } override fun areItemsTheSame(other : GenericListItem) = other is ControllerButtonViewItem && controllerId == other.controllerId diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerCheckBoxViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerCheckBoxViewItem.kt index 58a1ab61..f3d2d957 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerCheckBoxViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerCheckBoxViewItem.kt @@ -20,13 +20,13 @@ object ControllerCheckBoxBindingFactory : ViewBindingFactory { class ControllerCheckBoxViewItem(var title : String, var summary : String, var checked : Boolean, private val onCheckedChange : (item : ControllerCheckBoxViewItem, position : Int) -> Unit) : GenericListItem() { override fun getViewBindingFactory() = ControllerCheckBoxBindingFactory - override fun bind(holder : GenericViewHolder, position : Int) { - holder.binding.textTitle.isGone = title.isEmpty() - holder.binding.textTitle.text = title - holder.binding.textSubtitle.isGone = summary.isEmpty() - holder.binding.textSubtitle.text = summary - holder.binding.checkbox.isChecked = checked - holder.itemView.setOnClickListener { + override fun bind(binding : ControllerCheckboxItemBinding, position : Int) { + binding.textTitle.isGone = title.isEmpty() + binding.textTitle.text = title + binding.textSubtitle.isGone = summary.isEmpty() + binding.textSubtitle.text = summary + binding.checkbox.isChecked = checked + binding.root.setOnClickListener { checked = !checked onCheckedChange.invoke(this, position) } diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerGeneralViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerGeneralViewItem.kt index 08c83144..2bfa1aff 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerGeneralViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerGeneralViewItem.kt @@ -19,8 +19,8 @@ import emu.skyline.input.JoyConLeftController * @param type The type of controller setting this item is displaying */ class ControllerGeneralViewItem(private val controllerId : Int, val type : GeneralType, private val onClick : (item : ControllerGeneralViewItem, position : Int) -> Unit) : ControllerViewItem() { - override fun bind(holder : GenericViewHolder, position : Int) { - val context = holder.itemView.context + override fun bind(binding : ControllerItemBinding, position : Int) { + val context = binding.root.context val controller = context.getInputManager().controllers[controllerId]!! content = context.getString(type.stringRes) @@ -36,9 +36,9 @@ class ControllerGeneralViewItem(private val controllerId : Int, val type : Gener GeneralType.RumbleDevice -> controller.rumbleDeviceName ?: context.getString(R.string.none) } - super.bind(holder, position) + super.bind(binding, position) - holder.binding.root.setOnClickListener { onClick.invoke(this, position) } + binding.root.setOnClickListener { onClick.invoke(this, position) } } override fun areItemsTheSame(other : GenericListItem) = other is ControllerGeneralViewItem && controllerId == other.controllerId diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt index f8572642..a854d901 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerHeaderItem.kt @@ -2,7 +2,6 @@ package emu.skyline.adapter.controller import android.view.ViewGroup import emu.skyline.adapter.GenericListItem -import emu.skyline.adapter.GenericViewHolder import emu.skyline.adapter.ViewBindingFactory import emu.skyline.adapter.inflater import emu.skyline.databinding.ControllerHeaderBinding @@ -14,8 +13,8 @@ object ControllerHeaderBindingFactory : ViewBindingFactory { class ControllerHeaderItem(private val text : String) : GenericListItem() { override fun getViewBindingFactory() = ControllerHeaderBindingFactory - override fun bind(holder : GenericViewHolder, position : Int) { - holder.binding.root.text = text + override fun bind(binding : ControllerHeaderBinding, position : Int) { + binding.root.text = text } override fun areItemsTheSame(other : GenericListItem) = other is ControllerHeaderItem diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerStickViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerStickViewItem.kt index 67638742..d77edd87 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerStickViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerStickViewItem.kt @@ -18,8 +18,8 @@ import emu.skyline.input.StickId * This item is used to display all information regarding a [stick] and it's mappings for the controller */ class ControllerStickViewItem(private val controllerId : Int, val stick : StickId, private val onClick : (item : ControllerStickViewItem, position : Int) -> Unit) : ControllerViewItem(stick.toString()) { - override fun bind(holder : GenericViewHolder, position : Int) { - val context = holder.itemView.context + override fun bind(binding : ControllerItemBinding, position : Int) { + val context = binding.root.context val inputManager = context.getInputManager() val buttonGuestEvent = ButtonGuestEvent(controllerId, stick.button) @@ -39,9 +39,9 @@ class ControllerStickViewItem(private val controllerId : Int, val stick : StickI subContent = "${context.getString(R.string.button)}: $button\n${context.getString(R.string.up)}: $yAxisPlus\n${context.getString(R.string.down)}: $yAxisMinus\n${context.getString(R.string.left)}: $xAxisMinus\n${context.getString(R.string.right)}: $xAxisPlus" - super.bind(holder, position) + super.bind(binding, position) - holder.binding.root.setOnClickListener { onClick.invoke(this, position) } + binding.root.setOnClickListener { onClick.invoke(this, position) } } override fun areItemsTheSame(other : GenericListItem) = other is ControllerStickViewItem && controllerId == other.controllerId diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerTypeViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerTypeViewItem.kt index ca0b2f2c..ac8f2767 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerTypeViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerTypeViewItem.kt @@ -15,15 +15,15 @@ import emu.skyline.input.ControllerType * This item is used to display the [type] of the currently active controller */ class ControllerTypeViewItem(private val type : ControllerType, private val onClick : (item : ControllerTypeViewItem, position : Int) -> Unit) : ControllerViewItem() { - override fun bind(holder : GenericViewHolder, position : Int) { - val context = holder.itemView.context + override fun bind(binding : ControllerItemBinding, position : Int) { + val context = binding.root.context content = context.getString(R.string.controller_type) subContent = context.getString(type.stringRes) - super.bind(holder, position) + super.bind(binding, position) - holder.itemView.setOnClickListener { onClick.invoke(this, position) } + binding.root.setOnClickListener { onClick.invoke(this, position) } } override fun areItemsTheSame(other : GenericListItem) = other is ControllerTypeViewItem diff --git a/app/src/main/java/emu/skyline/adapter/controller/ControllerViewItem.kt b/app/src/main/java/emu/skyline/adapter/controller/ControllerViewItem.kt index 6b0fd15d..6fc0909c 100644 --- a/app/src/main/java/emu/skyline/adapter/controller/ControllerViewItem.kt +++ b/app/src/main/java/emu/skyline/adapter/controller/ControllerViewItem.kt @@ -23,17 +23,17 @@ open class ControllerViewItem(var content : String = "", var subContent : String override fun getViewBindingFactory() = ControllerBindingFactory - override fun bind(holder : GenericViewHolder, position : Int) { + override fun bind(binding : ControllerItemBinding, position : Int) { this.position = position - holder.binding.textTitle.apply { + binding.textTitle.apply { isGone = content.isEmpty() text = content } - holder.binding.textSubtitle.apply { + binding.textSubtitle.apply { isGone = subContent.isEmpty() text = subContent } - onClick?.let { onClick -> holder.itemView.setOnClickListener { onClick.invoke() } } + onClick?.let { onClick -> binding.root.setOnClickListener { onClick.invoke() } } } fun update() = adapter?.notifyItemChanged(position) diff --git a/app/src/main/res/layout/app_item_grid.xml b/app/src/main/res/layout/app_item_grid.xml index ed070214..c5c86d80 100644 --- a/app/src/main/res/layout/app_item_grid.xml +++ b/app/src/main/res/layout/app_item_grid.xml @@ -11,10 +11,10 @@ android:id="@+id/item_click_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="14dp" - android:layout_marginTop="14dp" - android:layout_marginEnd="14dp" - android:layout_marginBottom="14dp" + android:layout_marginStart="10dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="10dp" + android:layout_marginBottom="10dp" app:cardCornerRadius="16dp" app:cardElevation="2dp"> @@ -31,8 +31,8 @@ android:id="@+id/text_title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="20dp" - android:layout_marginEnd="20dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" @@ -44,9 +44,9 @@ android:id="@+id/text_subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="20dp" - android:layout_marginEnd="20dp" - android:layout_marginBottom="16dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp" + android:layout_marginBottom="10dp" android:ellipsize="marquee" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" diff --git a/app/src/main/res/layout/app_item_grid_compact.xml b/app/src/main/res/layout/app_item_grid_compact.xml index 754d4ecc..8a823407 100644 --- a/app/src/main/res/layout/app_item_grid_compact.xml +++ b/app/src/main/res/layout/app_item_grid_compact.xml @@ -1,70 +1,70 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/item_click_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="10dp" + android:layout_marginBottom="10dp" + app:cardCornerRadius="16dp" + app:cardElevation="2dp"> + android:layout_width="match_parent" + android:layout_height="wrap_content"> + android:id="@+id/icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:contentDescription="@string/icon" + android:foreground="@drawable/background_gradient" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:src="@drawable/default_icon" /> + android:id="@+id/text_title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:alpha="242.25" + android:ellipsize="marquee" + android:marqueeRepeatLimit="marquee_forever" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItem" + android:textColor="@android:color/white" + android:textStyle="bold" + app:layout_constrainedWidth="true" + app:layout_constraintBottom_toTopOf="@id/text_subtitle" + app:layout_constraintEnd_toEndOf="@id/icon" + app:layout_constraintStart_toStartOf="@id/icon" + tools:text="Title" /> + android:id="@+id/text_subtitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:alpha="242.25" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:marqueeRepeatLimit="marquee_forever" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceListItemSecondary" + android:textColor="@android:color/white" + app:layout_constraintBottom_toBottomOf="@id/icon" + app:layout_constraintEnd_toEndOf="@id/icon" + app:layout_constraintStart_toStartOf="@id/icon" + tools:text="Subtitle" /> diff --git a/app/src/main/res/layout/app_item_linear.xml b/app/src/main/res/layout/app_item_linear.xml index 7ba8089d..7fbf68a7 100644 --- a/app/src/main/res/layout/app_item_linear.xml +++ b/app/src/main/res/layout/app_item_linear.xml @@ -12,8 +12,8 @@ + + + + + + + diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml index 58ce0db2..598e0134 100644 --- a/app/src/main/res/layout/main_activity.xml +++ b/app/src/main/res/layout/main_activity.xml @@ -79,9 +79,9 @@ android:id="@+id/title_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="18dp" + android:layout_marginStart="16dp" android:layout_marginTop="16dp" - android:layout_marginEnd="18dp" + android:layout_marginEnd="16dp" android:fontFamily="sans-serif-medium" android:text="@string/app_name" android:textColor="?android:attr/textColorPrimary" @@ -94,8 +94,8 @@ android:id="@+id/sub_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="18dp" - android:layout_marginEnd="18dp" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" android:fontFamily="sans-serif-medium" android:letterSpacing="0.1" android:text="@string/emulator" @@ -108,9 +108,9 @@ android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="64dp" - android:layout_marginStart="12dp" + android:layout_marginStart="10dp" android:layout_marginTop="16dp" - android:layout_marginEnd="12dp" + android:layout_marginEnd="10dp" app:cardCornerRadius="16dp" app:cardElevation="2dp" app:layout_constraintTop_toBottomOf="@id/sub_text" /> @@ -125,44 +125,11 @@ android:layout_marginTop="-8dp" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - - - - - - - - - - + android:clipToPadding="false" + android:overScrollMode="never" />