Java 动画视图移动到我的布局之外

Java 动画视图移动到我的布局之外,java,android,android-animation,android-scrollview,Java,Android,Android Animation,Android Scrollview,我有一个滚动视图,其中包含几个相对视图和线性布局,如下所示: <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scroll" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true

我有一个
滚动视图
,其中包含几个
相对视图
线性布局
,如下所示:

<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true" >

      <RelativeLayout >

      </RelativeLayout>

      <LinearLayout >

      </LinearLayout>

</ScrollView>
AnimatorUtils.animateLayoutChanges(linearLayout);
// APPEARING handles items being added to the ViewGroup
transition.setAnimator(LayoutTransition.APPEARING, someAnimator);

// CHANGING handles among other things height or width changes of items in the ViewGroup
transition.setAnimator(LayoutTransition.CHANGING, someOtherAnimator);
final Animator animator = setupAnimator();
animator.setTarget(view);

// Record the current state
animator.setupStartValues();

modifyChildrenOfLinearLayout();

linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Remove the callback immediately we only need to catch it this one time.
        linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);

        // Record the new state
        animator.setupEndValues();

        // Start the animation
        animator.start();
    }
});
同时,我使用另一个
PropertyAnimator
将任何
视图移动到我垂直展开的视图下方,以便为展开的布局留出足够的空间。到目前为止,它正在发挥作用

不幸的是,以某种方式移动的
视图
最终超出了
滚动视图
的视口,因此我无法向下滚动并查看这些
视图
中的信息。从本质上讲,这些视图的垂直平移会使其下部无法到达,因为视口不会太大

我已经在
滚动视图上设置了
android:fillViewPort=“true”
。我也尝试过用
setFillViewPort()
以编程的方式实现它,但都没有任何效果


怎么了?为什么不工作?

来自Android开发者网站: ScrollView是一个框架布局,这意味着您应该在其中放置一个子元素,其中包含要滚动的全部内容;此子对象本身可能是具有复杂对象层次结构的布局管理器。通常使用的子项是垂直方向的线性布局,表示用户可以滚动的顶级项的垂直数组

我可以看到,您在滚动视图中添加了多个子布局,请添加一个线性布局,并在该线性布局中添加其余布局。 希望它能解决您的问题

试试这个

<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true" >

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


                <RelativeLayout >

                     </RelativeLayout>

                <LinearLayout >

                     </LinearLayout>

      </LinearLayout>

</ScrollView>


Scrollview必须只有一个子视图。因此,我只创建了一个LinearLayout子级,并在其中添加了rest代码。

当您在
视图上执行翻译动画时,这些
视图实际上不会在布局中移动。这对于用户来说只是视觉上的,但是当涉及到布局和/或测量时,任何转换值都会被忽略。总是好像
视图
根本没有翻译

我猜你现在正在做的是:

  • 您对单击事件做出反应,并展开要展开的
    视图
    
  • 您可以计算其他视图需要移动多少才能容纳扩展的
    视图
  • 然后在这些
    视图上执行平移动画,按它们需要移动的程度进行平移
  • 然后,一些
    视图突然离开屏幕
这种方法实际上永远不会奏效。您始终需要记住,
视图
在布局中的位置是由布局决定的。你所有的翻译基本上只是为了作秀。因此,当您尝试执行上述操作时,实际发生的情况如下:

  • 您对单击事件做出反应,并展开
    视图
  • 这个扩展导致Android开始一个布局和测量过程。将计算所有视图的位置和尺寸,并使用新尺寸将它们定位在新位置
  • 由于现在
    视图
    已经位于展开后的位置,因此平移动画只是将
    视图
    进一步向下移动,超出它们应该位于的位置
  • 作为副作用,
    视图
    似乎无缘无故离开屏幕
那么你能做些什么呢?本质上,你需要用另一种方式来解决这个问题。正如我前面提到的,Android已经为您计算了所有
视图的新大小和位置,您可以利用它来发挥自己的优势

你的问题有两个基本的解决方案。您可以让Android通过
LayoutTransitions
为您执行动画,也可以手动执行动画。这两种方法都使用名为
ViewTreeObserver
的东西。它可用于侦听布局中的更改或新的绘图过程

但最重要的是:
ScrollView
应该只与一个子项一起工作。因此,为了防止将来出现任何错误或问题,请将所有项目放置在另一个垂直方向的
线性布局中的
滚动视图中

1) 使用LayoutTransition 这只适用于API级别16及以上的应用程序。低于API级别16的可见性动画和平移动画将自动处理,但要使高度更改动画化,需要API级别16

我必须提到的一件重要事情是:

  • LayoutTransition
    为您设置更改动画。因此,如果使用自定义动画,可以删除所有自定义动画。如果将自己的动画保留在中,只会与
    LayoutTransition
    执行的动画产生冲突
  • 如果您不喜欢由
    LayoutTransition
    执行的动画,您可以自定义它们!我将在下面进一步解释如何做到这一点
  • 我通常使用这样的助手方法来设置
    LayoutTransition

    public static void animateLayoutChanges(ViewGroup container) {
        final LayoutTransition transition = new LayoutTransition();
        transition.setDuration(300);
    
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            transition.enableTransitionType(LayoutTransition.CHANGING);
            transition.enableTransitionType(LayoutTransition.APPEARING);
            transition.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
            transition.enableTransitionType(LayoutTransition.DISAPPEARING);
            transition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
        }
    
        container.setLayoutTransition(transition);
    }
    
    这将在API级别16和更高级别上启用所有可能的自动转换,并且只使用默认启用的低于该级别的转换。就像这样使用它:

    <ScrollView 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true" >
    
          <RelativeLayout >
    
          </RelativeLayout>
    
          <LinearLayout >
    
          </LinearLayout>
    
    </ScrollView>
    
    AnimatorUtils.animateLayoutChanges(linearLayout);
    
    // APPEARING handles items being added to the ViewGroup
    transition.setAnimator(LayoutTransition.APPEARING, someAnimator);
    
    // CHANGING handles among other things height or width changes of items in the ViewGroup
    transition.setAnimator(LayoutTransition.CHANGING, someOtherAnimator);
    
    final Animator animator = setupAnimator();
    animator.setTarget(view);
    
    // Record the current state
    animator.setupStartValues();
    
    modifyChildrenOfLinearLayout();
    
    linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Remove the callback immediately we only need to catch it this one time.
            linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    
            // Record the new state
            animator.setupEndValues();
    
            // Start the animation
            animator.start();
        }
    });
    
    如果在
    滚动视图中的
    LinearLayout
    上调用此方法,则对
    LinearLayout
    及其直接子项的高度/宽度/可见性的所有更改都将为您设置动画。此外,项目添加/删除动画也会为您处理

    要启用各种转换(如调整大小动画),您需要在代码中设置
    layouttransions
    ,但可以通过设置属性来启用基本转换(如项目添加/删除动画)

    android:animateLayoutChanges="true"
    
    在xml布局中的
    视图组上

    关于
    layouttransions
    的文档很少,但介绍了基本内容

    如果你想