4

I would need a child layout (can be any layout, like FrameLayout or RelativeLayout) to ignore orientation change and remain always in landscape orientation. But not its parent or any other sibling layouts/views, they should change their orientation accordingly.

Hence, I cannot use setRequestedOrientation() or android:screenOrientation="landscape". Or it will lock the orientation for the whole screen or the activity. I need to lock only just this single layout.

My layout XML:

RelativeLayout (Parent)
  TextView
    FrameLayout/RelativeLayout <-- this need to be locked
      FrameLayout
        Button
SztupY
  • 10,291
  • 8
  • 64
  • 87
loser
  • 51
  • 1
  • 6
  • Hi, I tried both and achieve somewhat required. Thanks for the editing the question's format. – loser Feb 17 '13 at 03:41

2 Answers2

1

Extend the layout class that you want to keep portrait orientation and override the dispatchConfiurationChanged(Configuration) method as follows.

public void dispatchConfigurationChanged(Configuration newConfig) {
    Configuration c = new Configuration(newConfig); // copy
    c.orientation = ORIENTATION_PORTRAIT; // lock to portrait
    super.dispatchConfigurationChanged(c);
}

Be sure that your application is configured not to restart on orientation changes.

Jiyong Park
  • 664
  • 3
  • 6
  • Thanks for the help. The grand child FrameLayout (with button) does pick up the orientation (via onConfigurationChanged) to be fixed to portrait with your example above. But the button still shown as landscape. Anyway, I probably got my concept wrong, I will other approach to rotate the button instead. – loser Feb 16 '13 at 08:03
  • This did not work for me, i have a custom view which i don't want to change orientation but adding this method to customview did not change anything. – Siddarth G Apr 05 '20 at 16:49
1

It probably depends what you mean by "not change orientation". However, I think that best place to start would be to create your own class for the part that shouldn't change. So the layout xml now has two files:

main_layout.xml

RelativeLayout (Parent)
    TextView
        MyNonChangingLayout

my_non_changing_layout.xml

 RelativeLayout
     FrameLayout
         Button

Where you have created

MyNonChangingLayout extends FrameLayout {
    MyNonchangingLayout(Context content) {
        super(context);
        myContext = context;
        makeFromXML();
    }

private void makeFromXML() {
    LayoutInflater inflater = (LayoutInflater)myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    topView =  inflater.inflate(MyR.layout.my_non_changing_layout, this, false);

    // Get all the sub Views here using topView.findViewById()

    // Do any other initiation of the View you need here

    // Make sure you this otherwise it won't actually appear!
    super.addView(topView);
}

/*
 * Then, you can override quite a lot of the layout's calls and
 * enforce behaviour on the children. Two examples:
 */

// To specifically catch orientation changes
@Overridge
onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // You could create the layout here by removing all views and rebuilding them
    // Perhaps by having a two xml layouts, one of which is "90 degrees out" ...
    // If you do make the layot here, make sure you don't clash with the constructor code!
    switch (newConfig.orientation) {
        case ORIENTATION_LANDSCAPE:
            // Make the layout for this orientation (as per above)
            break;
        case ORIENTATION_PORTRAIT:
            // Make the layout for this orientation (as per above)
            break;
        case ORIENTATION_SQUARE:
            // Make the layout for this orientation (as per above)
            break;
    }
}

//to handle size changes to enforce aspect ratios on children:
@override
protected void onSizeChanged (int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    int viewWidth = //something I've determine
    int viewHeight = //something I've determined
    setViewsize(viewToHaveSizedControlled, viewWidth, viewheight);
}

// The post thing means that it doesn't crash no matter which thread it is
// executed on ...
private void setViewsize(final View v, final int w, final int h) {
    post(new Runnable() {
        public void run() {
            ViewGroup.LayoutParams lp = v.getLayoutParams();
            lp.width = w;
            lp.height = h;
            v.setLayoutParams(lp);
    }});
}

}

You can then enforce pretty well anything you want. If you can be more specific about what behaviour you want to enforce on the sub region I might be able to suggest more specific code.

One thing you may be wanting to do is to keep

Neil Townsend
  • 6,024
  • 5
  • 35
  • 52
  • Thanks for the help. The onConfigurationChanged() is part of the solution I'm looking for. Now, I need to go to study how to make the necessary to the content in the view. Actually, I need to make the button appear exactly matching the physical home button. While the rest of the screen will change orientation when the device is rotated, the button would appear fixed to the device like the physical home button. Hehe... it's a really odd requirement. – loser Feb 16 '13 at 08:25
  • Could you not just solve that by having a two top level layouts with the button in the place you want - one for portrait and one for landscape? A top level layout with just the button (tied to the right place and with the image rotated as you want it) and a relative layout to hold everything else? – Neil Townsend Feb 17 '13 at 20:10
  • Thanks for tips, Neil. I'm doing what u suggest here. Which bring me to other layout rotation questions. hehe. Anyway, TQ for the help. – loser Feb 18 '13 at 11:14