如何循环揭示整个活动

时间:2015-04-06 03:50:20

标签: android android-5.0-lollipop

我尝试使用android:windowEnterTransitionandroid:windowExitTransition,但这似乎会为活动中的每个视图设置动画,即分别显示每个视图。如何使用内容为整个活动制作动画?两个活动之间没有共享元素。

2 个答案:

答案 0 :(得分:2)

有几种方法可以为整个活动设置动画。最有效的机制是使用Window Transitions。它们针对Window进行操作,因此不需要在每个帧上重绘内容。缺点是操作仅限于较旧的动画框架。

通常,您使用样式指定窗口动画。你可以在这里看到它是如何完成的:Start Activity with an animation

您还可以使用overridePendingTransition或ActivityOptions.makeCustomAnimation

如果要使用棒棒糖活动过渡框架,可以使用windowEnterTransition。如果您只想操作内容,请将最外面的ViewGroup设置为:

<WhateverViewGroup ... android:transitionGroup="true"/>

您可能希望为视图组指定名称或ID,并在输入转换中使用它,以便它仅定位该组。否则它会以状态栏背景为目标。

如果您希望它对整个Window内容进行操作:

getWindow().getDecorView().setTransitionGroup(true)

这将强制窗口内容作为一个单元。

答案 1 :(得分:-1)

经过大量研究和android源代码阅读后,我想出了如何做到这一点。它在Scala中,但您应该轻松地将其转换为Java。

以下是最重要的部分。

CircularRevealActivity.scala

override protected def onCreate(savedInstanceState: Bundle) {
  super.onCreate(savedInstanceState)
  val window = getWindow
  val decor = window.getDecorView.asInstanceOf[ViewGroup]
  // prevent fading of background
  decor.setBackgroundColor(android.R.color.transparent)
  if (Build.version >= 21) {
    window.setEnterTransition(circularRevealTransition)
    window.setReturnTransition(circularRevealTransition)
    // decor.setTransitionGroup(true) won't work
    for (i <- 0 until decor.getChildCount) {
      val child = decor.getChildAt(i).asInstanceOf[ViewGroup]
      if (child != null) child.setTransitionGroup(true)
    }
    if (savedInstanceState == null) {
      val intent = getIntent
      val x = intent.getFloatExtra(EXTRA_SPAWN_LOCATION_X, Float.NaN)
      if (!x.isNaN) {
        val y = intent.getFloatExtra(EXTRA_SPAWN_LOCATION_Y, Float.NaN)
        if (!y.isNaN) circularRevealTransition.spawnLocation = (x, y)
      }
    }
  }
}

CircularReveal.scala

@TargetApi(21)
class CircularReveal(context: Context, attrs: AttributeSet = null)
  extends Visibility(context, attrs) {
  var spawnLocation: (Float, Float) = _
  var stopper: View = _
  private val metrics = new DisplayMetrics
  private lazy val wm = context.getSystemService(Context.WINDOW_SERVICE)
    .asInstanceOf[WindowManager]
  private def getEnclosingCircleRadius(x: Float, y: Float) =
    math.hypot(math.max(x, metrics.widthPixels - x),
               math.max(y, metrics.widthPixels - y)).toFloat

  override def onAppear(sceneRoot: ViewGroup, view: View,
                        startValues: TransitionValues, endValues: TransitionValues) = {
    wm.getDefaultDisplay.getMetrics(metrics)
    val (x, y) = LocationObserver.getRelatedTo(spawnLocation, view)
    new NoPauseAnimator(ViewAnimationUtils
      .createCircularReveal(view, x.toInt, y.toInt, 0,
        getEnclosingCircleRadius(x, y)))
  }
  override def onDisappear(sceneRoot: ViewGroup, view: View,
                           startValues: TransitionValues, endValues: TransitionValues) = {
    wm.getDefaultDisplay.getMetrics(metrics)
    val (x, y) = if (stopper == null)
      LocationObserver.getRelatedTo((metrics.widthPixels * .5F,
        metrics.heightPixels.toFloat), view)
    else LocationObserver.getRelatedTo(stopper, view)
    new NoPauseAnimator(ViewAnimationUtils
      .createCircularReveal(view, x.toInt, y.toInt,
        getEnclosingCircleRadius(x, y), 0))
  }
}