diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatItem.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatItem.kt index 55b13a5be5..a02cfa5ae3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatItem.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatItem.kt @@ -22,8 +22,8 @@ class CheatItem { } companion object { - const val TYPE_CHEAT = 0 - const val TYPE_HEADER = 1 + const val TYPE_HEADER = 0 + const val TYPE_CHEAT = 1 const val TYPE_ACTION = 2 } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatListFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatListFragment.kt index 093c8c3fbe..c5b7697de2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatListFragment.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatListFragment.kt @@ -13,11 +13,11 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.color.MaterialColors -import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.elevation.ElevationOverlayProvider import org.dolphinemu.dolphinemu.R import org.dolphinemu.dolphinemu.databinding.FragmentCheatListBinding import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel +import org.dolphinemu.dolphinemu.features.settings.ui.SettingsDividerItemDecoration class CheatListFragment : Fragment() { private var _binding: FragmentCheatListBinding? = null @@ -39,8 +39,7 @@ class CheatListFragment : Fragment() { binding.cheatList.adapter = CheatsAdapter(activity, viewModel) binding.cheatList.layoutManager = LinearLayoutManager(activity) - val divider = MaterialDividerItemDecoration(requireActivity(), LinearLayoutManager.VERTICAL) - divider.isLastItemDecorated = false + val divider = SettingsDividerItemDecoration(requireActivity()) binding.cheatList.addItemDecoration(divider) @ColorInt val color = diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsDividerItemDecoration.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsDividerItemDecoration.kt new file mode 100644 index 0000000000..571fc00a15 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsDividerItemDecoration.kt @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * Partially based on: MaterialDividerItemDecoration + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dolphinemu.dolphinemu.features.settings.ui + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.graphics.drawable.ShapeDrawable +import android.view.View +import androidx.annotation.Px +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.DrawableCompat +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.ItemDecoration +import org.dolphinemu.dolphinemu.R +import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem +import kotlin.math.max +import kotlin.math.roundToInt + +class SettingsDividerItemDecoration(context: Context) : ItemDecoration() { + private var dividerDrawable: Drawable + + @Px + private var dividerThickness: Int + + private val tempRect = Rect() + + init { + val attrs = context.obtainStyledAttributes(intArrayOf(R.attr.colorSurfaceVariant)) + val dividerColor = + attrs.getColor(0, ContextCompat.getColor(context, R.color.dolphin_surfaceVariant)) + attrs.recycle() + val shape = ShapeDrawable() + dividerThickness = max(context.resources.displayMetrics.density.roundToInt(), 1) + + dividerDrawable = DrawableCompat.wrap(shape) + DrawableCompat.setTint(dividerDrawable, dividerColor) + } + + private fun isNextViewAHeader(view: View, parent: RecyclerView): Boolean { + val index = parent.indexOfChild(view) + if (index == parent.childCount - 1) { + return false + } + + val nextChild = parent.getChildAt(index + 1) + val viewHolder = parent.getChildViewHolder(nextChild) + // CheatsItem.TYPE_HEADER == SettingsItem.TYPE_HEADER + return viewHolder.itemViewType == SettingsItem.TYPE_HEADER + } + + override fun onDraw( + canvas: Canvas, parent: RecyclerView, state: RecyclerView.State + ) { + if (parent.layoutManager == null) { + return + } + + canvas.save() + val left: Int + val right: Int + if (parent.clipToPadding) { + left = parent.paddingLeft + right = parent.width - parent.paddingRight + canvas.clipRect( + left, parent.paddingTop, right, parent.height - parent.paddingBottom + ) + } else { + left = 0 + right = parent.width + } + + val dividerCount = parent.childCount - 1 + for (i in 0 until dividerCount) { + val child = parent.getChildAt(i) + + if (!isNextViewAHeader(child, parent)) { + continue + } + + parent.getDecoratedBoundsWithMargins(child, tempRect) + // Take into consideration any translationY added to the view. + val bottom = tempRect.bottom + child.translationY.roundToInt() + val top = bottom - dividerDrawable.intrinsicHeight - dividerThickness + dividerDrawable.setBounds(left, top, right, bottom) + dividerDrawable.draw(canvas) + } + canvas.restore() + } + + override fun getItemOffsets( + outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State + ) { + if (!isNextViewAHeader(view, parent)) { + return + } + outRect.bottom = dividerDrawable.intrinsicHeight + dividerThickness + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java index 00699e3a0c..81c7321339 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java @@ -17,8 +17,6 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.material.divider.MaterialDividerItemDecoration; - import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding; import org.dolphinemu.dolphinemu.features.settings.model.Settings; @@ -146,9 +144,7 @@ public final class SettingsFragment extends Fragment implements SettingsFragment recyclerView.setAdapter(mAdapter); recyclerView.setLayoutManager(manager); - MaterialDividerItemDecoration divider = - new MaterialDividerItemDecoration(requireActivity(), LinearLayoutManager.VERTICAL); - divider.setLastItemDecorated(false); + SettingsDividerItemDecoration divider = new SettingsDividerItemDecoration(requireActivity()); recyclerView.addItemDecoration(divider); setInsets();