Android Screen Orientation

| Page Views: 101

Android Screen Orientation Tutorial, Example and Libraries

In this class we want to cover screen orientation in android.

Rotating a screen in android causes some significant activities to happen. These need to be handled properly lest we have an app that crashes at runtime. Everytime you rotate a screen, this leads to configuration changes. The android system destroys the activity then re-creates it. Normally we have two main orientations: portrait and landscape.Thus the recreation of activities makes sense as android has to load resources based on the new configuration. Users expect apps to occupy the whole screen. And since screens are rectangular, the height in landscape mode will be the smaller dimension while in portrait it will be the larger one.

The screen orientation has to be handled carefully. We said the android system destroys the activity and recreates a new instance. That implies that your member and instance fields will be lost with the destroyed activity. And thus attempting to access them causes a leakage in memory. Luckily for us, we are provided with one chance to save to those variables before the destruction. Those variables are what define our activity state hence we are saving the activity state. Not just activities but we can also save fragments state. Remember fragments get hosted by activities. Hence destruction of an activity leads to destruction of fragments as well.

Then once we've saved that fragment's/activity's state, we can restore it to get back the previous state. Think for example when users are typing in an edittext, and they rotate the device either intentionaly or accidentally. You don't want the the already typed data getting lost. That can happen easily as the edittexts are user interface components that will be rendered in either an activity or fragment. Hence the proper way of handling screen orientation involves saving the activity/fragment state then later restoring it.

The screenOrientation Attrirbute

It is an activity element and gets specified within the <activity> tag in the android manifest file.

That orientation of android activity can be:

No. Type Description
1. Portrait The most popular orientation. In this case height is greater than width.
2. Landscape People prefer it especially when watching videos. In this case width is greater than height.
1. Sensor In this case the orientation is determined by orientation sensors.
1. Unspecified The orientation is determined by the system.

Screen Orientation Examples

Let's look at some examples available in github.

Example 1

Here is a simple screen orientation example.

import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.content.pm.ActivityInfo;

public class MainActivity extends AppCompatActivity {
static int i=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getScreenOrientation();

    }

    private void getScreenOrientation(){
        TextView textView=(TextView)findViewById(R.id.textView);
        if(getResources().getConfiguration().orientation== Configuration.ORIENTATION_PORTRAIT)
        {textView.setText("VERTICAL");}
        if(getResources().getConfiguration().orientation== Configuration.ORIENTATION_LANDSCAPE)
        {textView.setText("HORIZONTAL");}
    }

    public void onHorClick(View view) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);}
    public void onVertClick(View view) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);}
    public void onBtSensorClick(View view) {setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);}
}

You can download it here.

Example 2
import android.app.Activity;
import android.app.ListActivity;
import android.util.Log;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.ListView;
import java.util.ArrayList;
import android.widget.ArrayAdapter;

public class MainActivity extends Activity {

    private final String TAG = "ActivityLifeCycle";
    private String text = "";
    ArrayList<String> textStrings = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate() called");
        textStrings.add("TEST");
        textStrings.add("TEST 2");

        //get a reference for our save button from xml
        Button inputButton = (Button) findViewById(R.id.inputButton);

        //get a reference to our editText from xml
        final EditText editText = (EditText) findViewById(R.id.inputText);
        final TextView textView = (TextView) findViewById(R.id.outputText);
        final ListView listView = (ListView) findViewById(R.id.list);

        if(savedInstanceState!= null){
            Log.d("DEBUG", savedInstanceState.getString("savedText"));
            String str = savedInstanceState.getString("savedText");
            if(str != null){
                text = str;
            }

            ArrayList list = savedInstanceState.getStringArrayList("savedList");
            if (list!=null){
                textStrings = list;
            }
        }

        textView.setText(text);

        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                R.layout.activity_listview, textStrings);

        //ListView listView = getListView();
        //listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

        listView.setAdapter(adapter);
        //setListAdapter(adapter);

        //add a click listener to our save button
        inputButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v){
                text = editText.getText().toString();
                textStrings.add(text);

                Log.d("DEBUG ON Click", text);
                Log.d("DEBUG ON Click VIEW", textView.getText().toString());

                //set the new value in the text field
                textView.setText(text);
                listView.setAdapter(adapter);
            }
        });
    }

    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart");
    }

    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume");
    }

    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause");
    }

    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop");
    }

    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart");
    }

    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
    }

    protected void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);

        Log.i(TAG, "onSaveInstanceState");

        outState.putString("savedText", text);
        outState.putStringArrayList("savedList", textStrings);
    }

    protected void onRestoreInstanceState(Bundle savedState){
        super.onRestoreInstanceState(savedState);
        Log.i(TAG, "onRestoreInstanceState");

        TextView savedText = (TextView) findViewById(R.id.outputText);

        this.text = savedState.getString("savedText");
        this.textStrings = savedState.getStringArrayList("savedList");

    }
}

Download the full code here.

Top Screen Orientation Libraries

What of if for whatever reason you want to use a third party library. There are a couple and if you have written one please send me via email or comment section the link so I post it here.

1. ScreenOrientationHelper

This is a Screen orientation event listener helper for activity. The author built it due to onConfigurationChanged() seemingly not detecting screen orientations. You start by installing the library via gradle:

implementation 'com.akexorcist:screenorientationhelper:1.0.0'

Here's the usage. You implement the ScreenOrientationHelper.ScreenOrientationChangeListener interface this overriding the onScreenOrientationChanged. That method will give us the integer representing the orientation.

public class BaseActivity extends AppCompatActivity implements ScreenOrientationHelper.ScreenOrientationChangeListener {
    private ScreenOrientationHelper helper = new ScreenOrientationHelper(this);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        helper.onCreate(savedInstanceState);
        helper.setScreenOrientationChangeListener(this);
    }

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

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        helper.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        helper.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    public void onScreenOrientationChanged(int orientation) {

    }

    ...
}
No. Location Link
1. GitHub Download Code
2. GitHub Browse Code
3. GitHub Owner
2. Bubble

Another library is Bubble. This is an Android library for obtaining screen orientation. The author created it due to limitations in the way android handles screen orientation changes, which is basically by callbacks. Through this callback mechanism, the system re-creates views from scratch when an orientation occurs. This makes it impossible to implement smooth transitions. Furthermore, locking the orientation in android manifest means the callback is no longer invoked. This forces you to detect orientation changes manually in case you wanted custom view transitions

Here is an gif image of an camera app applying this library.

Here's how you install the library:

implementation 'pl.touk.android:bubble:1.0.0'

Here's a simple example implementation with RxJava and Kotlin:

class BubbleSampleActivity : AppCompatActivity() {
    val bubble: Bubble = Bubble()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_bubble_sample)
        textView = findViewById(R.id.label) as TextView
        bubble.register(this)
            .subscribe { bubbleEvent: BubbleEvent -> rotateTo(bubbleEvent.orientation) }
    }
    ...
}
No. Location Link
1. GitHub Download Code
2. GitHub Browse Code
3. GitHub Sample
3. GitHub Owner

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think


Previous Post