Sme*_*ard 28 android android-animation android-jetpack android-architecture-navigation
我正在使用Android Studio 3.2 Canary 14和导航架构组件.使用此功能,您可以像使用Intent一样定义过渡动画.
但是动画被设置为导航图中动作的属性,如下所示:
<fragment
android:id="@+id/startScreenFragment"
android:name="com.example.startScreen.StartScreenFragment"
android:label="fragment_start_screen"
tools:layout="@layout/fragment_start_screen" >
<action
android:id="@+id/action_startScreenFragment_to_findAddressFragment"
app:destination="@id/findAddressFragment"
app:enterAnim="@animator/slide_in_right"
app:exitAnim="@animator/slide_out_left"
app:popEnterAnim="@animator/slide_in_left"
app:popExitAnim="@animator/slide_out_right"/>
</fragment>
Run Code Online (Sandbox Code Playgroud)
为图表中的所有操作定义这一过程非常繁琐!
有没有办法在动作上将一组动画定义为默认值?
我没有运气使用款式.
Mar*_*ler 11
R.anim定义了默认动画(作为final):
nav_default_enter_anim
nav_default_exit_anim
nav_default_pop_enter_anim
nav_default_pop_exit_anim
要更改此行为,您必须使用自定义NavOptions,
因为这是将这些动画分配给NavAction的地方.
可以使用NavOptions.Builder分配这些:
protected NavOptions getNavOptions() {
NavOptions navOptions = NavOptions.Builder()
.setEnterAnim(R.anim.default_enter_anim)
.setExitAnim(R.anim.default_exit_anim)
.setPopEnterAnim(R.anim.default_pop_enter_anim)
.setPopExitAnim(R.anim.default_pop_exit_anim)
.build();
return navOptions;
}
Run Code Online (Sandbox Code Playgroud)
最有可能需要创建一个DefaultNavFragment,扩展类androidx.navigation.fragment(那里的文档似乎还没有完成).
或者...当看到attrs.xml那个包裹时; 这些动画都是风格化的:
<resources>
<declare-styleable name="NavAction">
<attr name="enterAnim" format="reference"/>
<attr name="exitAnim" format="reference"/>
<attr name="popEnterAnim" format="reference"/>
<attr name="popExitAnim" format="reference"/>
...
</declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)
这意味着,可以定义相应的样式 - 并定义这些样式,作为主题的一部分......
可以在styles.xml以下位置定义它们:
<style name="Theme.Default" parent="Theme.AppCompat.Light.NoActionBar">
<!-- these should be the correct ones -->
<item name="NavAction_enterAnim">@anim/default_enter_anim</item>
<item name="NavAction_exitAnim">@anim/default_exit_anim</item>
<item name="NavAction_popEnterAnim">@anim/default_pop_enter_anim</item>
<item name="NavAction_popExitAnim">@anim/default_pop_exit_anim</item>
</style>
Run Code Online (Sandbox Code Playgroud)
我找到了需要扩展NavHostFragment. 它类似于Link182,但较少涉及代码。大多数情况下,它需要从标准更改所有 xml defaultNavHost 片段名称:
<fragment
app:defaultNavHost="true"
...
android:name="androidx.navigation.fragment.NavHostFragment"
Run Code Online (Sandbox Code Playgroud)
到:
<fragment
app:defaultNavHost="true"
...
android:name="your.app.package.fragments.NavHostFragmentWithDefaultAnimations"
Run Code Online (Sandbox Code Playgroud)
代码NavHostFragmentWithDefaultAnimations:
package your.app.package.fragments
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.FragmentManager
import androidx.navigation.*
import androidx.navigation.fragment.FragmentNavigator
import androidx.navigation.fragment.NavHostFragment
import your.app.package.R
// Those are navigation-ui (androidx.navigation.ui) defaults
// used in NavigationUI for NavigationView and BottomNavigationView.
// Set yours here
private val defaultNavOptions = navOptions {
anim {
enter = R.animator.nav_default_enter_anim
exit = R.animator.nav_default_exit_anim
popEnter = R.animator.nav_default_pop_enter_anim
popExit = R.animator.nav_default_pop_exit_anim
}
}
private val emptyNavOptions = navOptions {}
class NavHostFragmentWithDefaultAnimations : NavHostFragment() {
override fun onCreateNavController(navController: NavController) {
super.onCreateNavController(navController)
navController.navigatorProvider.addNavigator(
// this replaces FragmentNavigator
FragmentNavigatorWithDefaultAnimations(requireContext(), childFragmentManager, id)
)
}
}
/**
* Needs to replace FragmentNavigator and replacing is done with name in annotation.
* Navigation method will use defaults for fragments transitions animations.
*/
@Navigator.Name("fragment")
class FragmentNavigatorWithDefaultAnimations(
context: Context,
manager: FragmentManager,
containerId: Int
) : FragmentNavigator(context, manager, containerId) {
override fun navigate(
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Navigator.Extras?
): NavDestination? {
// this will try to fill in empty animations with defaults when no shared element transitions are set
// https://developer.android.com/guide/navigation/navigation-animate-transitions#shared-element
val shouldUseTransitionsInstead = navigatorExtras != null
val navOptions = if (shouldUseTransitionsInstead) navOptions
else navOptions.fillEmptyAnimationsWithDefaults()
return super.navigate(destination, args, navOptions, navigatorExtras)
}
private fun NavOptions?.fillEmptyAnimationsWithDefaults(): NavOptions =
this?.copyNavOptionsWithDefaultAnimations() ?: defaultNavOptions
private fun NavOptions.copyNavOptionsWithDefaultAnimations(): NavOptions =
let { originalNavOptions ->
navOptions {
launchSingleTop = originalNavOptions.shouldLaunchSingleTop()
popUpTo(originalNavOptions.popUpTo) {
inclusive = originalNavOptions.isPopUpToInclusive
}
anim {
enter =
if (originalNavOptions.enterAnim == emptyNavOptions.enterAnim) defaultNavOptions.enterAnim
else originalNavOptions.enterAnim
exit =
if (originalNavOptions.exitAnim == emptyNavOptions.exitAnim) defaultNavOptions.exitAnim
else originalNavOptions.exitAnim
popEnter =
if (originalNavOptions.popEnterAnim == emptyNavOptions.popEnterAnim) defaultNavOptions.popEnterAnim
else originalNavOptions.popEnterAnim
popExit =
if (originalNavOptions.popExitAnim == emptyNavOptions.popExitAnim) defaultNavOptions.popExitAnim
else originalNavOptions.popExitAnim
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过传递 navOptions 在导航图 xml 或代码中更改动画。要禁用默认动画,请传递动画值为 0 的 navOptions 或传递 navigatorExtras(设置共享转换)。
测试版本:
implementation "androidx.navigation:navigation-fragment-ktx:2.3.1"
implementation "androidx.navigation:navigation-ui-ktx:2.3.1"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3610 次 |
| 最近记录: |