求助:实现Prisma应用中CAMERA与FEED间全屏Fragment及透明TabLayout动画
嘿,我刚好折腾过类似的Prisma风格页面切换动画,给你梳理几个可行的实现步骤,一步步来搞定:
核心需求拆解
咱们要实现的是三个关键点:Fragment全屏显示 + TabLayout透明化 + 页面切换时的缩放位移动画,下面逐个击破。
一、先搞定TabLayout透明化
- 直接在布局文件里给TabLayout设置透明背景,同时适配文字颜色避免看不见:
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" app:tabTextColor="#FFFFFF" app:tabSelectedTextColor="#FFD700" /> - 如果TabLayout嵌套在AppBarLayout里,记得把AppBarLayout的背景也设为透明,避免出现遮挡。
二、设置Fragment全屏显示
- 给Fragment的根布局添加
android:fitsSystemWindows="true",让内容自动适配状态栏高度,避免被挡住。 - 布局结构建议用
ConstraintLayout或FrameLayout,把TabLayout叠加在Fragment内容上方,给TabLayout设置android:elevation="4dp"保证层级在Fragment之上,同时让ViewPager/Fragment容器占满整个屏幕空间。 - 记得在Activity里隐藏默认ActionBar,或者把主题设置为
NoActionBar。
三、实现核心的页面切换动画
这部分是Prisma效果的灵魂,推荐两种方案,根据你的页面管理方式选择:
方案1:用ViewPager2的PageTransformer(适合ViewPager管理页面)
自定义一个PageTransformer,实现滑动时的缩放+位移效果,匹配Prisma的动画风格:
class PrismaPageTransformer : ViewPager2.PageTransformer { private val MIN_SCALE = 0.85f // 最小缩放比例 private val MIN_ALPHA = 0.0f // 最小透明度 override fun transformPage(page: View, position: Float) { page.apply { when { position < -1 -> { // 页面完全滑出左侧 alpha = MIN_ALPHA scaleX = MIN_SCALE scaleY = MIN_SCALE } position <= 0 -> { // 从左滑入/滑出到左的过程 alpha = MIN_ALPHA + (1 + position) * (1 - MIN_ALPHA) val scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)) scaleX = scaleFactor scaleY = scaleFactor translationX = width * -position * 0.3f // 增加轻微位移增强层次感 } position <= 1 -> { // 从右滑入/滑出到右的过程 alpha = MIN_ALPHA + (1 - position) * (1 - MIN_ALPHA) val scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - position) scaleX = scaleFactor scaleY = scaleFactor translationX = width * -position * 0.3f } else -> { // 页面完全滑出右侧 alpha = MIN_ALPHA scaleX = MIN_SCALE scaleY = MIN_SCALE } } } } }
然后给ViewPager2设置这个Transformer:
viewPager2.setPageTransformer(PrismaPageTransformer())
方案2:用FragmentTransaction自定义动画(适合手动切换Fragment)
如果是用FragmentManager手动切换页面,先在res/anim目录下创建两个动画文件:
slide_in_right.xml(右侧页面滑入):
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="100%" android:toXDelta="0%" android:duration="300"/> <scale android:fromXScale="0.85" android:toXScale="1.0" android:pivotX="50%" android:pivotY="50%" android:duration="300"/> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="300"/> </set>
slide_out_left.xml(左侧页面滑出):
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="0%" android:toXDelta="-30%" android:duration="300"/> <scale android:fromXScale="1.0" android:toXScale="0.85" android:pivotX="50%" android:pivotY="50%" android:duration="300"/> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="300"/> </set>
切换Fragment时调用:
supportFragmentManager.beginTransaction() .setCustomAnimations( R.anim.slide_in_right, // 进入动画 R.anim.slide_out_left, // 退出动画 R.anim.slide_in_left, // 反向进入(返回时) R.anim.slide_out_right // 反向退出(返回时) ) .replace(R.id.fragment_container, targetFragment) .addToBackStack(null) .commit()
四、额外优化小技巧
- 如果想让TabLayout在滑动时也有轻微的透明度变化,增强联动效果,可以给ViewPager2添加页面监听:
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { super.onPageScrolled(position, positionOffset, positionOffsetPixels) // 滑动过程中TabLayout透明度在0.8到1之间变化,可根据需求调整 tabLayout.alpha = 1f - Math.abs(positionOffset - 0.5f) * 0.2f } })
- 处理状态栏适配:在Activity中调用
WindowCompat.setDecorFitsSystemWindows(window, false),然后在Fragment布局的根节点添加android:paddingTop="@dimen/status_bar_height"(需要自己定义状态栏高度的dimen值)。
内容的提问来源于stack exchange,提问作者Kubo Brehuv
相关产品推荐
相关产品推荐

