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:
parent
0cef51fa97
commit
46473ceff9
18 changed files with 67 additions and 40 deletions
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
## dev
|
## dev
|
||||||
|
|
||||||
#### What's Improved
|
#### What's Changed
|
||||||
- Improved bottom sheet code to prevent clipping issues
|
- Use X-axis transitions instead of Z-axis (Avoids visual clipping)
|
||||||
|
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
- Fixed incorrect font being used in the queue title
|
- Fixed incorrect font being used in the queue title
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
*
|
*
|
||||||
* TODO: Add multi-select
|
* TODO: Add multi-select
|
||||||
*
|
*
|
||||||
|
* TODO: Remove asterisk imports
|
||||||
|
*
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,10 @@ class AlbumDetailFragment :
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,10 @@ class ArtistDetailFragment :
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
||||||
|
|
|
||||||
|
|
@ -64,10 +64,10 @@ class GenreDetailFragment :
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
override fun onCreateBinding(inflater: LayoutInflater) = FragmentDetailBinding.inflate(inflater)
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentHomeBinding
|
import org.oxycblt.auxio.databinding.FragmentHomeBinding
|
||||||
import org.oxycblt.auxio.home.list.AlbumListFragment
|
import org.oxycblt.auxio.home.list.AlbumListFragment
|
||||||
|
|
@ -79,10 +80,17 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
if (savedInstanceState != null) {
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
// Orientation change will wipe whatever transition we were using prior, which will
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
// 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)
|
override fun onCreateBinding(inflater: LayoutInflater) = FragmentHomeBinding.inflate(inflater)
|
||||||
|
|
@ -144,6 +152,11 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
|
||||||
collect(navModel.exploreNavigationItem, ::handleNavigation)
|
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) {
|
override fun onDestroyBinding(binding: FragmentHomeBinding) {
|
||||||
super.onDestroyBinding(binding)
|
super.onDestroyBinding(binding)
|
||||||
binding.homeToolbar.setOnMenuItemClickListener(null)
|
binding.homeToolbar.setOnMenuItemClickListener(null)
|
||||||
|
|
@ -153,6 +166,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_search -> {
|
R.id.action_search -> {
|
||||||
logD("Navigating to search")
|
logD("Navigating to search")
|
||||||
|
initSearchTransitions()
|
||||||
findNavController().navigate(HomeFragmentDirections.actionShowSearch())
|
findNavController().navigate(HomeFragmentDirections.actionShowSearch())
|
||||||
}
|
}
|
||||||
R.id.action_settings -> {
|
R.id.action_settings -> {
|
||||||
|
|
@ -364,9 +378,25 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initDetailTransitions()
|
||||||
|
|
||||||
findNavController().navigate(action)
|
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
|
* 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
|
* 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")
|
lazyReflectedField(ViewPager2::class, "mRecyclerView")
|
||||||
private val VIEW_PAGER_TOUCH_SLOP_FIELD: Field by
|
private val VIEW_PAGER_TOUCH_SLOP_FIELD: Field by
|
||||||
lazyReflectedField(RecyclerView::class, "mTouchSlop")
|
lazyReflectedField(RecyclerView::class, "mTouchSlop")
|
||||||
|
private const val KEY_INIT_WITH_SEARCH_TRANSITIONS =
|
||||||
|
BuildConfig.APPLICATION_ID + ".key.INIT_WITH_SEARCH_TRANSITIONS"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,6 @@ class PlaybackSheetBehavior<V : View>(context: Context, attributeSet: AttributeS
|
||||||
|
|
||||||
init {
|
init {
|
||||||
isHideable = true
|
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
|
// Hack around issue where the playback sheet will try to intercept nested scrolling events
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import androidx.core.view.postDelayed
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.transition.MaterialFadeThrough
|
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
import org.oxycblt.auxio.databinding.FragmentSearchBinding
|
||||||
|
|
@ -70,10 +69,10 @@ class SearchFragment :
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialFadeThrough()
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
||||||
returnTransition = MaterialFadeThrough()
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
|
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateBinding(inflater: LayoutInflater) = FragmentSearchBinding.inflate(inflater)
|
override fun onCreateBinding(inflater: LayoutInflater) = FragmentSearchBinding.inflate(inflater)
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,7 @@ class Settings(private val context: Context, private val callback: Callback? = n
|
||||||
unlikelyToBeNull(callback).onSettingChanged(key)
|
unlikelyToBeNull(callback).onSettingChanged(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** An interface for receiving some preference updates. */
|
||||||
* An interface for receiving some preference updates. Use/Extend this instead of
|
|
||||||
* [SharedPreferences.OnSharedPreferenceChangeListener] if possible, as it doesn't require a
|
|
||||||
* context.
|
|
||||||
*/
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onSettingChanged(key: String)
|
fun onSettingChanged(key: String)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
|
|
||||||
/**
|
/** A [RecyclerView] that enables some extra functionality for Auxio's use-case. */
|
||||||
* A [RecyclerView] that automatically applies insets to itself.
|
|
||||||
*
|
|
||||||
* TODO: Correctly handle edge-to-edge regarding scroll effects and saved scroll positions.
|
|
||||||
*/
|
|
||||||
open class AuxioRecyclerView
|
open class AuxioRecyclerView
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
|
||||||
|
|
@ -58,12 +54,12 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
return insets
|
return insets
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSpanSizeLookup(lookup: (Int) -> Boolean) {
|
inline fun setSpanSizeLookup(crossinline fullWidth: (Int) -> Boolean) {
|
||||||
val glm = layoutManager as GridLayoutManager
|
val glm = layoutManager as GridLayoutManager
|
||||||
val spanCount = glm.spanCount
|
val spanCount = glm.spanCount
|
||||||
glm.spanSizeLookup =
|
glm.spanSizeLookup =
|
||||||
object : GridLayoutManager.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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
RecyclerView(context, attrs, defStyleAttr) {
|
RecyclerView(context, attrs, defStyleAttr) {
|
||||||
private val topDivider = MaterialDivider(context)
|
private val topDivider = MaterialDivider(context)
|
||||||
private val bottomDivider = MaterialDivider(context)
|
private val bottomDivider = MaterialDivider(context)
|
||||||
|
|
||||||
private val spacingMedium = context.getDimenSize(R.dimen.spacing_medium)
|
private val spacingMedium = context.getDimenSize(R.dimen.spacing_medium)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:transitionGroup="true"
|
||||||
tools:context=".settings.AboutFragment">
|
tools:context=".settings.AboutFragment">
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:transitionGroup="true"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<org.oxycblt.auxio.detail.DetailAppBarLayout
|
<org.oxycblt.auxio.detail.DetailAppBarLayout
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
android:id="@+id/home_layout"
|
android:id="@+id/home_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:transitionGroup="true"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
android:id="@+id/main_layout"
|
android:id="@+id/main_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:transitionGroup="true"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:transitionGroup="true"
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
<org.oxycblt.auxio.ui.AuxioAppBarLayout
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:transitionGroup="true"
|
||||||
android:background="?attr/colorSurface"
|
android:background="?attr/colorSurface"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@
|
||||||
<item name="android:maxLines">1</item>
|
<item name="android:maxLines">1</item>
|
||||||
<item name="android:ellipsize">end</item>
|
<item name="android:ellipsize">end</item>
|
||||||
<item name="android:textColor">?android:attr/textColorSecondary</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>
|
||||||
|
|
||||||
<style name="Widget.Auxio.TextView.Header" parent="Widget.Auxio.TextView.Base">
|
<style name="Widget.Auxio.TextView.Header" parent="Widget.Auxio.TextView.Base">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue