>

Transitions APIsbf282.com: 中的作用,可以自己写一个

- 编辑:澳门博发娱乐官网 -

Transitions APIsbf282.com: 中的作用,可以自己写一个

sbf282.com 1

版本号 时间
V1.0 2017.07.23

转载自:Android开发技术前线 ( android-tech-frontier )

深入理解 Shared Element Transition (part 3a)

  • 原文链接 : Shared Element Transitions In-Depth (part 3a)
  • 作者 : Alex Lockwood
  • 译文出自 : 开发技术前线 www.devtf.cn
  • 译者 : tiiime
  • 校对者: chaossss
  • 状态 : 完成

0.27 正式版发布

  • 得益于某位不愿留名的同学的帮助,队列模式已经较好的实现了。

在我们做直播等视频类app的时候,总是有显示和发送弹幕的要求,弹幕可以方便用户进行沟通和互动,增加了娱乐性,增强app等客户端的用户粘度,下面我们就说一下弹幕显示方面的问题和相关框架BarrageRenderer。先给出github地址。1. BarrageRenderer弹幕框架

深入理解Content Transition (part 2)

  • 原文链接 : Content Transitions In-Depth (part 2)
  • 译者 : tiiime
  • 校对者: chaossss
  • 状态 : 完成

深入理解共享元素 Transition

这篇文章会深度分析共享元素 transitions 和它在 Activity & Fragment Transitions API 中的作用。这篇文章是下面这个系列中的第三篇:

  • Part 1: 在 Activity 和 Fragment 中使用 Transition
  • Part 2: 深入理解 Content Transition
  • Part 3a: 深入理解共享元素 Transition
  • Part 3b: 延迟共享元素的 Transition
  • Part 3c: 共享元素回调实践 (coming soon!)
  • Part 4: Activity & Fragment 过渡动画示例(coming soon!)

Part 3 会分成三个部分: part3a 介绍 共享元素 transitions 的底层操作,part3b 和 part3c
主要关注 API 的具体实现细节,例如推迟某些 共享元素 transition 的重要性和如何实现
SharedElementCallbacks

我们首先会总结下在 part 1 中提到的关于 共享元素 transition 的知识点,然后说一说在 Android Lollipop 中是怎样使用它来构建合适的过渡动画。

不兼容的修改

  • 移除 NavigationLegacyNavigator (ef44781) - @hedgerwang

    • NavigationLegacyNavigator 原来是用于帮助人们在不改动API的情况下迁移到新的导航库。这会使得我们不得不把那些不必要的旧API也全部迁移到新的导航库中。

    • 考虑到在产品中使用NavigationLegacyNavigator是不应该的,所以我们决定移除掉它,并会在将来把原来的Navigator改名为NavigatorDeprecated。

  • 移除 NavigationExperimental Containers (14eb427) - @ericvicenti

    • NavigationExperimental中的容器并不建议使用,因为应用的状态应当被应用的架构所管理,譬如使用redux、flux或者组件状态。
      这个提交把样例修改为使用组件状态来保存的,不过也有其他很多例子用来展示如何使用NavigationAnimatedView和redux的导航器reducer。:
      https://github.com/jlyman/RN-NavigationExperimental-Redux-Example
      Switching the f8 app with redux to navigation experimental: fbsamples/f8app#14
  • 移除 NavigationView (c3714d7) - @hedgerwang

    • 使用<NavigationView /> 没有明显的作用,并且维护起来非常麻烦。它的功能完全可以通过创建一个关闭了切换动画的NavigationAnimatedView来实现。它还可以被一个单纯的View和一个普通的场景渲染器来替代。

按照惯例,先贴GitHub源码地址,对您有帮助请点一下Star,谢谢

当然,如果是技术大牛团队或者有特殊需求的团队,可以自己写一个定制的弹幕显示框架,但是如果对于一般的小公司来说,技术实力不是很雄厚,时间紧迫的话,建议还是选择弹幕框架,本篇就介绍一个框架BarrageRenderer,也是我们项目中用到的框架。

深入理解Content Transition

这篇文章会深度分析 Content Transitions 和它在 Activity & Fragment Transitions API 中的作用。这篇文章是下面这个系列中的第二篇:

  • Part 1: 在 Activity 和 Fragment 中使用 Transition
  • Part 2: 深入理解 Content Transition
  • Part 3a:深入理解共享元素 Transition
  • Part 3b: 延迟共享元素的 Transition
  • Part 3c: 共享元素回调实践 (coming soon!)
  • Part 4: Activity & Fragment 过渡动画示例(coming soon!)

我们先来总结下在 part 1 中提到的关于 Content Transitions 的知识点,然后
说一说在 Android Lollipop 中是怎样使用它来构建合适的过渡动画。


什么是 共享元素 Transition ?

共享元素 transition 决定了 共享元素 视图(也叫做主角视图)在
Activity/Fragment 场景过渡时的动画效果。共享元素 的动画
在被调用 Activity/Fragment 的 进入/返回 共享元素 transition
<a id="1" href="#b1">(1)</a> 中执行,
可以通过下面的Window/Fragment 方法设置:

  • setSharedElementEnterTransition() - B进入 共享元素 transition ,执行将
    共享元素视图 从 A 中的起始位置移动到它在 B 中的最终位置的动画。
  • setSharedElementReturnTransition() - B返回 共享元素 transition ,执行将
    共享元素视图 从 B 中起始位置移动到它在 A 中的最终位置的动画。

Video 3.1 展示了在 Google Play Music 中是怎样使用共享元素 transition
的。这个 transition 包含两个元素:一个 ImageView和它的父视图 CardView
Transition 期间,CardView 会扩展到全屏或收缩回原状,
ImageView 能在这两个 Activity 里无缝的衔接。

