onConfigurationChanged doesn't avoid activity restart on orientation change - java

I would like, for a camera app, to avoid redrawing the activity on orientation change.
So far I've been using android:screenOrientation="landscape"
Now I want the icons to rotate according to orientation change.
Well, it should be very straightforward:
Firstly the code line above is deleted.
Then you set in the manifest for the activity:
android:configChanges="orientation|screenSize|keyboardHidden"
Finally, you override onConfigurationChanged in the activity:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//Do something
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
//Do something
}
}
Now, AFAIK, it should fire onConfigurationChanged instead restarting the activity (assuming it will be handled in onConfigurationChanged)
In practice, when orientation is changed, onConfigurationChanged is fired, but in addition to the unwanted rotation. How to cancel it? What am I missing?
Device: Xiaomi Mi2s
API: 4.1.1
Thanks,
Mark.

You need to prevent the parent from handling the config as follows:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(null);
//TODO: Do nothing when orientation has changed...
}
As you can see all you need to do is pass null to the super method of onConfigurationChanged, so it will actually prevent from going through all the changes you want to avoid.
Regards!

Try this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//Do something
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
//Do something
}
super.onConfigurationChanged(newConfig);
}
if you don't want to recreate activity, use orientation sensor for detecting orientation.

Well, after the traditional methods failed - I decided to implement orientation change routine by myself.
For this, firstly, I've returned android:screenOrientation="landscape" to the manifest.
Then, I've implemented sensor listener call back with some math:
private SensorEventListener listener = new SensorEventListener() {
public void onSensorChanged(SensorEvent e) {
if (e.sensor.getType()==Sensor.TYPE_ACCELEROMETER) {
float x = e.values[0];
float y = e.values[1];
//update _angle in rotate()
if (Math.abs(y) / Math.abs(x) < 1.0)
{
if (x<0 && _angle != 270f)
rotate(270f);
else if(x>=0 && _angle != 90f)
rotate(90f);
}
else
{
if (y<0 && _angle != 180f)
rotate(180f);
else if (y>=0 && _angle != 0f)
rotate(0f);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
Works like a charm.

Related

Force rotating screen stuck up with only landscape mode

In my Activity I have button if I click on the button am rotating the screen to landscape mode, But it stuck up with only landscape mode. How to enable the portrait mode? I am using the below code for force rotation.
rotate.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
});
the above code override the native rotation functionality, Could any one please suggest me how to enable the native rotation function?
Programatically You can do it with this code
potraitButton.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
});
buttonLandscape.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
});
if you want to rotate screen automatic:
SensorManager sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);
sensorManager.registerListener(new SensorEventListener() {
int orientation=-1;;
#Override
public void onSensorChanged(SensorEvent event) {
if (event.values[1]<6.5 && event.values[1]>-6.5) {
if (orientation!=1) {
Log.d("Sensor", "Landscape");
}
orientation=1;
} else {
if (orientation!=0) {
Log.d("Sensor", "Portrait");
}
orientation=0;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
Basically you have two option.
First you can switch back to portrait manually whenever you want using: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Another way is to override the onConfigurationChanged() (take a look at the doc here).
Example:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(changedOrientationManually &&
newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
//Logic (maybe setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);)
}
}
You can achieve your goal both ways, it depends on when you want to go back to portrait.
Create one global variable as
boolean landscape = false;
then while clicking button;
rotate.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v) {
if(!landscape){
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
landscape = true;
}else{
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
landscape = false;
}
}});
So if you click the button again it'll switch to portrait mode again.
In my understanding
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
overrides the orientation you defined for that activity in AndroidManifest, e.g.:
android:screenOrientation="sensor"
To get the automatic orientation changes back you need to reset the orientation:
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
See my own question: Switch activiy on orientation changed?

Don't restart application on orientation change

I'm new to android development and have been making simple apps and in all of them have been making a method called void logic() that I have called at the end of my ViewDidLoad method. logic() contains all of the functionality that my app has. The issue with this is that whenever the screen changes orientation the ViewDidLoad method is re-called and then my app starts as if the application is being opened for the first time. Does anyone know how to do this? This is similar to this question Don't reload application when orientation changes however I do want ViewDidLoad to be re-called when the orientation is changed so that the view is recreated with the new orientation. However I don't want the application to be restarted. Thanks.
You can use :
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
or
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
And your activity manifest :
<activity android:name=".yourname"
android:configChanges="orientation|keyboardHidden">
</activity>

Saving the activity state when rotating the screen

I'm working on an android app, right now I limited the user to only use horizontal view for all activities.
I want to be able to give the user the option to rotate the screen, but when I do that, the activity starts from the beginning instead of just staying the same.
Any idea how to save the state when rotating the screen?
Firstly, you have to override onConfigurationChanged(Configuration) within your Activity.
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
You also have to edit the appropriate element in your manifest file to include the android:configChanges Just see the code below:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
I also like Marko's idea but it's simply not efficient. This way, we don't have to call onCreate/onStartup/etc. all the time we do a simple rotate. There is no need to "rebuild" the infrastructure from scratch (e.g. getting Views,..)
Each time you rotate the device, onCreate method is being called again. You can save the values by overriding onSavedInstanceState and get them back in onRestoreInstanceState or in onCreate method. For example lets save boolean(you can save whatever you want):
save the value:
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean("booleanValue", true);
}
restore the value (you can call this in onCreate as well):
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey("booleanValue")) {
boolean myBoolean = savedInstanceState.getBoolean("booleanValue");
}
super.onRestoreInstanceState(savedInstanceState);
}
<activity (...)
android:configChanges="orientation|keyboard"
(...)>
Adding this to your manifest does not allow Android to restart the activity after chaging the layout.

How to register a listener for orientation change?

My android app will run at background and I need to be notify immediately when orientation change. eg. When user rotate the phone from portrait to landscape (or landscape to portrait), the system should be tell my app that the orientation has changed.
Thanks.
This method is called when screen rotated
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//Do stuff here
}
You do not have to explicitly set the Orientation listener.
onConfigurationChanged will be called by the system.
#Override
public void onConfigurationChanged(Configuration myConfig) {
super.onConfigurationChanged(myConfig);
int orient = getResources().getConfiguration().orientation;
switch(orient) {
case Configuration.ORIENTATION_LANDSCAPE:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Configuration.ORIENTATION_PORTRAIT:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
But you can implement onConfigurationChanged in daemon.
here : Service.

Change orientation without loading again

I want to change the orientation, but i have two different xml, one for portrait and the other one for landscape. The same information appear in the screen, except that it's moved to use some space. If i do :
android:configChanges="keyboardHidden|orientation"
It will only change from portrait to landscape in the same xml.
How can i change that ?
Set your view as a class variable:
private TextView yourView;
Add the following to the onCreate() method:
if (savedInstanceState != null) {
((TextView)findViewById(R.id.yourview)).restoreState(savedInstanceState);
}
And add an override on the saving of the instance state to save the state
#Override
protected void onSaveInstanceState(Bundle outState) {
yourView.saveState(outState);
}
Finally:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
You should be able to manage config changes with this...
Override the onConfigurationChanged() method in your activity. Check the current orientation and set appropriate content view using setContentView().
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.getConfiguration() == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(landscape_layout);
} else {
setContentView(portrait_layout);
}
initViews();
}
In your Activity, override this method:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
This will be triggered when orientation is changed. You can find out in what orientation you are using the parameter.
That's not how android works. If you want a different layout for portrait/landscape you must let the system handle the configuration change for you and load the appropriate layout xml.
Put this in your manifest
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
It solves mine and your problem :)

Categories

Resources