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?
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();
}
}