在 part1 里只是简单的介绍了下这个话题,这篇文章将会对 共享元素 transition
做更深度的分析。例如 共享元素 Transition 在底层是如何实现的?都有哪些类型的 Transition 对象可以使用? Transition 期间 共享元素视图 是在哪里怎样绘制的?接下来的几章里
我们会逐个解答这些问题。

新特性与增强

  • Animated: 实现了Animated的toJSON方法 (17f0807) - @wusuopu

修复BUG:使用“检查元素”功能查看动画组件时会产生报错。

  • 让 RefreshControl 正确的被JS控制(9aa37e8) - @janicduplessis

修复BUG:在controlled component来控制RefreshControl时,状态显示错误

  • 增加SwipeableListView (052cd7e 9b1a3c7 2a7f6ae) - @fred2028

看起来像是一个每一个项目都可以被左滑以展示功能菜单的View

  • 为NavigationAnimatedView的场景渲染器增加transition属性。 (55c3086<) - @hedgerwang

为新导航器增加transition属性

  • 让BugReporting支持自定义的源文件 (610cfdc) - @lexs

  • 给元素检查器增加"Open file"(打开文件)按钮 (f203c5d) - @frantic

使你可以直接在元素检查器中点击元素,在电脑上直接查看对应的文件

  • 给react-native的babel预配置集合增加插件 transform-react-jsx-source (858643d) - @frantic

这个插件往JSX里增加了标记信息,用于识别元素所对应的源代码位置。

  • 分支 NavigationAnimatedView为 NavigationTransitioner (<tt>7db7f78</tt>) - @hedgerwang

这个新组件和原来的NavigationAnimatedView类似,稍后会废弃屌原来的NavigationAnimatedView。

不同之处:移除了属性applyAnimation,添加了新属性configureTransition, onTransitionStart和 onTransitionEnd。

  • 将rnpm合并到react-native包中 (149d0b9) - @grabbou
    这在将来可以用于解决各种rnpm与react-native的版本不兼容问题。
  • 2017年09月25日18:42:00 修复了在iOS11下必现EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)的崩溃BUG。
  • 已知bug提示:在替换模式LiveGiftAddModeReplace下使用animatedWithGiftModel方法将导致UI效果不理想的bug。建议是animatedWithGiftModel方法使用于LiveGiftAddModeAdd模式。

下面我们看一下框架的star数目和作者。

Content Transition 是什么?

Content transition 决定了非共享元素 View (也称为 transitioning view) 在
Activity & Fragment 过渡期间是如何进入或退出场景的。出于 Google 新的设计语言
Material Design , content transitions 允许我们协调 Activity/Fragment 中每一个
view 的进入和退出 transition,轻松搞定流畅的屏幕切换动作。
开始使用 Android Lollipop,调用下面这些Window 和
Fragment 方法可以通过程序设置 content transitions :

  • setExitTransition() - 当 A 启动 B 时, A 中 views 离开场景的退出过渡动画

  • setEnterTransition() - 当 A 启动 B 时, B 中 views 进入场景的进入过渡动画

  • setReturnTransition() - 当 B 返回 A 时, B 中 views 离开场景的返回过渡动画

  • setReenterTransition() - 当 B 返回 A 时, A 中 views 进入场景的重入过渡动画

(注:A 和 B 是Activity 见 part 1)。

Video 2.1

  • Content transitions in the Google Play Games app (as of v2.2). Click to play.

Video 2.1作为示例阐明了在 Google Play Games app 中是如何使
用 content transitions 实现流畅的 activitiy 切换动画。当第二个 activity 启动,
它的进入 content transition 轻轻地从屏幕底部边缘将头像推入场景。按下返回按钮后,
第二个 activity 的返回 content transition 将图层分成上下两块,分别推出屏幕。


目前为止我们对 content transitions 的分析仅仅停留在表面,一些重要的问题仍然没有涉及。
例如 Content Transition 在底层是如何实现的?都有哪些类型的 Transition 对象可以使用?框架是如何确定哪些 view
是 transitioning view? 在 content transitions 中一个 ViewGroup 和它的子视图能不能当成一个整体
执行动画?下面我们就来一个一个解答这些问题。


深入共享元素 Transitions 底层

之前的文章已经介绍过 Transition 的两个主要任务分别是获取目标视图的 开始&结束 状态和创建这两个状态间视图的过渡动画(Animator)。共享元素 Transition 也一样:
在创建动画前需要捕获每一个
共享元素视图的起始和结束状态(就是共享元素在 调用/被调用 Activity/Fragment
里的位置,大小和外观)。有了这些信息 共享元素 Transition 就可以确定每一个 共享元素
视图应该执行的动画。

和 Content Transitions 的底层相似,框架通过在运行时明确的
更改每个 共享元素视图 的属性将这个状态信息提供给 共享元素 Transition 。
更准确地说 Activity A 启动 Activity B 时将会出现以下事件:<a id="2" href="#b2">(2)</a>


  1. Activity A 调用 startActivity() 构造,测量,布局了一个
    最初背景色为透明的半透明窗口 Activity B
  2. 框架将 B 中每一个共享元素视图复位到对应的原来在 A 中时的位置,接着 B 的进入 transition 捕获 B 中所有共享元素视图的起始状态。
  3. 框架将 B 中每一个共享元素视图复位到对应的在 B 的最终位置,接着 B 的进入 transition 捕获 B 中所有共享元素视图的结束状态。
  4. B 的进入 transition 比较所有共享元素视图的起始和结束状态,根据它们的不同
    创建一个 Animator
  5. 框架命令 A 隐藏共享元素视图,并运行返回的 AnimatorB 中的
    共享元素视图到位之后,B 的窗口背景在 **A **上逐渐显示,直到 B
    完全的显示出来,transition 运行完毕。

