I tried getOrientation() to get the orientation value but it always returns 0!
getOrientation() is deprecated but this is not neccesarily the root of your problem. It is true that you should use getRotation() instead of getOrientation() but you can only use it if you are targeting Android 2.2 (API Level 8) or higher. Some people and even Googlers sometimes seem to forget that.
As an example, on my HTC desire running Android 2.2. getOrientation() and getRotation() both report the same values:
0 (default, portrait),
1 (device 90 degree counterclockwise),
3 (device 90 degree clockwise)
It does not report when you put it "on its head" (rotate 180, that would be the value 2). This result is possibly device-specific.
First of all you should make clear if you use an emulator or a device. Do you know how to rotate the emulator? Then I would recommend to create a small test program with a onCreate() Method like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WindowManager mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display mDisplay = mWindowManager.getDefaultDisplay();
Log.d("ORIENTATION_TEST", "getOrientation(): " + mDisplay.getOrientation());
}
Check if the screen of your your device has been locked in the device settings Settings > Display > Auto-Rotate Screen. If that checkbox is unchecked, Android will not report orientation changes to your Activity. To be clear: it will not restart the activity. In my case I get only 0, like you described.
You can check this from your program if you add these lines to onCreate()
int sysAutoRotate = 0;
try {
sysAutoRotate = Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION);
} catch (SettingNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("ORIENTATION_TEST", "Auto-rotate Screen from Device Settings:" + sysAutoRotate);
It will return 0 if Auto-Rotate is off and 1 if Auto-Rotate is on.
Another try. In your original program you might have set in manifest
android:screenOrientation="portrait"
Same effect, but this time for your activity only. If you made the small test program this possibilty would have been eliminated (that's why I recommend it).
Remark: Yes the whole orientation / rotation topic is an "interesting" topic indeed. Try things out, use Log.d(), experiment, learn.
If you want to know if the content currently displayed is in landscape mode or portrait (possibly completely independent of the phone's physical rotation) you can use:
getResources().getConfiguration().orientation
Developer Documentation
public int orientation
Since: API Level 1
Overall orientation of the screen. May be one of ORIENTATION_LANDSCAPE, ORIENTATION_PORTRAIT, or ORIENTATION_SQUARE.
getOrientation() is deprecated. Instead, try getRotation().
To avoid use of Deprecated methods use the Android Configuration class found here. It works since API lvl 1 and still works on the latest android devices. (Not deprecated).
As and example consider the following code snippet:
Configuration config = getResources().getConfiguration();
if (config.orientation == Configuration.ORIENTATION_PORTRAIT)
{
setContentView(R.layout.portraitStart);
}
else
{
setContentView(R.layout.landscapeStart);
}
Best of luck- hope this answer helps whoever runs into it.
You should use:
getResources().getConfiguration().orientation
It can be one of ORIENTATION_LANDSCAPE, ORIENTATION_PORTRAIT.
http://developer.android.com/reference/android/content/res/Configuration.html#orientation
/* First, get the Display from the WindowManager */
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
/* Now we can retrieve all display-related infos */
int width = display.getWidth();
int height = display.getHeight();
int orientation = display.getOrientation();
I think you need to create two different layouts and inflate different layouts on different orientation. I am giving you a sample code which is working fine for me.
"context" you can pass from your activity in case of custom adapter.
If you are using custom adapter then you can try this code:
#Override
public View getView(final int position,
View convertView,
ViewGroup parent)
{
View rowView = convertView;
ViewHolder holder = null;
int i = context.getResources().getConfiguration().orientation;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (i == Configuration.ORIENTATION_PORTRAIT) {
rowView = inflater.inflate(R.layout.protrait_layout, null, false);
} else {
rowView = inflater.inflate(R.layout.landscape_layout, null, false);
}
holder = new ViewHolder();
holder.button = (Button) rowView.findViewById(R.id.button1);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
return rowView;
}
other wise you can directly set two different layouts in your code
int i = context.getResources().getConfiguration().orientation;
if (i == Configuration.ORIENTATION_PORTRAIT) {
ArrayAdapter<String> adt = new ArrayAdapter<String>(getApplicationContext(), R.layout.protrait_layout, name);
} else {
ArrayAdapter<String> adt = new ArrayAdapter<String>(getApplicationContext(), R.layout.landscape_layout, name);
}
I had the same problem on NexusOne SDK 2.3.
This solved it: Check orientation on Android phone.
Related
You would think that there would be a straight forward solution. The Android docs state:
The orientation sensor was deprecated in Android 2.2 (API level 8).
Instead of using raw data from the orientation sensor, we recommend
that you use the getRotationMatrix() method in conjunction with the
getOrientation() method to compute orientation values.
Yet, they don't provide a solution on how to implement getOrientation() and getRotationMatrix(). I've spent several hours reading through posts here on developers using these methods but they all have partially pasted code or some weird implementation. Googling hasn't provided a tutorial. Can someone please paste a simple solution using these two methods to generate the orientation??
Here is the implementation for getOrientation():
public int getscrOrientation()
{
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation = getOrient.getOrientation();
// Sometimes you may get undefined orientation Value is 0
// simple logic solves the problem compare the screen
// X,Y Co-ordinates and determine the Orientation in such cases
if(orientation==Configuration.ORIENTATION_UNDEFINED){
Configuration config = getResources().getConfiguration();
orientation = config.orientation;
if(orientation==Configuration.ORIENTATION_UNDEFINED){
//if height and widht of screen are equal then
// it is square orientation
if(getOrient.getWidth()==getOrient.getHeight()){
orientation = Configuration.ORIENTATION_SQUARE;
}else{ //if widht is less than height than it is portrait
if(getOrient.getWidth() < getOrient.getHeight()){
orientation = Configuration.ORIENTATION_PORTRAIT;
}else{ // if it is not any of the above it will definitely be landscape
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
}
}
return orientation; // return value 1 is portrait and 2 is Landscape Mode
}
And you can also refer this example which represent the use of both the methods:
getOrientation and getRotationMatrix
http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html
public int getScreenOrientation() {
// Query what the orientation currently really is.
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
return 1; // Portrait Mode
}else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
return 2; // Landscape mode
}
return 0;
}
protected void onResume() {
// change the screen orientation
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.portrait);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.landscape);
} else {
setContentView(R.layout.oops);
}
}
how to write the code that read the size of the screen. i have 4 different layout, "layout", "layout-land", "layout-large", and "layout-large-land"
every one of the layout i need to write a different code for each of them, for example at the "layout" , i have this code imagebutton1.setVisibility(View.VISIBLE); , but at the landscape screen, i have remove the imagebutton1. so i plan to if else statement, but i duno how to determine the size of the screen by using android java, need some guide here.
Technically, you could just do something like this:
ImageButton imageButton = findViewById(R.id.image_button);
if (imageButton1 != null) {
// if the imagebutton isn't found in the view hierarchy,
// then don't attempt to manipulate it.
imagebutton1.setVisibility(View.VISIBLE);
}
Otherwise you can use:
Configuration conf = getResources().getConfiguration();
boolean isLarge = (conf.screenLayout & Configuration.SCREENLAYOUT_SIZE_LARGE) ==
Configuration.SCREENLAYOUT_SIZE_LARGE;
boolean isLandscape = (conf.orientation == Configuration.ORIENTATION_LANDSCAPE);
boolean isLargeLand = isLarge && isLandscape;
Here's a pseudo code to detect screen rotate event, and decide to retain or changes the screen orientation.
public boolean onOrientationChanges(orientation) {
if(orientation == landscape)
if(settings.get("lock_orientation"))
return false; // Retain portrait mode
else
return true; // change to landscape mode
return true;
}
How do I make similar things in Android?
EDIT:
I'm actually looking answer on Where to handle orientation changes. I do not want to fix the orientation by adding screenOrientation="portrait".
I need something, similar to onConfigurationChanges(), where I can handle the orientation, but do no need me to manually redraw the view.
You need a Display instance firstly:
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
Then orientation may be called like this:
int orientation = display.getOrientation();
Check orientation as your way and use this to change orientation:
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
I hope it helps.
Update:
Okay, let's say you've an oAllow var which is Boolean and default value is False.
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
int orientation = display.getOrientation();
switch(orientation) {
case Configuration.ORIENTATION_PORTRAIT:
if(!oAllow) {
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
break;
case Configuration.ORIENTATION_LANDSCAPE:
if(!oAllow) {
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
break;
}
}
You can add more choices.
I didn't try this sample, but at least tells you some clues about how to solve. Tell me if you got any error.
UPDATE
getOrientation() is already deprecated see here. Instead Use getRotation(). To check if the device is in landscape mode you can do something like this:
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
int orientation = display.getRotation();
if (orientation == Surface.ROTATION_90
|| orientation == Surface.ROTATION_270) {
// TODO: add logic for landscape mode here
}
Try running
getResources().getConfiguration().orientation
From your context object to figure out what is the screen orientation at runtime, the possible values are documented here
In order to catch the orientation change event you can find the answer in the Android Dev Guide: Handling the Configuration Change Yourself
From the guide :
For example, the following manifest code declares an activity that
handles both the screen orientation change and keyboard availability
change:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">
Now, when one of these configurations change, MyActivity does not restart. Instead, the MyActivity receives a call to onConfigurationChanged(). This method is passed a Configuration object that specifies the new device configuration. By reading fields in the Configuration, you can determine the new configuration and make appropriate changes by updating the resources used in your interface. At the time this method is called, your activity's Resources object is updated to return resources based on the new configuration, so you can easily reset elements of your UI without the system restarting your activity.
...
if (this.getWindow().getWindowManager().getDefaultDisplay()
.getOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
// portrait mode
} else if (this.getWindow().getWindowManager().getDefaultDisplay()
.getOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
// landscape
}
You don't need to intercept the event and then override it. Just use:
// Allow rotation
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
// Lock rotation (to Landscape)
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
Points to note here are, if on Jellybean and above this will allow a 180 degree rotation when locked. Also when unlocked this only allows rotation if the user's master settings is to allow rotation. You can forbid 180 degree rotations and override the master settings and allow rotation, and much much more, so check out the options in ActivityInfo
In addition, if you have pre-set that there is to be no rotation, then your activity will not be destroyed and then restarted, just for you to set the orientation back which will again cause the activity to be restarted; Thus setting what you want in advance can be much more efficient.
Pre Jellybean use ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE -- no 180 degree rotation with this.
Check your android screen orientation at Runtime:
ListView listView = (ListView) findViewById(R.id.listView1);
if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
//do work for landscape screen mode.
listView.setPadding(0, 5, 0, 1);
} else if (getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
//Do work for portrait screen mode.
listView.setPadding(1, 10, 1, 10);
}
Another solution to determine screen orientation:
public boolean isLandscape() {
return Resources.getSystem().getDisplayMetrics().widthPixels - Resources.getSystem().getDisplayMetrics().heightPixels > 0;
}
I am using the XML tag
android:configChanges="orientation|keyboardHidden|keyboard"
and the following code to detect device orientation changes and change layouts:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
disp = getWindowManager().getDefaultDisplay();
swidth = disp.getWidth();
sheight = disp.getHeight();
parent.removeAllViews();
parent = new RelativeLayout(this);
if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
layoutPortrait();
else
layoutLandscape();
}
This works fine going form portrait to landscape. But, for whatever reason, going from landscape to portrait (starting in landscape or switching to it then back) doesn't change the screen back to portrait.
Through the use of Log messages I've determined that after being in Landscape mode, the Display and Configuration classes DO NOT UPDATE. They remain holding the same orientation/length/width values as when the device was in landscape.
Does anyone have any idea why this is?
Additional Code (requested by contributor)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disp = getWindowManager().getDefaultDisplay();
swidth = disp.getWidth();
sheight = disp.getHeight();
int ornt;
if(swidth == sheight)
ornt = Configuration.ORIENTATION_SQUARE;
else if(swidth < sheight)
ornt = Configuration.ORIENTATION_PORTRAIT;
else if(swidth > sheight)
ornt = Configuration.ORIENTATION_LANDSCAPE;
else
ornt = Configuration.ORIENTATION_UNDEFINED;
parent = new RelativeLayout(this);
labelOne = new TextView(this);
labelOne.setText("Temperature");
labelOne.setId((int)(Math.random()*Integer.MAX_VALUE));
temp = new EditText(this);
temp.setSingleLine(true);
temp.setBackgroundColor(Color.WHITE);
temp.setTextColor(Color.BLACK);
temp.setId((int)(Math.random()*Integer.MAX_VALUE));
labelTwo = new TextView(this);
labelTwo.setText("Humidity(%)");
labelTwo.setId((int)(Math.random()*Integer.MAX_VALUE));
humidity = new EditText(this);
humidity.setSingleLine(true);
humidity.setBackgroundColor(Color.WHITE);
humidity.setTextColor(Color.BLACK);
humidity.setId((int)(Math.random()*Integer.MAX_VALUE));
output = new TextView(this);
output.setBackgroundColor(Color.WHITE);
output.setTextColor(Color.BLACK);
output.setId((int)(Math.random()*Integer.MAX_VALUE));
submit = new Button(this);
submit.setText("Calculate");
submit.setId((int)(Math.random()*Integer.MAX_VALUE));
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Double result = Calculate.calculate(getInputs());
if(result !=null) {
String answer = String.format("%,.1f",result);
if(f.isChecked()) {
output.setText(answer + "°F");
} else {
output.setText(answer + "°C");
}
}
}
});
f = new RadioButton(this);
f.setText("Fahrenheit");
c = new RadioButton(this);
c.setText("Celsius");
rg = new RadioGroup(this);
rg.setOnCheckedChangeListener(new ListenForMode());
rg.addView(f);
rg.addView(c);
rg.setId((int)(Math.random()*Integer.MAX_VALUE));
f.setChecked(true);
if(ornt == Configuration.ORIENTATION_PORTRAIT || ornt == Configuration.ORIENTATION_SQUARE)
layoutPortrait();
else
layoutLandscape();
}
Final Update
Issue is with the emulator not responding correctly to the orientation changes. I changed the onConfigurationChanged(...) orientation checking to use the condition width < height for portrait and all else landscape. This works perfectly on my Android device.
Thanks to all contributors to this question!
You really shouldn't be overriding the configChanges in your manifest. Android can handle redrawing the Views for you, and it actually handles it really well, especially if you have filtered layouts in your resource folder.
If you are overriding configChanges because of issues with AsyncTask losing its Context (as I once did), I would recommend using an IntentService to handle your asynchronous work as Services aren't tied to any one Activity.
If it happens on emulator, then it's OK - emulator behaves a little bit weird in sense of configuration changes. I have been trying to solve similar problem, unless I noticed that the app worked fine on a real device.
It seems that the emulator ignores the android:configChanges="orientation" attribute, but in a bit strange way: it does force the configuration change but doesn't call onConfigurationChanged(..) method every time it should be called.
I'm working with a ListView, trying to get the convertView / referenceHolder optimisation to work properly but it's giving me trouble. (This is the system where you store the R.id.xxx pointers in as a tag for each View to avoid having to call findViewById). I have a ListView populated with simple rows of an ImageView and some text, but the ImageView can be formatted either for portrait-sized images (tall and narrow) or landscape-sized images (short and wide). It's adjusting this formatting for each row which isn't working as I had hoped.
The basic system is that to begin with, it inflates the layout for each row and sets the ImageView's settings based on the data, and includes an int denoting the orientation in the tag containing the R.id.xxx values. Then when it starts reusing convertViews, it checks this saved orientation against the orientation of the new row. The theory then is that if the orientation is the same, then the ImageView should already be set up correctly. If it isn't, then it sets the parameters for the ImageView as appropriate and updates the tag.
However, I found that it was somehow getting confused; sometimes the tag would get out of sync with the orientation of the ImageView. For example, the tag would still say portrait, but the actual ImageView would still be in landscape layout. I couldn't find a pattern to how or when this happened; it wasn't consistent by orientation, position in the list or speed of scrolling. I can solve the problem by simply removing the check about convertView's orientation and simply always set the ImageView's parameters, but that seems to defeat the purpose of this optimisation.
Can anyone see what I've done wrong in the code below?
static LinearLayout.LayoutParams layoutParams;
(...)
public View getView(int position, View convertView, ViewGroup parent){
ReferenceHolder holder;
if (convertView == null){
convertView = inflater.inflate(R.layout.pick_image_row, null);
holder = new ReferenceHolder();
holder.getIdsAndSetTag(convertView, position);
if (data[position][ORIENTATION] == LANDSCAPE) {
// Layout defaults to portrait settings, so ImageView size needs adjusting.
// layoutParams is modified here, with specific values for width, height, margins etc
holder.image.setLayoutParams(layoutParams);
}
holder.orientation = data[position][ORIENTATION];
} else {
holder = (ReferenceHolder) convertView.getTag();
if (holder.orientation != data[position][ORIENTATION]){ //This is the key if statement for my question
switch (image[position][ORIENTATION]) {
case PORTRAIT:
// layoutParams is reset to the Portrait settings
holder.orientation = data[position][ORIENTATION];
break;
case LANDSCAPE:
// layoutParams is reset to the Landscape settings
holder.orientation = data[position][ORIENTATION];
break;
}
holder.image.setLayoutParams(layoutParams);
}
}
// and the row's image and text is set here, using holder.image.xxx
// and holder.text.xxx
return convertView;
}
static class ReferenceHolder {
ImageView image;
TextView text;
int orientation;
void getIdsAndSetTag(View v, int position){
image = (ImageView) v.findViewById(R.id.pickImageImage);
text = (TextView) v.findViewById(R.id.pickImageText);
orientation = data[position][ORIENTATION];
v.setTag(this);
}
}
Thanks!
Rather than putting orientation as a data member of ReferenceHolder, examine the actual LayoutParams of the ImageView to see what orientation it is in. This way, by definition, you can't get out of sync somehow.
To be honest, I'm confused by the code you have there, as you never seem to change layoutParams, which would seem to be kinda important. Or, shouldn't you have layoutParamsPortrait and layoutParamsLandscape or something? To me, it looks like the rules are:
If it's portrait and the row is initially created, leave it portrait
Everything else is landscape, regardless of what the orientation flag says, since you always set it to layoutParams, which is presumably landscape