ui: update transitions

Update transitions in the home fragment to X-axis.

I noticed a visual issue in the detail transition in the existing
version stemming from how the main fragment's drawing is clipped by
the bottom sheet, resulting in a less-than-ideal Z-axis transition.

While I wanted to fix this by attempting to switch to inset based
bottom sheet management, I still need to wait for more changes in
order to successfully pull that off, and hence I'll be reverting it
soon.

Moving these transitions to X-axis prevents this visual issue while
still being roughly semantically similar.
This commit is contained in:
OxygenCobalt 2022-08-08 16:09:17 -06:00
parent 0cef51fa97
commit 46473ceff9
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
18 changed files with 67 additions and 40 deletions

View file

@ -2,8 +2,8 @@
## dev
#### What's Improved
- Improved bottom sheet code to prevent clipping issues
#### What's Changed
- Use X-axis transitions instead of Z-axis (Avoids visual clipping)
#### What's Fixed
- Fixed incorrect font being used in the queue title

View file

@ -44,6 +44,8 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
*
* TODO: Add multi-select
*
* TODO: Remove asterisk imports
*
* @author OxygenCobalt
*/
class MainActivity : AppCompatActivity() {

View file

@ -68,10 +68,10 @@ class AlbumDetailFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)

View file

@ -63,10 +63,10 @@ class ArtistDetailFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)

View file

@ -64,10 +64,10 @@ class GenreDetailFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)

View file

@ -39,6 +39,7 @@ import com.google.android.material.tabs.TabLayoutMediator
import com.google.android.material.transition.MaterialSharedAxis
import java.lang.reflect.Field
import kotlin.math.abs
import org.oxycblt.auxio.BuildConfig
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentHomeBinding
import org.oxycblt.auxio.home.list.AlbumListFragment
@ -79,10 +80,17 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
if (savedInstanceState != null) {
// Orientation change will wipe whatever transition we were using prior, which will
// result in no transition when the user navigates back. Make sure we re-initialize
// our transitions.
if (savedInstanceState.getBoolean(KEY_INIT_WITH_SEARCH_TRANSITIONS)) {
initSearchTransitions()
} else {
initDetailTransitions()
}
}
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentHomeBinding.inflate(inflater)
@ -144,6 +152,11 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
collect(navModel.exploreNavigationItem, ::handleNavigation)
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(KEY_INIT_WITH_SEARCH_TRANSITIONS, enterTransition is MaterialSharedAxis)
super.onSaveInstanceState(outState)
}
override fun onDestroyBinding(binding: FragmentHomeBinding) {
super.onDestroyBinding(binding)
binding.homeToolbar.setOnMenuItemClickListener(null)
@ -153,6 +166,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
when (item.itemId) {
R.id.action_search -> {
logD("Navigating to search")
initSearchTransitions()
findNavController().navigate(HomeFragmentDirections.actionShowSearch())
}
R.id.action_settings -> {
@ -364,9 +378,25 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
else -> return
}
initDetailTransitions()
findNavController().navigate(action)
}
private fun initSearchTransitions() {
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
}
private fun initDetailTransitions() {
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
/**
* By default, ViewPager2's sensitivity is high enough to result in vertical scroll events being
* registered as horizontal scroll events. Reflect into the internal recyclerview and change the
@ -405,5 +435,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
lazyReflectedField(ViewPager2::class, "mRecyclerView")
private val VIEW_PAGER_TOUCH_SLOP_FIELD: Field by
lazyReflectedField(RecyclerView::class, "mTouchSlop")
private const val KEY_INIT_WITH_SEARCH_TRANSITIONS =
BuildConfig.APPLICATION_ID + ".key.INIT_WITH_SEARCH_TRANSITIONS"
}
}

View file

@ -55,9 +55,6 @@ class PlaybackSheetBehavior<V : View>(context: Context, attributeSet: AttributeS
init {
isHideable = true
if (Settings(context).roundMode) {
sheetBackgroundDrawable.setCornerSize(context.getDimen(R.dimen.size_corners_medium))
}
}
// Hack around issue where the playback sheet will try to intercept nested scrolling events

View file

@ -28,7 +28,6 @@ import androidx.core.view.postDelayed
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentSearchBinding
@ -70,10 +69,10 @@ class SearchFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
returnTransition = MaterialFadeThrough()
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateBinding(inflater: LayoutInflater) = FragmentSearchBinding.inflate(inflater)

View file

@ -63,11 +63,7 @@ class Settings(private val context: Context, private val callback: Callback? = n
unlikelyToBeNull(callback).onSettingChanged(key)
}
/**
* An interface for receiving some preference updates. Use/Extend this instead of
* [SharedPreferences.OnSharedPreferenceChangeListener] if possible, as it doesn't require a
* context.
*/
/** An interface for receiving some preference updates. */
interface Callback {
fun onSettingChanged(key: String)
}

View file

@ -27,11 +27,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.util.systemBarInsetsCompat
/**
* A [RecyclerView] that automatically applies insets to itself.
*
* TODO: Correctly handle edge-to-edge regarding scroll effects and saved scroll positions.
*/
/** A [RecyclerView] that enables some extra functionality for Auxio's use-case. */
open class AuxioRecyclerView
@JvmOverloads
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
@ -58,12 +54,12 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
return insets
}
fun setSpanSizeLookup(lookup: (Int) -> Boolean) {
inline fun setSpanSizeLookup(crossinline fullWidth: (Int) -> Boolean) {
val glm = layoutManager as GridLayoutManager
val spanCount = glm.spanCount
glm.spanSizeLookup =
object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int) = if (lookup(position)) spanCount else 1
override fun getSpanSize(position: Int) = if (fullWidth(position)) spanCount else 1
}
}
}

View file

@ -40,7 +40,6 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
RecyclerView(context, attrs, defStyleAttr) {
private val topDivider = MaterialDivider(context)
private val bottomDivider = MaterialDivider(context)
private val spacingMedium = context.getDimenSize(R.dimen.spacing_medium)
init {

View file

@ -6,6 +6,7 @@
android:layout_height="wrap_content"
android:background="?attr/colorSurface"
android:orientation="vertical"
android:transitionGroup="true"
tools:context=".settings.AboutFragment">
<org.oxycblt.auxio.ui.AuxioAppBarLayout

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true"
android:background="?attr/colorSurface">
<org.oxycblt.auxio.detail.DetailAppBarLayout

View file

@ -5,6 +5,7 @@
android:id="@+id/home_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true"
android:background="?attr/colorSurface">
<org.oxycblt.auxio.ui.AuxioAppBarLayout

View file

@ -5,6 +5,7 @@
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true"
android:background="?attr/colorSurface">
<androidx.fragment.app.FragmentContainerView

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true"
android:background="?attr/colorSurface">
<org.oxycblt.auxio.ui.AuxioAppBarLayout

View file

@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true"
android:background="?attr/colorSurface"
android:orientation="vertical">

View file

@ -145,7 +145,7 @@
<item name="android:maxLines">1</item>
<item name="android:ellipsize">end</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
<item name="android:textAppearance">@style/TextAppearance.Auxio.LabelMedium</item>
<item name="android:textAppearance">@style/TextAppearance.Auxio.BodySmall</item>
</style>
<style name="Widget.Auxio.TextView.Header" parent="Widget.Auxio.TextView.Base">