Content transitions 是根据每个过渡视图的可见性变化来调节的,共享元素 transition
是根据每个共享元素视图的位置,大小和外观的变化来调节的
。从 API 21 开始,框架提供了
几个自定义共享元素场景切换动画的 Transition 实现。

  • ChangeBounds - 捕获共享元素布局边界根据不同构造动画。
    ChangeBounds 在共享元素 Transition 中经常使用,大多数共享元素在两个
    Activity/Fragment 间会有大小 或/和 位置不同。
  • ChangeTransform - 捕获共享元素缩放和角度,
    根据不同构建动画<a id="3" href="#b3">(3)</a>。
  • ChangeClipBounds - 捕获共享元素的 clip bounds)
    (剪辑边界) ,根据不同构建动画。
  • ChangeImageTransform - 捕获共享元素 ImageView 的
    变换矩阵( transform matrices) ,根据不同构建动画。结合 ChangeBounds
    可以让 ImageView
    无缝的改变大小,形状和 ImageView.ScaleType。
  • @android:transition/move - 一个 TransitionSet ,同时执行上面四种
    transition 。在 part 1 里提到过,如果没有明确的声明 进入/返回 共享元素
    transition ,框架会默认运行这个 transition。

在上面的例子中,我们还可以发现 共享元素视图实例并没有在 Activities/Fragments 间
“共享”
。事实上,进入/返回 共享元素 transitions期间,用户看到的绝大多数东西都是在
B 的 content view 中绘制的。框架并没有从 AB
传递 共享元素视图实例,
而是采用了不同的方法实现相同的视觉效果。当 A 启动 B ,框架收集 A
中共享元素的所有相关信息,并传递给 B。接下来 B 使用这些信息初始化
共享元素视图的起始状态(它们在 A 中时对应的大小,位置和外观)。Transition
开始时,B 中除了共享元素视图外的所有东西都被初始化为对用户不可见。Tansition
的执行过程中,框架将 B 的 Activity 窗口逐渐显示,直到 B
中共享元素结束动画窗口变为不透明。


BUG修复

  1. 在初始化react实例的时候阻塞对JS模块的调用(a1ba091) - @astreet
  • 修复NavigationCard的属性类型检查。 (b1cd1cb) - @hedgerwang

  • 修复RefreshControl的访问冲突(fbce30) - @janicduplessis

  • NavigationExperimental: didFocus 事件应当在动画结束之后再调用。 (8975bb8) - @hedgerwang

  • 修复当初次渲染RefreshControl就要求刷新的时候并没有开始刷新的问题。(cac5ce3) - @aforty

  • 修复NavigationPropTypes.SceneRenderer是一个普通对象的问题(0e997c6) - @joenoon

现在拆分了SceneRenderer和SceneRendererProps,解决了类型检查时候导致的问题。

  • 解决 SwipeableRow 的显示问题 (5146775) - @fred2028

默认的icon size会导致拉出的图片溢出到SwipeableRow之上。现在所有的样式都必须由调用者传入,由调用者自行控制相关的尺寸来达到最佳适应。

  • 解决了95%的WindowedListView乱跳的问题 (5e91a2a) - @sahrens

  • 解决了SwipeableRow在Android下闪烁和在iOS下晃动的问题(62e588b) - @fred2028

  • 解决ListView的onChangeVisibleRows所汇报的行数不正确的问题(0aea74e) - @dmueller39

sbf282.com 2star数目

Content Transitions 底层深入

上篇文章我们说过 Transition 的两个主要职责分别是获取目标视图的开始结束状态和创建这两个状态间的过渡动画。同样,框架必须先改变每个 transitioning view 的可见性并将状态信息交给 content
transition ,它才能创建过渡动画。更准确的说,当 Activity A 启动 Activity B 将会出现以下事件:<a id="1" href="#b1">(1)</a>

  1. Activity A 调用 startActivity()

    • 框架首先会遍历 A 的 view 层次结构,确定当 A 的退出 transition 运行后有哪些
      transitioning views 会退出场景。
    • A 的退出 transition 捕获 A 中 transitioning views 的起始状态。
    • 框架将 A 中所有 transitioning views 设置为不可见
    • 在下一个画面中,A 的退出 transition 捕获 A 中所有 transitioning views 的结束状态。
    • A 的退出 transition 比较每一个 transitioning view 开始和结束状态的不同,
      并基于这些信息创建一个 Animator,最后运行 Animator 将所有 transitioning views
      移出场景。
  2. Activity B 被启动

    • 框架遍历 B 的 view 层次结构, 确定当 B 的进入 transition 运行后有哪些
      transitioning views 会进入场景。
    • B 的进入 transition 捕获 B 中 transitioning views 的起始状态。
    • 框架将 B 中所有 transitioning views 设置为可见
    • 在下一个画面中,B 的进入 transition 捕获 B 中所有 transitioning views 的结束状态。
    • B 的进入 transition 比较每一个 transitioning view 开始和结束状态的不同,
      并基于这些信息创建一个 Animator,最后运行 Animator 将所有 transitioning views
      移入场景。

框架通过在可见不可见之间切换每个 transitioning view 的可见性来保证
content transition 能够获得用来构建目标动画所需要的状态信息。
显然所有的 content Transition 对象至少要能够获取和记录每个 transitioning view
起始和结束状态的可见性。还好 Visibility 这个抽象类已经提供了这个功能 :
需要创建并返回 (让 view 进入/退出场景的) AnimatorVisibility
子类只需要实现 onAppear()) 和 onDisappear()) 这两个工厂方法。
从 API 21 开始,有三个已经写好的 Visibility 实现( Fade, SlideExplode),可以使用它们来构建 Activity 和 Fragment 的 content transitions。
有必要的话也可以自己实现 Visibility 类达到想实现的效果。后边的文章会有具体介绍。


使用共享元素 Overlay <a id="4" href="#b4">(4)</a>

