2015-04-06 31 views
2

我嘗試使用android:windowEnterTransitionandroid:windowExitTransition,但似乎爲活動中的每個視圖設置動畫,即分別顯示每個視圖。我怎樣才能讓整個活動的內容動起來?兩項活動之間沒有共同的要素。如何循環顯示整個活動

回答

0

經過大量的研究和Android源代碼閱讀,我想出瞭如何做到這一點。它在斯卡拉,但你應該很容易地將它翻譯成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)) 
    } 
} 
2

有幾種方法可以爲整個活動設置動畫。最有效的機制是使用窗口轉換。這些操作是針對Window的,因此內容不需要在每一幀上重新繪製。不利的一面是操作僅限於較舊的動畫框架。

通常,您可以使用樣式指定窗口動畫。你可以看到它是如何在這裏完成:Start Activity with an animation

如果你想用棒棒糖活動過渡框架還可以使用overridePendingTransition或ActivityOptions.makeCustomAnimation

,您可以使用windowEnterTransition。如果你只想你的內容進行操作上,設置最外層的ViewGroup有:

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

你可能想給你的視圖組的名稱或ID,並在進入過渡使用它,這樣它的目標只有組。否則,它會定位諸如狀態欄背景之類的內容。

如果你想讓它在整個窗口中的內容進行操作:

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

這將迫使窗口中的內容作爲一個單元。

+1

'getDecorView()''返回View',所以它應該是'((的ViewGroup)getWindow()getDecorView())setTransitionGroup (真)'。但不幸的是,這似乎並不奏效。而'android:transitionGroup =「true」'不能正確處理狀態欄和導航欄。 :-( – Mygod 2015-04-11 02:05:17

+0

以下是錯誤消息:'java.lang.ClassCastException:android.view.ViewRootImpl無法轉換爲android.app.ActivityTransitionCoordinator.setSharedElementMatrices(ActivityTransitionCoordinator.java:503)'android.view.ViewGroup'。 – Mygod 2016-07-05 23:43:52

+0

錯誤上面的消息是通過將其設置爲共享元素生成的。以下是解決方案無法運行的原因:https://android.googlesource.com/platform/frameworks/base/+/fc7476d/core/java/com/android /internal/policy/PhoneWindow.java#2872'@Override public boolean isTransitionGroup(){return false;}' – Mygod 2016-07-06 01:46:46