Измените вес макета с помощью анимации

В моем основном файле макета у меня есть RelativeLayout с весом 1 (в основном для отображения карты) над LinearLayout с весом 2, объявленным следующим образом:

<LinearLayout
    android:id="@+id/GlobalLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:id="@+id/UpLayout"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1" >
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/DownLayout"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="2"
        android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

DownLayout содержит список элементов, когда я нажимаю на элемент, я хотел бы изменить вес DownLayout на 4, поэтому верхний макет (карта) занимает только 1/5 экрана вместо 1/3.

Мне удалось это сделать, изменив LayoutParams:

    LinearLayout linearLayout = (LinearLayout) mActivity.findViewById(R.id.DownLayout);
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
    params.weight = 4.0f;
    linearLayout.setLayoutParams(params);

Это работает, но я не удовлетворен, изменение слишком быстрое, переход отсутствует, хотя я бы хотел, чтобы он был гладким. Есть ли способ использовать анимацию для этого?

Я нашел несколько примеров с ObjectAnimator, чтобы изменить weightSum, но он не хочет, я хочу (если я изменяю только это свойство, у меня есть свободное место ниже моего макета):

        float ws = mLinearLayout.getWeightSum();
        ObjectAnimator anim = ObjectAnimator.ofFloat(mLinearLayout, "weightSum", ws, 5.0f);
        anim.setDuration(3000);
        anim.addUpdateListener(this);
        anim.start();

Есть ли способ использовать ObjectAnimator (или что-то еще) для этого?

Спасибо!

Ответ 1

Недавно я столкнулся с подобной проблемой и решил ее с помощью стандартной анимации (мне нужно настроить API 10, чтобы не использовать ObjectAnimator). Я использовал комбинацию ответа здесь с небольшими изменениями, чтобы учесть вес вместо высоты.

Мой пользовательский класс анимации выглядит следующим образом:

private class ExpandAnimation extends Animation {

    private final float mStartWeight;
    private final float mDeltaWeight;

    public ExpandAnimation(float startWeight, float endWeight) {
        mStartWeight = startWeight;
        mDeltaWeight = endWeight - startWeight;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContent.getLayoutParams();
        lp.weight = (mStartWeight + (mDeltaWeight * interpolatedTime));
        mContent.setLayoutParams(lp);
    }

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

И его вызываемый этим методом...

public void toggle() {
    Animation a;
    if (mExpanded) {
        a = new ExpandAnimation(mExpandedWeight, mCollapsedWeight);
        mListener.onCollapse(mContent);
    } else {
        a = new ExpandAnimation(mCollapsedWeight, mExpandedWeight);
        mListener.onExpand(mContent);
    }

    a.setDuration(mAnimationDuration);
    mContent.startAnimation(a);
    mExpanded = !mExpanded;
}

Надеюсь, это поможет вам, если вам нужно больше деталей или у вас есть вопросы о чем-то, дайте мне знать.