最后,如果想要完全理解共享元素 transition 的运作,我们必须先说说共享元素 overlay。
可能不是很明显,共享元素默认是在整个窗口视图层的顶层 ViewOverlay
上绘制
。简单介绍下 ,
ViewOverlay 这个类是在 API 18 中为了方便在视图层顶层
绘制引入的。添加到视图 ViewOverlay 之中的Drawable
和 view (甚至是一个 ViewGroup 的子类) ,
将会被绘制在视图的最上层。这就解释了框架为什么
默认选择在窗口视图层的 ViewOverlay 中绘制共享元素。
共享元素视图应该是贯穿整个 transition 的焦点;
如果 transitioning views 意外的绘制在共享元素之上就会
破坏这个效果<a id="5" href="#b5">(5)</a>。


虽然共享元素默认绘制在共享元素的 ViewOverlay 之中,但是
框架也提供了关闭 overlay 的方法,只要调用
Window#setSharedElementsUseOverlay(false))
就可以了。如果你关闭了 overlay
,要留意这样做可能会引起的副作用。例如,Video 3.2
执行了一个简单的共享元素 transition 两次,
一次开启和一次关闭 共享元素 overlay 。第一次达到了预期想要的结果,
第二次关闭 overlay 后运行的效果不理想。Transition view 从底部向上移入
调用 Activity 的 content view 时挡住了部分 共享元素 ImageView 。虽然
可以改变在 View 上绘制视图的顺序或者通过在共享元素 parent 里调用
setClipChildren(false) 这些旁门左道来修复问题,但是与可能带来的维护问题
相比真是得不偿失。总之,除非你感觉必须要关掉共享元素 overlay 才能达到你想要的效果,
其他情况尽量不要关闭它,这样会保持代码简洁,并且共享元素 transition 效果更引人注目。

安卓

  • 目标
  • 版本更新说明
  • 最新版本
  • 快速使用
  • 自定义配置

可以看见,star数目不是很多,但是也是可以的了,毕竟无法和AFNetworking这种非常流行的框架相比,每一个app都要有网络申请,但是不是每个app都会有弹幕的,这和行业限制也有一定的关系。

Transitioning Views 和 Transition Groups

直到现在,我们已经假设 content transitions 操作一组叫做 transitioning views 的非共享 view 。
在这节中,我们将探讨 Transition 框架如何确定哪些 View 是非共享 View,以及如何使用 transition group 深度定制框架

Transition 开始前,框架会在 Activity 窗口(或 Fragment) 的视图层上执行一个递归的搜索,用来
构建 transitioning views 的集合。这个搜索通过对图层的根视图递归调用重写的ViewGroup#captureTransitioningViews 方法启动,部分源码如下:

/** @hide */
@Override
public void captureTransitioningViews(List<View> transitioningViews) {
    if (getVisibility() != View.VISIBLE) {
        return;
    }
    if (isTransitionGroup()) {
        transitioningViews.add(this);
    } else {
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            child.captureTransitioningViews(transitioningViews);
        }
    }
}

Video 2.2

  • A simple Radiohead app that illustrates a potential bug involving transition groups and WebViews. Click to play.

这个递归调用很简单: 框架遍历树的每一层,直到找到一个可见的leaf view (子视图)或者一个 transition group。Transition groups 本质上允许我们在 Activity/Fragment 的 transition
期间将全部 ViewGroups 当作一个整体执行过渡动画。如果一个 ViewGroup
isTransitionGroup ()) <a id="2" href="#b2">(2)</a>方法返回值为 true,它和它的子视图会被当作一
个整体来执行过渡动画。否则,这个递归搜索会继续执行下去, 这个 ViewGroup 的子视图在动画期间
会执行自己的独立的过渡动画。搜索最终会返回一个全部由 content transition
执行动画的 transitioning views 集合 。<a id="3" href="#b3">(3)</a>


上面的 Video 2.1 展示了 transition groups 的效果。在 enter transition ,
用户头像是作为一个单独的 View 进入屏幕,return transition 时却是和包含它的 parent
ViewGroup 一起消失。在 Google Play Games 里可能用了一个 transition group
来实现在返回前一个 activity 时,让当前场景拦腰斩断的效果。


有时 transition groups 还被用来修复 Activity/Fragment transitions 中诡异的 bugs。
例如,Video 2.2中: 调用 Activity 显示了一个电台司令专辑图的网格布局,
被调用 Activity 展示了一个背景标题图,一个共享元素专辑封面图还有一个 WebView
这个 App 使用了一个和 Google Play Games app 类似的 return transition,将背景图和底部的
WebView 分别推出屏幕。然而这里有个小故障导致 WebView 不能流畅的退出屏幕。

好吧,错误在哪呢?原来 WebView 是一个 ViewGroup,因此在默认情况下 WebView 不会被当作 transitioning view
的。当 return transition 被执行时,WebView 会被完全忽略,直到过渡动画结束才会被移除屏幕。
找到问题就好解决了,只要在 return transition 开始前调用 webView.setTransitionGroup(true)
就能修复这个bug。


结语

综上所诉,这篇文章讲了三个重点:

  1. 共享元素 transition 确定 共享元素视图(主角视图) 从一个 Activity/Fragment 移动到
    另一个其间场景过渡的动画。
  2. 共享元素 transition 是根据每一个 共享元素视图 的位置,大小,和外观的变化调节的。
  3. 共享元素默认是绘制在窗口视图的顶层 ViewOverlay 上面的。

希望这篇文章对你有所帮助 ~


1 Note that the Activity Transition API gives you the ability to also specify exit and reenter shared element transitions using the setSharedElementExitTransition() and setSharedElementReenterTransition() methods, although doing so is usually not necessary. For an example illustrating one possible use case, check out this blog post. For an explanation why exit and reenter shared element transitions are not available for Fragment Transitions, see George Mount's answer and comments in this StackOverflow post. ↩

2 A similar sequence of events occurs during the exit/return/reenter transitions for both Activities and Fragments. ↩

