草庐IT

android - 动画工具栏和 fragment 事务

coder 2023-11-27 原文

我有 MainActivity,它使用以下 xml 实现 Navigation Drawer:

<android.support.v4.widget.DrawerLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/container_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />
    </LinearLayout>

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#FFFFFF"/>


</LinearLayout>

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity ="start"
    >


    <ListView
        android:id="@+id/drawerList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="5dp"
        android:divider="@color/material_blue_grey_800"
        android:dividerHeight="1dp"
        android:background="#FFFFFF"
        />

   </RelativeLayout>

</android.support.v4.widget.DrawerLayout>

现在我的 ListView 中有 3 个项目,单击其中任何一个,我的代码将 Framelayout 替换为该特定 fragment ,如下所示:

Fragment f1 = new Fragment()

 FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
 ft.setCustomAnimations(R.anim.slide_in,R.anim.hyper_out,R.anim.hyper_in,R.anim.slide_out)


ft.replace(R.id.content, f1).addToBackStack(null).commit();

上面的代码可以很好地根据需要用自定义动画替换 fragment 。但是,我的问题是如何在 fragment 事务期间为工具栏和 fragment 设置动画。

所有 fragment 都有各自的工具栏标题,这些标题在每个 fragment 类的 onActivityCreated() 方法中通过以下代码更改:

((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("Title");

我是否应该将动画应用于我的布局以掩盖工具栏?

最佳答案

我有同样的问题 - 它似乎在每个应用程序的开发过程中的某个时刻突然出现,我从未解决过它,并恢复到一些低于标准的解决方案。现在我带着解决方案回来了!

在 Kotlin 中回答,但同样的原则适用于 Java。

要使 ToolbarFragmentTransaction 动画一起动画化,您首先需要一种方法来通知持有 Toolbar 的 Activity/Fragment 动画开始/结束。我会将包含 ToolbarActivity/Fragment 称为 ToolbarHost

首先,定义一个ToolbarHost可以实现的接口(interface),接收回调:

interface FragmentAnimationListener {

    fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean)

    fun onAnimationEnd(fragment: Fragment, animation: Animation, enter: Boolean)
}

我还添加了一个扩展方法来帮助子 Fragment 找到对接收回调感兴趣的父 ToolbarHost:

fun Fragment.findParentAnimationListener(): FragmentAnimationListener? {
    return when (parentFragment) {
        is FragmentAnimationListener -> parentFragment as FragmentAnimationListener
        null -> return activity as? FragmentAnimationListener
        else -> parentFragment?.findParentAnimationListener()
    }
}

现在我们将以下内容添加到将要在屏幕上显示动画的子 Fragment。我建议将以下内容添加到基础 Fragment 类中。这会拦截从 FragmentTransaction* 提供给子 Fragment 的动画,添加一个监听器,找到 ToolbarHost,并通知它我们的动画开始/结束。

override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
    var animation = super.onCreateAnimation(transit, enter, nextAnim)

    if (animation == null && nextAnim != 0) {
        animation = AnimationUtils.loadAnimation(activity!!, nextAnim)
    }

    val parentAnimationListener = findParentAnimationListener()

    if (animation != null) {    
        animation.setAnimationListener(object : Animation.AnimationListener {

            override fun onAnimationStart(animation: Animation) {
                parentAnimationListener?.onAnimationStart(this@BaseFragment, animation, enter)
            }

            override fun onAnimationEnd(animation: Animation) {
                parentAnimationListener?.onAnimationEnd(this@BaseFragment, animation, enter)
            }

            override fun onAnimationRepeat(animation: Animation?) {
            }
        })
    }

    return animation
}

* 这适用于通过 FragmentTransaction.setCustomAnimation(int, int, ..) 提供的动画。我没有使用不同类型的 FragmentTransaction 动画或没有 FragmentTransaction 动画对此进行测试。

现在我们的 ToolbarHost 知道子 Fragment 何时执行其动画,我们可以考虑同时为工具栏设置动画。

假设你的ToolbarHost是一个 fragment ,我们首先实现FragmentAnimationListener:

class ParentFragment : Fragment(), FragmentAnimationListener {

    override fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean) {
        ...
    }

    override fun onAnimationEnd(fragment: Fragment, animation: Animation, enter: Boolean) {
        ...
    }
}

现在,我们马上就遇到了一个问题,因为我们将 AnimationListener 添加到基础 Fragment 类,我们的 onAnimationStartonAnimationEnd 将从正在退出的 fragment 和正在进入的 fragment 调用(假设您的 FragmentTransaction 正在用另一个 fragment 替换一个 fragment )。因此,在我们尝试使用 Toolbar 做任何事情之前,我们需要只过滤掉我们感兴趣的 fragment 。

我将使用“进入”Fragment 作为工具栏动画的触发器 - 当我们弹出堆栈时,我将使用相同的Fragment(现在“退出”)再次。所以,我唯一感兴趣的 Fragment 是正在转换的那个:

class ParentFragment : Fragment(), FragmentAnimationListener {

    var newFragment: Fragment? = null 

    fun replaceFragment(newFragment: Fragment) {

        // Store a reference to the fragment we're transitioning to
        this.newFragment = newFragment

        childFragmentManager.beginTransaction()
            .setCustomAnimations(..)
            .replace(container, newFragment, tag)
            .commit()
    }

    override fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean) {
        if (fragment == newFragment) {
            if (enter) {
                // Animate our Toolbar in
            } else {
                // Animate our Toolbar out
            }
        }
    }
}

最后一步是实际执行工具栏动画。您可以使用自己的时间、插值器等创建自己的 Animation - 但我更喜欢只使用为子 Fragment 设置动画的相同 Animator >。这样,如果我们淡入,Toolbar 将淡入。如果我们滑出,Toolbar 将滑出。通过使用相同的 Animation,我们可以确定我们有正确的持续时间和插值器,因此我们的 Animation 将同时运行。

override fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean) {
    if (fragment == newFragment) {
        toolbar.animation = animation
    }
}

关于android - 动画工具栏和 fragment 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30815928/

有关android - 动画工具栏和 fragment 事务的更多相关文章

  1. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  2. ruby - 分布式事务和队列,ruby,erlang,scala - 2

    我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和

  3. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  4. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  7. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  8. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  9. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  10. ruby - 使用 Ruby 开发工具包将文件上传到 Amazon S3 - 2

    我正在尝试上传文件。一个简单的hello.txt。我正在关注文档,但无法将其上传到我的存储桶。#STARTAWSCLIENTs3=Aws::S3::Resource.newbucket=s3.bucket(BUCKET_NAME)begins3.buckets[BUCKET_NAME].objects[KEY].write(:file=>FILE_NAME)puts"Uploadingfile#{FILE_NAME}tobucket#{BUCKET_NAME}."bucket.objects.eachdo|obj|puts"#{obj.key}=>#{obj.etag}"endresc

随机推荐