1

所以,我有一个包含 aButtonImageView. 当您按下按钮时,ImageView 应该从按钮中滑出,就像我刚刚拉下卷帘一样(将其下方的其他视图向下滑动)。基本上如下图所示。当您再次按下按钮时,ImageView 应该与 gif 不同,再次平滑动画。

Button+ImageView 百叶窗.

使用这个 SO question,我设法将高度从 0 设置为全尺寸,但方向错误。我将 scaleType 设置为“Matrix”,设置高度时的默认行为是从上到下显示部分到 [height]。

对于动画,我需要相反的。因此,如果我将高度设置为 50dp,它将显示底部 50dp。然后我可以在 ImageView 显示的同时向下移动它,从而产生卷帘效果。

我查看了所有不同的布局和视图选项,但没有发现似乎可以做到这一点。所以我猜我需要指定转换矩阵。我查看了 android.graphics.Matrix 类,但它对我来说有点但太复杂了。我根本不知道如何使用它。

如果有另一种更简单的方法来做到这一点,那就太棒了,但如果没有,那么我真的需要矩阵方面的帮助。

我还包括这里的代码:

滚动视图 XML

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/sliding_accordion"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:src="@drawable/acc_image"
        android:contentDescription="@string/accord"
        android:scaleType="matrix"
        android:layout_below="@+id/acc_button"
        android:layout_marginTop="-10dp"
        android:layout_centerHorizontal="true"/>

    <Button
        android:id="@+id/acc_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

代码中的实现。
(注意,MyCustomAnimation 类是此处找到的类的复制粘贴版本)

//Called from all constructors
private void create()
{
    final Context context = getContext();
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.widget_accordion, this, false);

    final Button theButton = (Button) layout.findViewById(R.id.topic_button);
    final ImageView accordionView = (ImageView) layout.findViewById(R.id.sliding_accordion);
    accordionView.setVisibility(INVISIBLE);

    theButton.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            if (accordionView.getVisibility() == View.VISIBLE)
            {
                MyCustomAnimation a = new MyCustomAnimation(accordionView, 1000, MyCustomAnimation.COLLAPSE);
                height = a.getHeight();
                accordionView.startAnimation(a);
            }
            else
            {
                MyCustomAnimation a = new MyCustomAnimation(accordionView, 1000, MyCustomAnimation.EXPAND);
                a.setHeight(height);
                accordionView.startAnimation(a);
            }
        }
    });

    this.addView(layout);
}
4

1 回答 1

0

这花了很长时间才完美。但经过大量的实验,我设法做到了。

我为抽屉的边距设置动画,但由于负边距的意外行为,打开抽屉的按钮无法定位在顶部。

当抽屉关闭时,XML 如下所示:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/accordion"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <com.animationtest.drawer.Drawer
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/topic_drawer"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="0dp"
        android:visibility="invisible"/>

    <com.animationtest.drawer.Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/topic_btn"
        android:layout_marginTop="58dp"/>

</RelativeLayout>

然后,当按下按钮时,抽屉的 top_margin 会增加,直到它到达所需的任何位置(在本例中为抽屉高度 - someOffset)。

我使用 android.view.animation.Animation 为小部件设置动画,我的 applyTransformation 函数看起来像这样(注意 mLayoutParams 是抽屉参数):

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    int valueDifference = Math.abs(startValue - endValue);
    float valueChange = interpolatedTime * valueDifference;

    if(currentState.equals(State.COLLAPSED)) {
        // is closed and I want to open it
        mLayoutParams.topMargin = Math.round(interpolatedTime * valueDifference);
    }
    else {
        // is opened and I want to close it
        mLayoutParams.topMargin = valueDifference - Math.round(interpolatedTime * valueDifference);
    }

    drawerView.requestLayout(); //this is my drawer
}

最后,为了在抽屉移动时隐藏它的顶部,我覆盖了 DrawerView 的 dispatchDraw 方法,如下所示:

@Override
protected void dispatchDraw(Canvas canvas) {
    float height = getHeight();
    float top = height - ((LayoutParams) getLayoutParams()).topMargin;

    Path path = new Path();
    RectF rectF = new RectF(0.0f, top, getWidth(), height);

    path.addRoundRect(rectF, 0.0f, 0.0f, Path.Direction.CW);
    canvas.clipPath(path);
    super.dispatchDraw(canvas);
}

最后一点: 由于 Button 的位置,需要将小部件边距设置为负数,以使其在列表或布局中正确对齐。在这种情况下,它必须是 -58dp。

于 2013-08-29T16:44:48.403 回答