3 One other subtle feature of ChangeTransform is that it can detect and handle changes made to a shared element view's parent during a transition. This comes in handy when, for example, the shared element's parent has an opaque background and is by default selected to be a transitioning view during the scene change. In this case, the ChangeTransform will detect that the shared element's `parent is being actively modified by the content transition, pull out the shared element from its parent, and animate the shared element separately. See George Mount's StackOverflow answer for more information. ↩

4 Note that this section only pertains to Activity Transitions. Unlike Activity Transitions, shared elements are not drawn in a ViewOverlay by default during Fragment Transitions. That said, you can achieve a similar effect by applying a ChangeTransform transition, which will have the shared element drawn on top of the hierarchy in a ViewOverlay if it detects that its parent has changed. See this StackOverflow post for more information. ↩

5 Note that one negative side-effect of having shared elements drawn on top of the entire view hierarchy is that this means it will become possible for shared elements to draw on top of the System UI (such as the status bar, navigation bar, and action bar). For more information on how you can prevent this from happening, see this Google+ post. ↩

  1. Activity Transition API 也提供了
    setSharedElementExitTransition()setSharedElementReenterTransition()
    这两个方法来设置 退出/重入 共享元素过渡,虽然通常来说是不必要的。
    这篇文章介绍了一个可能会遇到的用例。在这个 stackoverflow
    提问中 George Mount 的回答解释了为什么 退出/重入 共享元素 transition 在
    Fragment Transitions 中不可用。 <a id="b1" href="#1">↩</a>

  2. Activities 和 Fragments 的 退出/返回/重入 transition 过程中出现事件序列相似 <a id="b2" href="#2">↩</a>

  3. ChangeTransform 还有一个超赞的特性,它可以检测并处理共享元素父视图过渡期间
    的改变。当共享元素父视图有一个不透明背景,在场景变换过程中默认被选为
    transitioning view 时,ChangeTransform 就有了用武之地。如果它检测出
    共享元素父视图已被 content transition 更改,就会将共享元素提取出来,单独执行
    共享元素的动画。StackOverflow answer 这里有 George Mount
    的详细说明。
    <a id="b3" href="#3">↩</a>

  4. 注意,这部分只与 Activity Transition 有关。和Activity Transition 不同,Fragment Transition
    期间共享元素默认不在 ViewOverlay 中绘制。尽管如此,你仍可以使用 ChangeTransform
    transition 来达到相似的效果,如果它检测到父视图改变了,就会把共享元素绘制在
    ViewOverlay 的顶层。StackOverflow 这里有更多信息。
    <a id="b4" href="#4">↩</a>

  5. 注意,将共享元素绘制在整个图层最顶层也有一些负面效果。有可能
    会将共享元素绘制在 System UI 之上(比如 status bar, navigation bar还有 action bar)。
    解决方法看这里 Google+ post。
    <a id="b5" href="#5">↩</a>


新特性与增强

  • 为HorizontalScrollView增加pagingEnabled属性 (a3146e4) - @dmmiller

  • 开源的SwipeRefreshLayoutRecordingModule (457e348) - @bestander

  • 实现了TextInput的returnKeyType/returnKeyLabel (dd8caf4) - @Bhullnatik

  • 为RefreshControl增加了 progressViewOffset属性 (<tt>f7ce0c1</tt>) - @UnoDeTantos

  • 现在可以通过属性来禁用/锁定Android下ViewPager的滑动 (<tt>31250ad</tt>) - @kevinejohn

  • 解决当React Context还未初始化完毕时点击RootView时的访问冲突问题。(fd37666) - Olivier Notteghem

  • 为ScrollView增加FpsListener (b67d4a2) - Nathan Spaun

  • 现在还没有实际作用不过将来这个将被用于记录和跟踪滚动条的滚动性能。

  • 升级到OkHttp3 (6bbaff2) - @AndrewJack

  • 解决 NetworkingModule 构造时添加拦截器(interceptors)时出现的问题 (921d0de) - @bestander

  • 当忘记执行react-native start的时候,提示更友好的信息(c634ea](https://github.com/facebook/react-native/commit/bc634ea35044c84295904a6bb5f04e2d52ba688e))) - @codeheroics

下面我们在看一下框架的作者。

结语

总之,这篇文章讲了三个重点:

  • Content transition 决定了 Activity/Fragment 中非共享元素视图(被称为 transitioning views)
    在 Activity/Fragment transition 期间如何进入或退出场景。
  • Content transitions 被触发是因为它的 transitioning views 可见性改变 ,并且应该总是继承
    Visibility 这个抽象类。
  • Transition groups 可以让我们在 content transition 期间将 ViewGroups
    当作一个整体执行过渡动画。

希望这篇文章能够帮到你,欢迎留下评论~


  1. Activities 和 Fragments 在 return/reenter transitions 期间出现的一系列事件相似。
    <a id="b1" href="#1">↩</a>
  2. 如果 ViewGroup 有一个非空的 background drawable 或者非空的默认 transition name 那么
    isTransitionGroup() 将返回 true (所述方法文档))
    <a id="b2" href="#2">↩</a>
  3. 当 transition 运行时,任何在 content Transition 对象中被明确地 added)或
    excluded) 的 view 也会被考虑。<a id="b3" href="#3">↩</a>

BUG修复

  • 修复通过Controlled模式使用Android Picker时的问题 (0cd2904>) - @spicyj

  • 使得Modal弹框时的状态栏保持沉浸式 (191d278) - @jemise111

  • 为较老的Android设备增加React队列所允许的栈大小 (d4f6f61) - @nikki93

  • 在发送触摸时间时携带时间戳信息,以使得反馈更为准确 (f2c1868) - @dmmiller

  • 弹幕过几秒自动消失
  • 实现A用户弹幕出现时,B用户发送礼物,B用户弹幕在A用户弹幕下方,A/B用户弹幕存在时,A/B用户连续发送礼物,弹幕显示的礼物数量增加,谁的礼物数量较大,谁的弹幕在上方。
  • A/B用户弹幕存在时,C用户发送礼物,A/B用户中较早出现的弹幕被替换成C用户的弹幕数据,并且C用户的弹幕处于下方

