mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Login screens: add some animation for Fragment transition (WIP)
This commit is contained in:
parent
1bec8c29b8
commit
500eb113b6
10 changed files with 108 additions and 41 deletions
|
@ -16,10 +16,12 @@
|
|||
|
||||
package im.vector.riotx.features.login
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
|
@ -42,6 +44,14 @@ abstract class AbstractLoginFragment : VectorBaseFragment(), OnBackPressed {
|
|||
// Due to async, we keep a boolean to avoid displaying twice the cancellation dialog
|
||||
private var displayCancelDialog = true
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
|
|
@ -19,11 +19,15 @@ package im.vector.riotx.features.login
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.auth.registration.FlowResult
|
||||
|
@ -56,6 +60,27 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
private val enterAnim = R.anim.enter_fade_in
|
||||
private val exitAnim = R.anim.exit_fade_out
|
||||
|
||||
private val popEnterAnim = R.anim.no_anim
|
||||
private val popExitAnim = R.anim.exit_fade_out
|
||||
|
||||
private val topFragment: Fragment?
|
||||
get() = supportFragmentManager.findFragmentById(R.id.loginFragmentContainer)
|
||||
|
||||
private val commonOption: (FragmentTransaction) -> Unit = { ft ->
|
||||
// Find the loginLogo on the current Fragment, this should not return null
|
||||
(topFragment?.view as? ViewGroup)
|
||||
// Find findViewById does not work, I do not know why
|
||||
// findViewById<View?>(R.id.loginLogo)
|
||||
?.children
|
||||
?.first { it.id == R.id.loginLogo }
|
||||
?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||
// TODO
|
||||
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_login
|
||||
|
||||
override fun initUiAndData() {
|
||||
|
@ -96,31 +121,37 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
@Suppress("UNUSED_VARIABLE")
|
||||
val dummy = when (loginNavigation) {
|
||||
is LoginNavigation.OpenServerSelection ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerSelectionFragment::class.java,
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginServerSelectionFragment::class.java,
|
||||
option = { ft ->
|
||||
val view = findViewById<View?>(R.id.loginSplashLogo)
|
||||
if (view != null) {
|
||||
ft.addSharedElement(view, ViewCompat.getTransitionName(view) ?: "")
|
||||
}
|
||||
findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||
findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||
findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
|
||||
// TODO Disabled because it provokes a flickering
|
||||
//ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
|
||||
})
|
||||
is LoginNavigation.OnServerSelectionDone -> onServerSelectionDone()
|
||||
is LoginNavigation.OnSignModeSelected -> onSignModeSelected()
|
||||
is LoginNavigation.OnLoginFlowRetrieved ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginSignUpSignInSelectionFragment::class.java)
|
||||
LoginSignUpSignInSelectionFragment::class.java,
|
||||
option = commonOption)
|
||||
is LoginNavigation.OnWebLoginError -> onWebLoginError(loginNavigation)
|
||||
is LoginNavigation.OnForgetPasswordClicked ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginResetPasswordFragment::class.java)
|
||||
LoginResetPasswordFragment::class.java,
|
||||
option = commonOption)
|
||||
is LoginNavigation.OnResetPasswordSendThreePidDone -> {
|
||||
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginResetPasswordMailConfirmationFragment::class.java)
|
||||
LoginResetPasswordMailConfirmationFragment::class.java,
|
||||
option = commonOption)
|
||||
}
|
||||
is LoginNavigation.OnResetPasswordMailConfirmationSuccess -> {
|
||||
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginResetPasswordSuccessFragment::class.java)
|
||||
LoginResetPasswordSuccessFragment::class.java,
|
||||
option = commonOption)
|
||||
}
|
||||
is LoginNavigation.OnResetPasswordMailConfirmationSuccessDone -> {
|
||||
// Go back to the login fragment
|
||||
|
@ -130,12 +161,14 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginWaitForEmailFragment::class.java,
|
||||
LoginWaitForEmailFragmentArgument(loginNavigation.email),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
is LoginNavigation.OnSendMsisdnSuccess ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginGenericTextInputFormFragment::class.java,
|
||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginNavigation.msisdn),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +189,9 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
// This way it will be automatically popped in when starting the next registration stage
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginFragment::class.java,
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +235,9 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
when (state.serverType) {
|
||||
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
|
||||
ServerType.Modular,
|
||||
ServerType.Other -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginServerUrlFormFragment::class.java)
|
||||
ServerType.Other -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginServerUrlFormFragment::class.java,
|
||||
option = commonOption)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,8 +251,13 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
// It depends on the LoginMode
|
||||
when (state.loginMode) {
|
||||
LoginMode.Unknown -> error("Developer error")
|
||||
LoginMode.Password -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment::class.java, tag = FRAGMENT_LOGIN_TAG)
|
||||
LoginMode.Sso -> addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
|
||||
LoginMode.Password -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginFragment::class.java,
|
||||
tag = FRAGMENT_LOGIN_TAG,
|
||||
option = commonOption)
|
||||
LoginMode.Sso -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginWebFragment::class.java,
|
||||
option = commonOption)
|
||||
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +269,9 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
.setTitle(R.string.app_name)
|
||||
.setMessage(getString(R.string.login_registration_not_supported))
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginWebFragment::class.java,
|
||||
option = commonOption)
|
||||
}
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show()
|
||||
|
@ -238,7 +282,9 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
.setTitle(R.string.app_name)
|
||||
.setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer, LoginWebFragment::class.java)
|
||||
addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginWebFragment::class.java,
|
||||
option = commonOption)
|
||||
}
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show()
|
||||
|
@ -269,19 +315,23 @@ class LoginActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
is Stage.ReCaptcha -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginCaptchaFragment::class.java,
|
||||
LoginCaptchaFragmentArgument(stage.publicKey),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
is Stage.Email -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginGenericTextInputFormFragment::class.java,
|
||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
is Stage.Msisdn -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginGenericTextInputFormFragment::class.java,
|
||||
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
is Stage.Terms -> addFragmentToBackstack(R.id.loginFragmentContainer,
|
||||
LoginTermsFragment::class.java,
|
||||
LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))),
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG)
|
||||
tag = FRAGMENT_REGISTRATION_STAGE_TAG,
|
||||
option = commonOption)
|
||||
else -> Unit // Should not happen
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
package im.vector.riotx.features.login
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.transition.TransitionInflater
|
||||
import butterknife.OnClick
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotx.R
|
||||
|
@ -39,14 +37,6 @@ class LoginServerSelectionFragment @Inject constructor(
|
|||
|
||||
override fun getLayoutResId() = R.layout.fragment_login_server_selection
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/default_animation_duration"
|
||||
android:shareInterpolator="false">
|
||||
android:startOffset="@integer/default_animation_offset">
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="0"
|
||||
android:toAlpha="1" />
|
||||
|
||||
</set>
|
||||
</set>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="@integer/default_animation_duration"
|
||||
android:shareInterpolator="false">
|
||||
android:duration="@integer/default_animation_half">
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="1"
|
||||
android:toAlpha="0" />
|
||||
|
||||
</set>
|
||||
</set>
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
<!-- Missing attributes are in the style -->
|
||||
<ImageView
|
||||
style="@style/LoginLogo"
|
||||
android:transitionName="loginLogoTransition"
|
||||
tools:ignore="ContentDescription,MissingConstraints,UnusedAttribute" />
|
||||
|
||||
<!-- Missing attributes are in the style -->
|
||||
|
@ -25,6 +24,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/login_server_title"
|
||||
android:textAppearance="@style/TextAppearance.Vector.Login.Title"
|
||||
android:transitionName="loginTitleTransition"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
@ -148,7 +149,7 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/loginServerChoiceOtherTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:text="@string/login_server_other_title"
|
||||
|
@ -156,7 +157,6 @@
|
|||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginServerChoiceOtherText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
@ -183,6 +183,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/login_continue"
|
||||
android:transitionName="loginSubmitTransition"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
android:layout_marginTop="48dp"
|
||||
android:text="@string/login_splash_title"
|
||||
android:textAppearance="@style/TextAppearance.Vector.Login.Title"
|
||||
android:transitionName="loginTitleTransition"
|
||||
app:layout_constraintBottom_toTopOf="@+id/loginSplashText1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loginSplashLogo" />
|
||||
|
||||
|
@ -123,6 +125,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="48dp"
|
||||
android:text="@string/login_splash_submit"
|
||||
android:transitionName="loginSubmitTransition"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
8
vector/src/main/res/values-v21/styles_login.xml
Normal file
8
vector/src/main/res/values-v21/styles_login.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="LoginLogo.v21" parent="LoginLogoBase">
|
||||
<item name="android:transitionName">loginLogoTransition</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -1,7 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<integer name="default_animation_duration">500</integer>
|
||||
<integer name="default_animation_half">200</integer>
|
||||
|
||||
<integer name="default_animation_duration">400</integer>
|
||||
|
||||
<integer name="default_animation_offset">200</integer>
|
||||
|
||||
<integer name="rtl_mirror_flip">0</integer>
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
<item name="layout_constraintStart_toStartOf">parent</item>
|
||||
</style>
|
||||
|
||||
<style name="LoginLogo" parent="LoginLogoBase">
|
||||
<style name="LoginLogo.v21" parent="LoginLogoBase" />
|
||||
|
||||
<style name="LoginLogo" parent="LoginLogo.v21">
|
||||
<item name="layout_constraintEnd_toEndOf">parent</item>
|
||||
<item name="android:layout_marginTop">32dp</item>
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue