Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
264 views
in Technique[技术] by (71.8m points)

android - How does one Animate Layout properties of ViewGroups?

I have the following layout:

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

    <FrameLayout android:id="@+id/viewgroup_left"
                 android:layout_height="match_parent"
                 android:layout_weight="2"
                 android:layout_width="0dp">

        ... children ... 

    </FrameLayout>

    <LinearLayout android:id="@+id/viewgroup_right"
                  android:layout_height="match_parent"
                  android:layout_weight="1"
                  android:layout_width="0dp"
                  android:orientation="vertical">

        ... children ...

    </LinearLayout>

</LinearLayout>

I end up with something like this:

  +------------------------+------------+
  |                        |            |
  |                        |            |
  |         Left           |   Right    |
  |                        |            |
  |                        |            |
  +------------------------+------------+

When a certain toggle is toggled, I want to animate Left so that its width expands to fill the entire screen. At the same time, I would like to animate the width of Right so that it shrinks to zero. Later, when the toggle is toggled again, I need to restore things to the above state.

I've tried writing my own Animation that calls View.getWidth() but when I animate back to that value (by setting View.getLayoutParams().width) it is wider than when it began. I suspect I'm just doing it wrong. I have also read all the documentation on the Honeycomb animation stuff, but I don't want to translate or scale... I want to animate the layout width property. I can't find an example of this.

What is the correct way to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since noone helped you yet and my first answer was such a mess I'll try to give you the right answer this time ;-)

Actually I like the idea and I think this is a great visual effect which might be useful for a bunch of people. I would implement an overflow of the right view (I think the shrink looks strange since the text is expanding to the bottom).

But anyway, here's the code which works perfectly fine (you can even toggle while it's animating).

Quick explanation:
You call toggle with a boolean for your direction and this will start a handler animation call loop. This will increase or decrease the weights of both views based on the direction and the past time (for a smooth calculation and animation). The animation call loop will invoke itself as long it hasn't reached the start or end position.

The layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="10"
    android:id="@+id/slide_layout">
    <TextView
        android:layout_weight="7"
        android:padding="10dip"
        android:id="@+id/left"
        android:layout_width="0dip"
        android:layout_height="fill_parent"></TextView>
    <TextView
        android:layout_weight="3"
        android:padding="10dip"
        android:id="@+id/right"
        android:layout_width="0dip"
        android:layout_height="fill_parent"></TextView>
</LinearLayout>

The activity:

public class TestActivity extends Activity {

    private static final int ANIMATION_DURATION = 1000;

    private View mSlidingLayout;
    private View mLeftView;
    private View mRightView;

    private boolean mAnimating = false;
    private boolean mLeftExpand = true;
    private float mLeftStartWeight;
    private float mLayoutWeightSum;
    private Handler mAnimationHandler = new Handler();
    private long mAnimationTime;

    private Runnable mAnimationStep = new Runnable() {
        @Override
        public void run() {
            long currentTime = System.currentTimeMillis();
            float animationStep = (currentTime - mAnimationTime) * 1f / ANIMATION_DURATION;
            float weightOffset = animationStep * (mLayoutWeightSum - mLeftStartWeight);

            LinearLayout.LayoutParams leftParams = (LinearLayout.LayoutParams)
                    mLeftView.getLayoutParams();
            LinearLayout.LayoutParams rightParams = (LinearLayout.LayoutParams)
                    mRightView.getLayoutParams();

            leftParams.weight += mLeftExpand ? weightOffset : -weightOffset;
            rightParams.weight += mLeftExpand ? -weightOffset : weightOffset;

            if (leftParams.weight >= mLayoutWeightSum) {
                mAnimating = false;
                leftParams.weight = mLayoutWeightSum;
                rightParams.weight = 0;
            } else if (leftParams.weight <= mLeftStartWeight) {
                mAnimating = false;
                leftParams.weight = mLeftStartWeight;
                rightParams.weight = mLayoutWeightSum - mLeftStartWeight;
            }

            mSlidingLayout.requestLayout();

            mAnimationTime = currentTime;

            if (mAnimating) {
                mAnimationHandler.postDelayed(mAnimationStep, 30);
            }
        }
    };

    private void toggleExpand(boolean expand) {
        mLeftExpand = expand;

        if (!mAnimating) {
            mAnimating = true;
            mAnimationTime = System.currentTimeMillis();
            mAnimationHandler.postDelayed(mAnimationStep, 30);
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.slide_test);

        mLeftView = findViewById(R.id.left);
        mRightView = findViewById(R.id.right);
        mSlidingLayout = findViewById(R.id.slide_layout);

        mLeftStartWeight = ((LinearLayout.LayoutParams)
                mLeftView.getLayoutParams()).weight;
        mLayoutWeightSum = ((LinearLayout) mSlidingLayout).getWeightSum();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...