sbf282.com 3

iOS

<a ></a>版本更新:

  • 大致实现了不同用户增加弹幕的效果

sbf282.com 4

  • 实现了用户连续发送数字增加效果
  • 实现了新增弹幕从空位出现的效果

sbf282.com 5

  • 实现了第二个用户之后送礼物替换较早的弹幕效果

sbf282.com 6

  • 实现了上面的视图移除后,正在连击的下面的视图移动到上面的效果

sbf282.com 7

  • 实现了目标效果

sbf282.com 8

  • 实现了自定义最大礼物数量的需求

sbf282.com 9

  • 新增了自下而上的展现效果

sbf282.com 10

可见,这里他比较牛逼的框架,也就BarrageRenderer这个了,但是很值得我们学习了。

新特性与增强

  • NavigatorIOS: 导出了interactivePopGestureEnabled属性 (4d2c72b) - @rigdern

该属性可以禁用左滑返回上一页。

  • 使得root view 的背景颜色更为明确(fa5d1fe) - @shaneosullivan

  • 在IOSImagePicker的回调返回图片的宽高 (df40f48) - @thans

  • 使得<Text>标签内可以内嵌View (fe5c0d2) - @rigdern

  • 为红屏增加“复制栈”的功能 (5047f6f) - Chris Evans

V1.7

  • 解决了一个视图显示BUG,现在几乎不会出现该BUG。

sbf282.com 11

下面我们看一下框架有那些代码,如下图。

BUG修复

  • 修复了LocationObserver的distanceFilter缓存问题(2310494) - @jrichardlai

  • ScrollView: 触发onScroll事件时现在总是会发送最终的滚动位置(deef8aa) - @rigdern

  • 当设置了scrollEventThrottle时,以前的版本并不保证最终的位置能被发送。

  • 修复了在Image loader的数组中包含nil会导致崩溃的问题 (ed1ee9b) - @nicklockwood

  • 隐藏软键盘时使用了正确的动画函数(03edc75) - @rigdern

  • 修复 NativeEventListener注销的问题 (516bf7b) - @nicklockwood

V1.8

  • 支持向左移除弹幕,支持左边出现动画效果,增加弹幕移除后的回调代理。

sbf282.com 12

sbf282.com 13框架组成

0.26 正式版发布

<a ></a>V1.901测试版

  • 支持从1增加到某个数字的动画(在替换模式LiveGiftAddModeReplace下存在小bug,如果有某猿能提供帮助将不胜感激)
  • 支持队列模式(如下GIF图,注意看鼠标~)
  • 移除的模式增加无动画移除
  • 修改了部分枚举名称更符合OC语法
  • 暴露了动画时长属性,方便开发者依据不同情况自行修改

sbf282.com 14

可以看见,代码组成并不少。

新功能

  1. 升级至react15.0.2
  2. 支持在WebSockets中发送和接收二进制数据
  3. 在CLI中添加--version
  4. 在react-native bundle 中添加--reset-cache 重置文件缓存
  5. 为js文件添加encode格式/哈希签名

<a ></a>快速使用

  • 使用的第三方库:

    • Masonry
    • SDWebImage
  • 两个模型:LiveGiftListModelLiveUserModel

    • LiveGiftListModel是用来显示弹幕上右侧礼物图片picUrl和打赏的语句rewardMsg的,礼物有type字段
    • LiveUserModel是用来显示送礼物的人的名称name和头像iconUrl
  • V1.4只需要导入#import "LiveGiftShow.h"

  • V1.5只需要导入#import "LiveGiftShowCustom.h",具体使用可参考V15TestVC.m,不建议同时使用LiveGiftShow.hLiveGiftShowCustom.h

  • V1.6只需要导入#import "LiveGiftShowCustom.h",具体使用可参考V15TestVC.m,向V1.5兼容。如有需要更新,只需要将LiveGiftShowCustom.hLiveGiftShowCustom.m替换为V1.6版本的文件即可。

  • @property (nonatomic ,weak) LiveGiftShow * giftShow;

 - (LiveGiftShow *)giftShow{ if (!_giftShow) { LiveGiftShow * giftShow = [[LiveGiftShow alloc]init]; [self.view addSubview:giftShow]; _giftShow = giftShow; [giftShow mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo; make.height.equalTo; make.left.equalTo(self.view.mas_left); make.top.equalTo(self.view.mas_top).offset; }]; } return _giftShow;}
  • 在开发中使用
LiveGiftShowModel * listModel = [LiveGiftShowModel giftModel:self.giftArr[3] userModel:self.firstUser];[self.giftShow addGiftListModel:listModel];

即可完成接入。每一次点击只需要[self.giftShow addGiftListModel:listModel];即可自动计数加一。最高支持显示9999。

前面介绍了框架的基本情况,下面我们说一下框架深入等方面。

Bug修复

  1. 修复潜在的“Should never unset includeInLayout”不变
  2. 修正初始场景渲染NavigationExperimental
  3. 修正了modalbox不正确的布局
  4. 修复ART模式中画边距bug
  5. 使用相对路径时,修复获取文件错误bug
  6. 本地修复流程定义
  7. 去掉尺寸固定视图导出的常数
  8. 修复package.json脚本里使用的react native CLI
  9. 修正WebSocket兼容性
  10. 修复JSWatchdog复位
  11. 修复Animated的setValue在native正常工作
  12. 固定路径再生运行时
  13. 修复HMR预设

特别说明

  • 在1.5+版本之后,只需要替换LiveGiftShowCustom.hLiveGiftShowCustom.m基本上即可完成版本更新。
  • 在V1.6+版本中,LiveGiftShowCustom.m
