37

I need to be able to rotate whole layouts on the fly (on the click of a button).

I am able to rotate the layouts using, eg. layout.setRotation(270.0f). The problem is, after the rotation, the layout height and width are not matching its parent's.

I have tried inverting height and width like so,

RelativeLayout layout = (RelativeLayout)findViewById(R.id.rootLayout);
LayoutParams layoutParams = layout.getLayoutParams();
int height = layout.getHeight();
int width = layout.getWidth();
layoutParams.height = width;
layoutParams.width = height;

Which does nothing at all.

I am working with sdk 14.

The first image below is the app as it starts. The second one, after a rotation. I wish to fill the black "space". Any help would be appreciated.

The images below show only a button in the layout. However, in reality, the layout are a lot more complex. What I am trying to achieve is "faking" a landscape view.

When starting After rotation

Edit: Changed images and added descriptions.

boulaycote
  • 602
  • 1
  • 6
  • 18

9 Answers9

48

Not sure why this is useful, but it's a nice puzzle. Here is something that works for me:

On rotate click, do this:

RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main);
int w = mainLayout.getWidth();
int h = mainLayout.getHeight();

mainLayout.setRotation(270.0f);
mainLayout.setTranslationX((w - h) / 2);
mainLayout.setTranslationY((h - w) / 2);

ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) mainLayout.getLayoutParams();
lp.height = w;
lp.width = h;
mainLayout.requestLayout();

And the layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:id="@+id/main"
    android:layout_height="match_parent"
    android:background="#ffcc88"
    tools:context=".TestRotateActivity" >

    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        />

    <Button 
        android:id="@+id/rotate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Rotate"
        android:layout_centerInParent="true"
        />

</RelativeLayout>
yoah
  • 7,180
  • 2
  • 30
  • 30
  • Yep this works. Exactly what I need. Now I simple need to add different rotation options. `requestLayout` did it. – boulaycote Feb 05 '14 at 00:15
  • 2
    thanx for nice solution...the trick works for me too but it scales my child imageview....i want to prevent it...pz help me – H Raval Aug 13 '16 at 08:58
5

Try this code:

btnRotate.setOnClickListener(new OnClickListener()
{
    @SuppressLint("NewApi")
    @Override
    public void onClick(View v) 
    {
        int orientation = getResources().getConfiguration().orientation;
        switch(orientation)
        {
            case Configuration.ORIENTATION_LANDSCAPE:
                llparent.setRotation(270.0f);
                RelativeLayout.LayoutParams layoutParams_LandsScape =
                    new RelativeLayout.LayoutParams(
                        rlRoot.getHeight(), rlRoot.getWidth()); 
                layoutParams_LandsScape.setMargins(
                    rlRoot.getTop(), rlRoot.getRight(),
                    rlRoot.getBottom(), rlRoot.getLeft());
                layoutParams_LandsScape.addRule(RelativeLayout.CENTER_IN_PARENT);
                llparent.setLayoutParams(layoutParams_LandsScape);  
                break;
            case Configuration.ORIENTATION_PORTRAIT:
                llparent.setRotation(270.0f);
                RelativeLayout.LayoutParams layoutParams_Portrait =
                    new RelativeLayout.LayoutParams(
                        rlRoot.getHeight(), rlRoot.getWidth()); 
                layoutParams_Portrait.setMargins(
                    0, 0, rlRoot.getBottom(), rlRoot.getLeft());    
                layoutParams_Portrait.addRule(RelativeLayout.CENTER_IN_PARENT);
                llparent.setLayoutParams(layoutParams_Portrait);
                break;
            }
        }
    });
}

And XML:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RotateAnim">

    <RelativeLayout
        android:id="@+id/rlroot"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#090">

        <LinearLayout
            android:id="@+id/llParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#900"
            android:gravity="center"
            android:orientation="vertical">

            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="Button"/>
        </LinearLayout>
    </RelativeLayout>
</RelativeLayout>
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Sagar Shah
  • 4,272
  • 2
  • 25
  • 36
3

Simple and tricky way to make screen orientation along the button click.. with an example..

Here,I'm using the sharedPreference(Im setting an boolean value based on orientation )

Method for button onClick.

