当LinearLayout的高度为0时,它不会重新调整大小。

7

有一个奇怪的问题。我已经将其简化为一个非常简单的示例,但仍然无法解决。

我有一个LinearLayout嵌套在另一个LinearLayout中。 我想使用动画来调整子级的大小(有时候很好用)。这是我的Layout XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
        <!-- Lots more controls will appear above -->
        <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:id="@+id/animation_subject">
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello"
                android:gravity="center" />
        </LinearLayout> 
        <!-- Lots more controls will appear below -->
    </LinearLayout>

    <Button android:text="Slide it Down!" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="btnDoAnimDown_OnClick" />

</LinearLayout>

现在,您可以看到有一个按钮,这是该按钮的代码。
public void btnDoAnimDown_OnClick(View v)
{
    View pnlSlider = findViewById(R.id.animation_subject);
    pnlSlider.measure(1000, 1000);
    DropDownAnim anim = new DropDownAnim(pnlSlider, pnlSlider.getMeasuredHeight(), true);
    anim.setDuration(2000);
    pnlSlider.startAnimation(anim);

    return;     
}

如果你现在运行它,它不会滑下来。但是,如果你将按钮移动到我命名为“概述”的LinearLayout中,并将其放在子LinearLayout之后,它就可以正常工作!像这样...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
        <!-- Lots more controls will appear above -->
        <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:id="@+id/animation_subject">
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello"
                android:gravity="center" />
        </LinearLayout> 
        <!-- Lots more controls will appear below -->
        <Button android:text="Slide it Down!" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="btnDoAnimDown_OnClick" />
    </LinearLayout>

</LinearLayout>

现在它向下滑动,完全符合预期。显然父布局出了些问题......由于getMeasuredHeight()返回正确的值,所以只是动画没有实际运行!

这就是动画类,我是否遗漏了一些愚蠢的东西?可能是的!

import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class DropDownAnim extends Animation {
    int targetHeight;
    View view;
    boolean down;

    public DropDownAnim(View view, int targetHeight, boolean down) {
        this.view = view;
        this.targetHeight = targetHeight;
        this.down = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down) {
            newHeight = (int) (targetHeight * interpolatedTime);
        } else {
            newHeight = (int) (targetHeight * (1 - interpolatedTime));
        }
        Log.d("new height", String.valueOf(newHeight));
        view.getLayoutParams().height = newHeight;
        view.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, ((View)view.getParent()).getWidth(), parentHeight);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

任何帮助都将是极好的!

不算完美的解决方案,但可以把按钮放在那里并将其可见性设置为“gone”。这样行得通吗? - Urban
那我就无法点击它来测试了。我会放置另一个对象并尝试测试。 - Dean Thomas
不行,没有机会。如果下一个兄弟不是触发动画的按钮,它就无法执行。多奇怪啊。我非常困惑。 - Dean Thomas
我想点击按钮,因为这会启动动画。无论如何,这并没有解决问题。还是谢谢。 - Dean Thomas
不,完全没有 :( 同样的问题,什么也没发生。动画从未被调用。 - Dean Thomas
显示剩余5条评论
3个回答

3

让我猜一下。

在你的第一个布局中,内部布局和按钮共享外部线性布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
        <!-- Lots more controls will appear above -->
        <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:id="@+id/animation_subject">
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello"
                android:gravity="center" />
        </LinearLayout> 
        <!-- Lots more controls will appear below -->
    </LinearLayout>

    <Button android:text="Slide it Down!" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="btnDoAnimDown_OnClick" />

</LinearLayout>

这使得外部布局成为一个ViewGroup!

但是,在您的动画初始化方法中,您对给定视图的父级进行了转换。

您将其转换为View,而在您的第一个布局中它不是View。

在第二个布局中,它是View,这就是为什么它可以工作的原因。

因此,我建议您尝试将其转换为ViewGroup:

@Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, ((ViewGroup)view.getParent()).getWidth(), parentHeight);
    }

不错的尝试,但是没有成功。我已经将初始化还原为应该的状态,所以传入parentWidth和parentHeight,而不是计算它们,但仍然没有成功。 :( - Dean Thomas

2

不确定是否有帮助,但是尝试将android:layout_weight="1"添加到具有id="@+id/animation_subject"LinearLayout中。


这现在使得布局占用了它的空间,因此它生成了自己的高度。当点击slideDown时确实起作用,但它会跳到0,然后向下滑动。但问题在于它的高度最初不是0。 - Dean Thomas
问题在于 XML 中设置了 0 大小,这表示应基于子视图大小自动设置大小。作为 hack,您可以在 XML 中将视图可见性设置为“gone”,并在动画的第一次中编程将大小设置为 0,然后将可见性设置为 View.VISIBLE - Dmitry

2
我不知道为什么你的代码不想执行动画。但是我通过一点改变来解决了它。我的做法是将动画应用于父布局而不是正在转换的布局。 这是 XML 代码,我只是在父布局上添加了一个 ID:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:orientation="vertical" >

    <LinearLayout android:id="@+id/animation_subject_parent" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
        <!-- Lots more controls will appear above -->
        <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:id="@+id/animation_subject">
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello"
                android:gravity="center" />
        </LinearLayout> 
        <!-- Lots more controls will appear below -->
    </LinearLayout>
        <Button android:text="Slide it Down!" android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="btnDoAnimDown_OnClick" />

</LinearLayout>

这里是按钮点击的代码:

public void btnDoAnimDown_OnClick(View v)
{
    View pnlSlider = findViewById(R.id.animation_subject);
    View parent = findViewById(R.id.animation_subject_parent);

    pnlSlider.measure(1000, 1000);
    DropDownAnim anim = new DropDownAnim(pnlSlider, pnlSlider.getMeasuredHeight(), true);
    anim.setDuration(2000);

    parent.startAnimation(anim);

    return;     
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接