#pragma mark - 初始化+ (instancetype)addToView:superView{ LiveGiftShowCustom * v = [[LiveGiftShowCustom alloc]init]; [superView addSubview:v]; //布局 [v mas_makeConstraints:^(MASConstraintMaker *make) { //这个改动之后要注意修改LiveGiftShowView.h的kViewWidth make.width.equalTo; //将主视图的高度设置0.01,保证弹幕后面的视图能响应点击事件。 make.height.equalTo; //这个可以任意修改 make.left.equalTo(superView.mas_left); //这个参数在的设定应该注意最大礼物数量时不要超出屏幕边界。 make.top.equalTo(superView.mas_top).offset; }]; v.backgroundColor = [UIColor clearColor]; return v;}

1. 框架发起原因

这里要引用作者自己的话了。弹幕实质是多个精灵的时间上的渲染方式。 PC/Web上已经有很成熟的解决方案了; Android上比较有名的是BiliBili开源的DanmakuFlameMaster, 但是开源社区尚没有比较好的iOS弹幕渲染器.觉得在二次元文化逐渐渗透的今天,视频弹幕已经是很重要的一种情绪表达方式了。

ANDROID版

<a ></a>自定义配置

  • LiveGiftShow V1.4管理所有弹幕的视图,在V1.7之后移除。
  • LiveGiftShowCustom V1.5之后管理所有弹幕的视图
两个弹幕之间的高度差 两个交换动画时长
kGiftViewMargin kExchangeAnimationTime
50.0 0.25
  • LiveGiftShowView一个弹幕的视图
弹幕背景宽 弹幕背景高 送礼者名称字号 送礼者名称文字颜色 礼物寄语字号 礼物寄语文字颜色
kViewWidth kViewHeight kNameLabelFont kNameLabelTextColor kGiftLabelFont kGiftLabelTextColor
240.0 44.0 12.0 whiteColor 10.0 orangeColor
每个数字图片宽度 弹幕几秒后消失 数字改变动画时长 弹幕消失动画时长
kGiftNumberWidth kTimeOut kNumberAnimationTime kRemoveAnimationTime
15.0 3 0.25 0.5
  • 如果在使用过程中遇到问题,或者想要与我分享/吐槽/建议/意见,我会第一时间回复大家~jonhory@163.com

2. 特点

  • 提供过场弹幕与悬浮弹幕支持,支持图片弹幕与文字弹幕。
  • 提供图文弹幕接口attributedText,可按照demo中的指示生成图文混排弹幕。
  • 弹幕字体可定义: 颜色、边框、圆角、背景、字体等皆可定制。
  • 自动轨道搜寻算法,新发弹幕会根据相同方向的同种弹幕获取最佳运动轨道。
  • 支持延时弹幕,为反复播放弹幕提供可能,支持与外界的时间同步。
  • 独立的动画时间系统, 可以统一调整动画速度。
  • 特制的动画引擎,播放弹幕更流畅,可承接持续的10条/s的弹幕流速。
  • 丰富的扩展接口,实现了父类的接口就可以自定义弹幕动画。
  • 概念较清晰,可以为任意UIView绑定弹幕,当然弹幕内容需要创建控件输入。
  • 因为作者记性比较差,所以在很多紧要处添加了注释,理解代码更容易。

新功能

  1. 添加ViewPager禁用滚动的能力
  2. 添加揭露从Java同步JS的能力
  3. 添加从文件系统加载Boost库的选项
  4. 添加Animated.add支持原生动画
  5. 添加支持setChildren

3. 弹幕效果演示

下面我们就看一下弹幕效果。

sbf282.com 15弹幕效果演示1sbf282.com 16弹幕效果演示效果2

视频演示地址

Bug修复

  1. 通过不再承担修复崩溃的AdsManager只有一个反应上下文存在一次
  2. 修正使用弹出窗口引起的崩溃
  3. 修复事件冒泡机制
  4. 修复setFontWeight方法的NullPointerException
  5. 修复mapView 的IndexOutOfBoundsException
  6. 修复PullRefreshViewAndroid中未定义引用bug
  7. 修复事件冒泡出来机制
  8. 修复ReactNativeART绘弧图bug
  9. 修复TextInput 的ClassCastException异常
  10. 修复textShadowOffset没有宽度或高度错误

4. 使用方式

  • 下载版本库,进入BarrageRendererDemo目录。 运行pod update拉取相关库,即可以运行BarrageRendererDemo.xcworkspace
  • 也可以在您工程的podfile中添加一条引用:pod 'BarrageRenderer','1.9.1'并在工程目录下的命令行中运行 pod update,(CocoaPods 版本 0.39)。
  • 或者尝试使用 2.1.0 版本,此版本使用更方便,在部分特殊情况下的性能也有所提升。或者将代码下载下来, 将BarrageRenderer/目录添加到您的工程当中
  • 在需要使用弹幕渲染功能的地方 #import<BarrageRenderer/BarrageRenderer.h>创建BarrageRenderer,添加BarrageRenderer.view,执行start方法, 通过receive方法输入弹幕描述符descriptor, 即可以显示弹幕,详见demo。
  • demo的基本功能演示了:如何在view上增加一条弹幕,如何启动、停止、暂停、恢复弹幕播放,如何减速弹幕的运动速度。
  • demo的高级功能演示了:如何使用自定义方式添加图文混排弹幕,如何支持录播中在固定时间点显示固定弹幕的逻辑。

IOS版

5. 基本使用

一般只需要在- viewDidLoad里创建一个 BarrageRenderer对象,并将其view add 到你想要添加弹幕动画的 view 上,配置就结束了。当你想要添加一条弹幕到屏幕上的时候,你只需要创建一个弹幕描述符 BarrageDescriptor, 为其指定弹幕Sprite 的类名,然后通过 params 设置一些属性, 调用 BarrageRenderer 的 receive 方法即可成功将弹幕显示在屏幕上。弹幕支持的属性可参照 BarrageSpriteProtocol.h文件 以及在 BarrageSprite 族的属性。

