我有 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。
要使 Toolbar 与 FragmentTransaction 动画一起动画化,您首先需要一种方法来通知持有 Toolbar 的 动画开始/结束。我会将包含 Activity/Fragment Toolbar 的 Activity/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 类,我们的 onAnimationStart 和onAnimationEnd 将从正在退出的 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/
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功
我已经开始使用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
我正在尝试上传文件。一个简单的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