How to rotate views on orientation change without recreating layout?

柔情痞子 提交于 2019-12-02 18:22:05

Try to use OrientationEventListener. You don't need to use onConfigurationChanged and android:configChanges="orientation|keyboardHidden|screenSize".

You need set android:screenOrientation="portrait" for the activity in AndroidManifest.xml. Here is my solution with OrientationEventListener:

public class MyActivity extends Activity{

private ImageButton menuButton;

private Animation toLandAnim, toPortAnim;
private OrientationListener orientationListener;

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_image_ruler);

    menuButton=(ImageButton)findViewById(R.id.menu_button);
    toLandAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_landscape);
    toPortAnim= AnimationUtils.loadAnimation(this, R.anim.menubutton_to_portrait);

    orientationListener = new OrientationListener(this);
}

@Override protected void onStart() {
    orientationListener.enable();
    super.onStart();
}

@Override protected void onStop() {
    orientationListener.disable();
    super.onStop();
}

private class OrientationListener extends OrientationEventListener{
    final int ROTATION_O    = 1;
    final int ROTATION_90   = 2;
    final int ROTATION_180  = 3;
    final int ROTATION_270  = 4;

    private int rotation = 0;
    public OrientationListener(Context context) { super(context); }

    @Override public void onOrientationChanged(int orientation) {
        if( (orientation < 35 || orientation > 325) && rotation!= ROTATION_O){ // PORTRAIT
            rotation = ROTATION_O;
            menuButton.startAnimation(toPortAnim);
        }
        else if( orientation > 145 && orientation < 215 && rotation!=ROTATION_180){ // REVERSE PORTRAIT
            rotation = ROTATION_180;
            menuButton.startAnimation(toPortAnim);
        }
        else if(orientation > 55 && orientation < 125 && rotation!=ROTATION_270){ // REVERSE LANDSCAPE
            rotation = ROTATION_270;
            menuButton.startAnimation(toLandAnim);
        }
        else if(orientation > 235 && orientation < 305 && rotation!=ROTATION_90){ //LANDSCAPE
            rotation = ROTATION_90;
            menuButton.startAnimation(toLandAnim);
        }
    }
}
}

This also prevents from too frequent rotations when orientation is about 45, 135... etc. Hope it helps.

David Medenjak

The basics are actually a lot easier. Have a look at Handling Runtime Changes.

First things first, by setting

android:configChanges="orientation|keyboardHidden|screenSize"

in your Manifest on your activity tag you can handle the orientation change yourself. (orientation should be enough, but there are sometimes issues where the event does not fire with that alone.)

You then skip onCreate and instead onConfigurationChanged gets called. Overwrite this method and apply your layout changes here. Whether you change your linearLayouts orientation here or have a custom view handling layout for different screens itself is up to you and depends on your implementation.

Animating will be a bit trickier, if it is even possilbe. A quick search says it is not.


Update for comment "I only want to rotate some views themselves rather than rotating the layout"

In theory it is possible to create your own layout and handle the drawing of your child views. I just tried it but could not produce any results in an appropriate time, but what you would need to do:

  • keep your last measured values use tags on the view or similar approaches to keep the last measurements and layouts, so that after the orientation change you can diff
  • await orientation change: trigger rotated drawing - rotate the canvas, layout the views with the previous dimensions, and draw the child views where they would have been before, and
  • start an animation interpolate from the last to the new values, rotating the canvas from the last to the new layout

This is how I would do it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!