Search code examples
androidscreen-orientationonconfigurationchanged

Setting up Orientation.. different designs for both portrait and landscape mode.. without resetting the entered value


i have different layout design for portrait mode and a different looking layout for landscapre mode.. inside 'res' folder, i created a new folder called 'land-layout', where i created the file with the same name as inside 'layout'.

i have the textview (counter), which restores the value, when the orientation changes.. But the problem i am facing is, when the orientation goes from portrait to landscape, the design still continues to be the same as that was in portrait mode.. i wanted to know, how do i handle it ?? i'd be grateful. Thanks.

MainActivity.java :

public class MainActivity extends Activity {

private int sum = 0;
Button add, sub;
TextView tv1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv1 = (TextView) findViewById(R.id.textView1);

    add = (Button) findViewById(R.id.button1);
    add.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            sum++;
            tv1.setText("Incrementation = " + sum);
        }
    });
    sub = (Button) findViewById(R.id.button2);
    sub.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            sum--;
            tv1.setText("Decrementation = " + sum);
        }
    });
}  
@Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);

if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// setContentView(R.layout.activity_main);
Log.v("message", "ORIENTATION_LANDSCAPE");

} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Log.v("message", "ORIENTATION_PORTRAIT");
}

}


@Override
protected void onSaveInstanceState(Bundle outState) {
    // TODO Auto-generated method stub
    super.onSaveInstanceState(outState);
    outState.putInt("sum", sum);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onRestoreInstanceState(savedInstanceState);
    int x = savedInstanceState.getInt("sum");
}

}

res\layout-land\activity_main.xml(for landscape mode)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/backg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="total is = 0"
    android:layout_gravity="center"
    android:textSize="40sp"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>

<Button
    android:id="@+id/button1"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_weight="1"
    android:text="ADD" />

<Button
    android:id="@+id/button2"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:layout_gravity="center"
    android:text="Sub" />
</LinearLayout>

<TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Large Text"
    android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

res\layout\activity_main.xml(for portrait mode) :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/backg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:freezesText="true"
    android:text="total is = 0"
    android:textSize="40sp"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<Button
    android:id="@+id/button1"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="ADD" />

<Button
    android:id="@+id/button2"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="Sub" />

</LinearLayout>

in manifest i added : android:configChanges="orientation|screenSize" (how do i use onConfigurationChanged() to handle the layout ? )

<activity
        android:name="com.example.apptest.MainActivity"
        android:configChanges="orientation|screenSize"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="com.example.apptest.MAINACTIVITY" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

Solution

  • When you write this

    android:configChanges="orientation|screenSize"
    

    in the manifest : it means that you will handle orientation change yourself. So write something like this to handle configuration change.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.activity_main);
        ...
    }
    

    Note that doing this : you will inflate the new layout from xml. So new Views will be created and the content of previous views will be lost.

    For a better user experience, you need to transfer the content from the old view in the new view :

    Something like this :

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        CharSequence tmp = ((TextView)findViewById(R.myId)).getText();
        setContentView(R.layout.activity_main);
        ((TextView)findViewById(R.myId)).setText(tmp);
        ...
    }
    

    BUT Android provides useful hook to write all of this in a better way.

    remove this line from the manifest

    android:configChanges="orientation|screenSize"
    

    and use :

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //here store your data in outState
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(savedInstanceState!=null){
           //at this point savedInstanceState contains everything that was stored in outState.
        }