Better Implementation of Rotate3dAnimation in Android ViewFlipper
I wanted to create an Android MapActivity with the map in one view, which could be flipped over and then configured in another view, then flipped back over to the map again. The solution I came up with works, but I'm wondering if there's a better way to do this.
I copied the Rotate3DAnimation class from the Android ApiDemos, and declared these at the top of my MapActivity class:
private MapView mMapView;
private ViewFlipper mFlipper;
private Rotate3dAnimation mInMapAnimation;
private Rotate3dAnimation mInStgAnimation;
private Rotate3dAnimation mOutMapAnimation;
private Rotate3dAnimation mOutStgAnimation;
Next, in my onCreate method of the MapActivity I did this:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreat开发者_运维技巧e(savedInstanceState);
setContentView(R.layout.mapoverviewlayout);
// Initialize the map.
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
// Obtain the view flipper.
mFlipper = (ViewFlipper)findViewById(R.id.mapviewflipper);
// Initialize the settings view and handle the setting clicks.
Button stgMapDone = (Button)findViewById(R.id.MapViewOptionsDone);
stgMapDone.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
UnitOverviewMapActivity.this.mFlipper.showNext();
}
});
}
And finally, I used a menu button to select the appropriate flip animations. I did this because if the map flips one direction to reveal the settings view, I wanted it to flip in the reverse direction to hide the settings view. So in my onPrepareOptionsMenu (since that's where my button was) I did this:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mInMapAnimation == null) {
mInMapAnimation = new Rotate3dAnimation(-90, 0, mMapView.getWidth() / 2, mMapView.getHeight() / 2, 0.0f, false);
mInMapAnimation.setDuration(1000);
mInMapAnimation.setStartOffset(1000);
}
if (mInStgAnimation == null) {
mInStgAnimation = new Rotate3dAnimation(90, 0, mMapView.getWidth() / 2, mMapView.getHeight() / 2, 0.0f, false);
mInStgAnimation.setDuration(1000);
mInStgAnimation.setStartOffset(1000);
}
if (mOutMapAnimation == null) {
mOutMapAnimation = new Rotate3dAnimation(0, -90, mMapView.getWidth() / 2, mMapView.getHeight() / 2, 0.0f, false);
mOutMapAnimation.setDuration(1000);
}
if (mOutStgAnimation == null) {
mOutStgAnimation = new Rotate3dAnimation(0, 90, mMapView.getWidth() / 2, mMapView.getHeight() / 2, 0.0f, false);
mOutStgAnimation.setDuration(1000);
}
if (mFlipper.getCurrentView().getId() == R.id.mapparentlayout) {
mFlipper.setInAnimation(mInStgAnimation);
mFlipper.setOutAnimation(mOutMapAnimation);
}
else {
mFlipper.setInAnimation(mInMapAnimation);
mFlipper.setOutAnimation(mOutStgAnimation);
}
return true;
}
This works fine, but it just seems inefficient. I (apparently mistakenly) assumed that "flipping" would be a built-in feature of the ViewFlipper container. Is there a better or more efficient way to accomplish this?
This is the best I could figure. Part of the problem was being unable to determine the size of the mapView in order to calculate the size arguments for the animation constructors. I changed my onCreate code to the following, and it shortened it quite a bit.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapoverviewlayout);
// Initialize the map.
mMapView = (MapView) findViewById(R.id.mapview);
mMapView.setBuiltInZoomControls(true);
// Obtain the view flipper.
mFlipper = (ViewFlipper)findViewById(R.id.mapviewflipper);
// Initialize the animations.
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int h2 = display.getHeight() / 2;
int w2 = display.getWidth() / 2;
mInMapAnimation = new Rotate3dAnimation(-90, 0, w2, h2, 0.0f, false);
mInMapAnimation.setDuration(500);
mInMapAnimation.setStartOffset(500);
mInStgAnimation = new Rotate3dAnimation(90, 0, w2, h2, 0.0f, false);
mInStgAnimation.setDuration(500);
mInStgAnimation.setStartOffset(500);
mOutMapAnimation = new Rotate3dAnimation(0, -90, w2, h2, 0.0f, false);
mOutMapAnimation.setDuration(500);
mOutStgAnimation = new Rotate3dAnimation(0, 90, w2, h2, 0.0f, false);
mOutStgAnimation.setDuration(500);
}
As far as I have been able to tell - no. ViewFlipper uses the same animations for in and out no matter which view you are currently seeing.
精彩评论