public void rotate(View v) {
    edt = prefs.edit();

    if (!prefs.getBoolean("screen_protrait", true)) {
        edt.putBoolean("screen_protrait", true);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        edt.putBoolean("screen_protrait", false);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
    edt.commit();
}

In xml, set an onClick method for rotate button

       <Button
   android:id="@+id/bt_rotate"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:onClick="rotate"
   android:text="Rotate" />

Last one, is in onCreate of Activity you want to set the Prefernce from Application..as

  prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

Keep coding.. You can achieve your goal...Let me know,if it's working with your scenario.

Joyal
  • 414
  • 7
  • 19
2

If you want to literally rotate the screen, you can force a screen orientation. Otherwise there's no easy way to do what you are trying to do as View.setRotation(float) will always render the View in its "real" bounds and then rotate it! What I suggest is careful consideration of what elements of the layout should be rotated and then to rotate those specifically.

The only true "automatic" way of achieving it would be to create a custom layout that essentially measures, layouts and draws children rotated... Honestly I would only go there if I really, really needed to and it's probably more trouble than it's worth!

Community
  • 1
  • 1
Takhion
  • 2,706
  • 24
  • 30
2
    // get root layout from activity's XML
    LinearLayout mParentLayout = (LinearLayout) findViewById(R.id.activity_main);

    // get screen size from DisplayMetrics if you need to rotate before the screen is shown
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    int height = displayMetrics.heightPixels;
    int width = displayMetrics.widthPixels;

    // if you are rotating after the view was shown
    // acquire width and height from the layout's parent's LayoutParams

    // calculate offset to move the view into correct position
    int offset = (width - height) / 2;

    // rotate the layout
    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(height, width);
    mParentLayout.setLayoutParams(lp);
    // 90° clockwise
    mParentLayout.setRotation(90.0f);
    mParentLayout.setTranslationX(offset);
    mParentLayout.setTranslationY(-offset);

It may look like the suggested answer, but this displays how to get dimensions from DisplayMetrics and the calculating the offset for the translation is a little different because that's the only way it worked properly.

rexxar
  • 1,671
  • 1
  • 21
  • 27
1

i'll suggest you rotate only button rather than rotating the whole layout like

btn_rotate.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) 
{
    rotation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.rotate);
    rotation.setFillAfter(true);
    btn_rotate.startAnimation(rotation);
}
});

rotate.xml

<set>
    <rotate
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:duration="0"
          android:fromDegrees="270"
          android:pivotX="50%"
          android:pivotY="50%"
          android:startOffset="0"
          android:toDegrees="270" />
</set>
Rajan
  • 1,069
  • 1
  • 9
  • 17
  • Thanks for your suggestion, and I have tried that already. Problem is I really need to "fake" landscape orientation rather than rotating views in place. In reality the layout would be a lot more complex than a simple button. – boulaycote Jan 29 '14 at 14:28
0

try set your layout params to match_parent after rotation:

layout.setRotation(270.0f)

and then

RelativeLayout layout = (RelativeLayout) findViewById(R.id.rootLayout);     
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

EDIT: get the parentView View parent = layout.getParent(); and set the width and height of the parent view to your layout as you need - in width to height and vice versa.

Alex
  • 688
  • 6
  • 8
0

Android: alternate layout xml for landscape mode

As I can remember, you should define a new layout for the horizontal view. I think this link can help you

Community
  • 1
  • 1
albert2702
  • 64
  • 2
  • I need to "fake" landscape orientation. This would be the right way to do it for real :) Thanks for the link! – boulaycote Jan 29 '14 at 15:55
0

Try this code:
(RelativeLayoutOuterFrame) it is the name of your layout.which you want to rotate.

Actually, we are not rotate the layout.we just change height an width value.

    int w = RelativeLayoutOuterFrame.getWidth();
    int h = RelativeLayoutOuterFrame.getHeight();
    ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) RelativeLayoutOuterFrame.getLayoutParams();
    lp.height = w;
    lp.width = h;
    RelativeLayoutOuterFrame.setGravity(RelativeLayout.CENTER_IN_PARENT);
    RelativeLayoutOuterFrame.setGravity(RelativeLayout.CENTER_HORIZONTAL);
    RelativeLayoutOuterFrame.requestLayout();
Andybhai
  • 1
  • 1