重大更改

  1. 为所有签入的项目添加标志“-lc ++”

6. 动态移除弹幕

2.1.0 新增特性

在某些情况下,你可能需要从屏幕中动态地移除弹幕。2.1.0版本为此提供了一个默认的弹幕标识符 params[@"identifier"]以及 一个移除弹幕的方法- removeSpriteWithIdentifier:(NSString *)identifier;。 举例而言,你可以在用户点击弹幕的时候,移除弹幕,代码如下:

_weak BarrageRenderer *render = _renderer; descriptor.params[@"clickAction"] = ^(NSDictionary *params){ [render removeSpriteWithIdentifier:params[@"identifier"]]; };

新功能

  1. 添加在LayoutAnimation可以删除动画
  2. 调度本地通知时支持添加图标数量和警报措施的支持

7. 更新弹幕视图

2.1.0 新增特性

有时候,你想要为你的弹幕精灵 view 添加动画。当然,你可以使用 animation 或者 NSTimer。由于 BarrageRenderer 整体由 CADisplayLink 驱动,你可以借用 BarrageRenderer的时钟,来更新你的精灵 view 。这样做的好处在于,当你通过 BarrageRenderer 暂停弹幕时,你的 弹幕精灵 view 也将暂停。为此,你可以在自定义弹幕精灵 view 的时候,实现协议方法- updateWithTime:(NSTimeInterval)time来依据时间更新你的 view 。连贯起来就成了动画。你可以参考 demo 中 AvatarBarrageView 类的实现。

需要注意的是,- updateWithTime:(NSTimeInterval)time中不要放置过多的计算逻辑。在大量弹幕下,这样有可能造成动画的卡顿。

Bug修复

  1. 解决应用程序在启动过程中死锁
  2. 修复RCTJavaScriptContextCreatedNotification
  3. 修复CJK TextInput 自动完成模式
  4. 修正了未设置文本大小造成RCTShadowText返回一个无限的高度bug
  5. 修复ookieMap在RCTJSCExecutor导致内存泄漏bug
  6. 修复与HTTP返回301时图像显示无响应
  7. 修正了红盒子按一个堆栈帧无法打开,编辑

8. 设置靠边位置

1.9.0 版本支持为过场弹幕与悬浮弹幕设置"靠边"属性。对于过场弹幕,可设置side(BarrageWalkSide)属性;对于悬浮弹幕,可设置side(BarrageFloatSide)属性。代码表现为:

descriptor.params[@"side"] = @(BarrageWalkSideRight); // 过场弹幕中,靠右侧行驶

descriptor.params[@"side"] = @(BarrageFloatSideLeft); // 悬浮弹幕中,靠屏幕左侧堆叠

0.25 正式版发布

9. 设置隐入隐出

1.8.0 版本新增属性,仅对悬浮弹幕有效,设置如下:

descriptor.params[@"fadeInTime"] = @; // 隐入时间descriptor.params[@"fadeOutTime"] = @; // 隐出时间

重大变更

在react-native中引用React的做法发生了变更(在当前版本老的做法会提出警告,如何屏蔽警告点这里。在下一版本将会报错):

之前

import React, { Component, View } from 'react-native';

现在

import React, { Component } from 'react';
import { View } from 'react-native';
具体哪些属于React,哪些属于React Native,可以参考这篇帖子(需要科学上网)。

我摘录如下:

"react":

  • Children
  • Component
  • PropTypes
  • createElement
  • cloneElement
  • isValidElement
  • createClass
  • createFactory
  • createMixin

"react-native":

  • hasReactNativeInitialized
  • findNodeHandle
  • render
  • unmountComponentAtNode
  • unmountComponentAtNodeAndRemoveContainer
  • unstable_batchedUpdates
  • View
  • Text
  • ListView
  • ...
  • 以及其他所有的原生组件。

10. 图文混排弹幕

最简单的弹幕只是文本, 但有时候你可能需要添加emoji表情或者图片上去。emoji表情是UTF字符集原生支持的,对待他和其他的文本字符没有区别;对于图片,你有两种方式可以添加图片弹幕, 一种是使用 attributedText 设置属性文本,一种是自定义view。自定义 view 可以参考 BarrageWalkImageTextSprite。 需要注意的是,如果 - bindingView方法返回的是你自定义的 view,你需要覆盖你自定义 view 的- sizeThatFits方法,返回正确的 view 大小。

V2版本中,bindingView 方法被废除,你需要通过 descriptor.params[@"viewClassName"]指明 sprite所要关联的 view 类。

新功能

  1. 添加支持JavaScript的第三方调试器
  2. 添加WindowedListView页脚包装
  3. 添加了支持缺少XHR的响应-
  4. 添加用于预读远程图像Image.prefetch的缓存
  5. 添加ES2015函数到babel的变换 - 855c0cc
  6. 添加重新加载非QWERTY键盘模拟器说明
  7. 添加使用XMLHttpRequest Android和iOS时超时处理函数onTimeout

11. 直接在 Sprite 子类中布局元素

你可能在方法 - bindingView 中创建了许多视图元素,而并非返回一个自定义 view,因此,这时候你并不方便自定义 view 的 - sizeThatFits方法,为此你可以选择覆盖 BarrageSprite 的 size 属性的- size 方法,在此方法中返回你的弹幕 view 的大小。当然,在 - bindingView里你要设置各个子 view 的位置,以及处理一些可变大小元素比如 UILabel 的布局问题。

V2 版本中,bindingView 方法被废除,相关的子 view 布局则写在sprite关联的 view 类中。

弃用

  1. 弃用警告ReactNative.addons
  2. 废弃区分web与移动程序的警告

本文由胜博发-编程发布,转载请注明来源:Transitions APIsbf282.com: 中的作用,可以自己写一个