1
0
Fork 0

For #3086: Adds settings animations (#9187)

master
Sawyer Blatz 2020-03-17 12:35:00 -07:00 committed by GitHub
parent a457755388
commit b4e1360f59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 4 deletions

View File

@ -18,8 +18,11 @@ import androidx.preference.Preference
import androidx.preference.Preference.OnPreferenceClickListener import androidx.preference.Preference.OnPreferenceClickListener
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AccountObserver
@ -43,7 +46,7 @@ import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.account.AccountAuthErrorPreference import org.mozilla.fenix.settings.account.AccountAuthErrorPreference
import org.mozilla.fenix.settings.account.AccountPreference import org.mozilla.fenix.settings.account.AccountPreference
@Suppress("LargeClass") @Suppress("LargeClass", "TooManyFunctions")
class SettingsFragment : PreferenceFragmentCompat() { class SettingsFragment : PreferenceFragmentCompat() {
private val accountObserver = object : AccountObserver { private val accountObserver = object : AccountObserver {
@ -114,6 +117,8 @@ class SettingsFragment : PreferenceFragmentCompat() {
showToolbar(getString(R.string.settings_title)) showToolbar(getString(R.string.settings_title))
update() update()
view!!.findViewById<RecyclerView>(R.id.recycler_view)?.hideInitialScrollBar(lifecycleScope)
} }
private fun update() { private fun update() {
@ -165,6 +170,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
@Suppress("ComplexMethod", "LongMethod") @Suppress("ComplexMethod", "LongMethod")
override fun onPreferenceTreeClick(preference: Preference): Boolean { override fun onPreferenceTreeClick(preference: Preference): Boolean {
// Hide the scrollbar so the animation looks smoother
val recyclerView = view!!.findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.isVerticalScrollBarEnabled = false
val directions: NavDirections? = when (preference.key) { val directions: NavDirections? = when (preference.key) {
resources.getString(R.string.pref_key_search_settings) -> { resources.getString(R.string.pref_key_search_settings) -> {
SettingsFragmentDirections.actionSettingsFragmentToSearchEngineFragment() SettingsFragmentDirections.actionSettingsFragmentToSearchEngineFragment()
@ -301,6 +310,18 @@ class SettingsFragment : PreferenceFragmentCompat() {
} }
} }
// Extension function for hiding the scroll bar on initial loading. We must do this so the
// animation to the next screen doesn't animate the initial scroll bar (it ignores
// isVerticalScrollBarEnabled being set to false).
private fun RecyclerView.hideInitialScrollBar(scope: CoroutineScope) {
scope.launch {
val originalSize = scrollBarSize
scrollBarSize = 0
delay(SCROLL_INDICATOR_DELAY)
scrollBarSize = originalSize
}
}
/** /**
* Updates the UI to reflect current account state. * Updates the UI to reflect current account state.
* Possible conditions are logged-in without problems, logged-out, and logged-in but needs to re-authenticate. * Possible conditions are logged-in without problems, logged-out, and logged-in but needs to re-authenticate.
@ -366,4 +387,8 @@ class SettingsFragment : PreferenceFragmentCompat() {
accountPreferenceCategory?.isVisible = false accountPreferenceCategory?.isVisible = false
} }
} }
companion object {
private const val SCROLL_INDICATOR_DELAY = 10L
}
} }

View File

@ -0,0 +1,11 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-50%" android:toXDelta="0%"
android:interpolator="@android:interpolator/decelerate_quad"
android:duration="275"/>
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:duration="275" />
</set>

View File

@ -0,0 +1,11 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="50%" android:toXDelta="0%"
android:interpolator="@android:interpolator/decelerate_quad"
android:duration="275"/>
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:duration="275" />
</set>

View File

@ -0,0 +1,11 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="-50%"
android:interpolator="@android:interpolator/decelerate_quad"
android:duration="275"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0"
android:duration="275" />
</set>

View File

@ -0,0 +1,11 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0%" android:toXDelta="50%"
android:interpolator="@android:interpolator/decelerate_quad"
android:duration="275"/>
<alpha android:fromAlpha="1.0" android:toAlpha="0"
android:duration="275" />
</set>

View File

@ -62,7 +62,6 @@
<fragment <fragment
android:id="@+id/homeFragment" android:id="@+id/homeFragment"
android:name="org.mozilla.fenix.home.HomeFragment" android:name="org.mozilla.fenix.home.HomeFragment"
app:enterAnim="@anim/zoom_out_fade"
tools:layout="@layout/fragment_home"> tools:layout="@layout/fragment_home">
<action <action
android:id="@+id/action_homeFragment_to_turnOnSyncFragment" android:id="@+id/action_homeFragment_to_turnOnSyncFragment"
@ -91,6 +90,10 @@
app:destination="@id/historyFragment" /> app:destination="@id/historyFragment" />
<action <action
android:id="@+id/action_homeFragment_to_settingsFragment" android:id="@+id/action_homeFragment_to_settingsFragment"
app:enterAnim="@anim/fade_in_up"
app:exitAnim="@anim/fade_out"
app:popExitAnim="@anim/fade_out_down"
app:popEnterAnim="@anim/fade_in"
app:destination="@id/settingsFragment" /> app:destination="@id/settingsFragment" />
<action <action
android:id="@+id/action_homeFragment_to_createCollectionFragment" android:id="@+id/action_homeFragment_to_createCollectionFragment"
@ -385,55 +388,123 @@
app:popUpTo="@+id/settingsFragment" /> app:popUpTo="@+id/settingsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_dataChoicesFragment" android:id="@+id/action_settingsFragment_to_dataChoicesFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/dataChoicesFragment" app:destination="@id/dataChoicesFragment"
app:popUpTo="@+id/settingsFragment" /> app:popUpTo="@+id/settingsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_sitePermissionsFragment" android:id="@+id/action_settingsFragment_to_sitePermissionsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/sitePermissionsFragment" /> app:destination="@id/sitePermissionsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_loginsFragment" android:id="@+id/action_settingsFragment_to_loginsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/loginsFragment" /> app:destination="@id/loginsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_accessibilityFragment" android:id="@+id/action_settingsFragment_to_accessibilityFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/accessibilityFragment" /> app:destination="@id/accessibilityFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_accountSettingsFragment" android:id="@+id/action_settingsFragment_to_accountSettingsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/accountSettingsFragment" /> app:destination="@id/accountSettingsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_searchEngineFragment" android:id="@+id/action_settingsFragment_to_searchEngineFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/searchEngineFragment" /> app:destination="@id/searchEngineFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_turnOnSyncFragment" android:id="@+id/action_settingsFragment_to_turnOnSyncFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/turnOnSyncFragment" /> app:destination="@id/turnOnSyncFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_aboutFragment" android:id="@+id/action_settingsFragment_to_aboutFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/aboutFragment" /> app:destination="@id/aboutFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_customizationFragment" android:id="@+id/action_settingsFragment_to_customizationFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/customizationFragment" /> app:destination="@id/customizationFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_privateBrowsingFragment" android:id="@+id/action_settingsFragment_to_privateBrowsingFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/privateBrowsingFragment" /> app:destination="@id/privateBrowsingFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_trackingProtectionFragment" android:id="@+id/action_settingsFragment_to_trackingProtectionFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/trackingProtectionFragment" /> app:destination="@id/trackingProtectionFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_deleteBrowsingDataFragment" android:id="@+id/action_settingsFragment_to_deleteBrowsingDataFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/deleteBrowsingDataFragment" /> app:destination="@id/deleteBrowsingDataFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_accountProblemFragment" android:id="@+id/action_settingsFragment_to_accountProblemFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/accountProblemFragment" /> app:destination="@id/accountProblemFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_deleteBrowsingDataOnQuitFragment" android:id="@+id/action_settingsFragment_to_deleteBrowsingDataOnQuitFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/deleteBrowsingDataOnQuitFragment" /> app:destination="@id/deleteBrowsingDataOnQuitFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_defaultBrowserSettingsFragment" android:id="@+id/action_settingsFragment_to_defaultBrowserSettingsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/defaultBrowserSettingsFragment" /> app:destination="@id/defaultBrowserSettingsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_localeSettingsFragment" android:id="@+id/action_settingsFragment_to_localeSettingsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/localeSettingsFragment" /> app:destination="@id/localeSettingsFragment" />
<action <action
android:id="@+id/action_settingsFragment_to_addonsFragment" android:id="@+id/action_settingsFragment_to_addonsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:destination="@id/addonsManagementFragment" /> app:destination="@id/addonsManagementFragment" />
</fragment> </fragment>
<fragment <fragment

View File

@ -3,7 +3,8 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this - License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <androidx.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.preference.Preference <androidx.preference.Preference

View File

@ -5,4 +5,3 @@
object AndroidComponents { object AndroidComponents {
const val VERSION = "37.0.20200317130045" const val VERSION = "37.0.20200317130045"
} }