views:

130

answers:

2

I am having trouble setting up landscape mode in my application.

I have a /res folder that contains a layout folder and a layout-land folder

layout
-----main.xml

layout-land
-----main.xml

My /layout-land/main.xml contains different UI elements than /layout/main.xml. How can I map each layout appropriately when the user has switched to landscape mode and vice versa?

I am basically displaying a full screen ImageView when the user switches to landscape mode. The ImageView will download an image from the internet and display it. Switching back to portrait, should simply go back to my portrait mode, which has a different set of UI components.

I get a crash when I switch to landscape mode:

because I can't get the id:

chartImageViewLandscape = (ImageView) this.findViewById(R.id.chartImageViewLandscape);

chartImageViewLandscape is in /layout-land/main.xml

How can I get a reference to this?

+1  A: 

What is the question exactly ?

Do you define the android:orientation in both of your layouts ? Beside that, nothing else to do. Android will switch by itself.

If you have different UI components, you probably want to still declare them in both layouts so that any call to findViewById will not crash your app. Just make the layout so that they are not displayed (in a FrameLayout, behind the image for example)

If you prefer to do it more manually, you need to put an android:configChanges="orientation" in your manifest and implement onConfigurationChanged

Matthieu
Sounds good. Also, as far as having it download from the internet on changing the configuration goes, you should definitely find a way to store the image in between orientation changes (for one I've done, I used onRetainNonConfigurationInstance() to save an object and getLastNonConfigurationInstance() to restore the image) so that it doesn't try to redownload the image every time it goes from portrait to landscape and vice versa.
kcoppock
updated with more details on my problem. @kcoppock can you show me an example of your onRetainNonConfigurationInstance()?
Sheehan Alam
A: 

Sheehan, regarding onRetainNonConfigurationInstance(), below is what I am currently doing for my app in progress. I have the feeling I'm overcomplicating it though, I think there's a simpler way; however, this works just fine for me currently:

So in my activity class "RotationMenu.java":

private Object catcher;
//lots of non-related code here

//directoryList is a returned list of selected directories, that I wish to
//retain in the event of an orientation state change.
String[] directoryList = new String[arrayList.size()];
arrayList.toArray(directoryList);

//here, I set the class Object catcher to the directoryList
catcher = directoryList;

//rest of non-related code

//this method is called when the orientation changes (for me,
//when I open my Droid's hardware keyboard)
public Object onRetainNonConfigurationInstance()
{
    //If I've entered anything into my catcher Object, it will be kept
    //across orientation changes.
    final Object data = catcher;
    return data;
}

Now, in my onCreate(Bundle savedInstanceState) method:

//We retrieve the stored Object and cast it to a String array
final Object recipient = (String[]) getLastNonConfigurationInstance();

//in case the state changes again before the code that sets the directories is run
catcher = recipient;

//if there was any stored data, we can now reinstate the list adapter where the
//directoryList was originally being used.
if(recipient != null)
{
    returnedDirectories.setAdapter(new ArrayAdapter<String>(
        this.getBaseContext(),
        R.layout.simple_list_item_small,
        (String[])recipient));
}

Again, this is how I am doing it currently. If anyone knows of a more efficient method, by all means comment. :)

kcoppock
I'll try and implement this into my own code! Do you know how I can pull chartImageViewLandscape from my /layout-land/main.xml? Seems like it is always null!
Sheehan Alam
You don't want to actually store the View object, from my understanding, that will cause memory leaks. Instead, store the bitmap or drawable that the ImageView contains, and then set that back to the chartImageViewLandscape View in the onCreate() method.
kcoppock
but I can't even set chartImageViewLandScape because I need to be able to hook it up to the layout via findViewById
Sheehan Alam
You shouldn't have to. As long as the layout names are the same, it will look it up by its ID, no matter where you move it. Maybe I am misunderstanding?
kcoppock
/layout-land/main.xml has only an ImageView and nothing else. /layout/main.xml has a listview, and some buttons etc. Hope that clarifies things a bit?
Sheehan Alam
It does, but both ImageViews should have the same android:id. If so, there should be no issue (except when your code tries to access the id of your listview and buttons when in landscape mode).
kcoppock
What do you mean by both ImageViews? The ImageView created in code, and the ImageView in my layout? The weird thing is, there are no compile errors, just at runtime chartImageViewLandscape is null.
Sheehan Alam
The ImageView in your layout will default to whatever value you have defined in the XML. the chartImageViewLandscape is an ImageView object that references that object in your layout. So when you change orientations, onCreate() will be called again, and so the line "chartImageViewLandscape = (ImageView)findViewById(R.id.chartImageViewLandscape)" will be called again, only this time it will find the view from your landscape XML layout.
kcoppock
Thanks for the extremely detailed answer, and follow thru. I understand fully what is going on, and have implemented your configuration instance code, and it is working as expected.
Sheehan Alam
You're welcome! Glad you got it working!
kcoppock