I have two screens and two xml-files for one activity. In my onCreate method I call the fist one and handle some user input. After that I am changing my layout with
setContentView(R.layout.activity_quiz2);
and everything is fine and works as intended but when I run the application and turn my device after I switched the layouts. It will just switch back to the first layout and stay on that layout (every button and all works as well).
How can I prevent my screen from changing back my layouts when I turn my device?
It's switching back to the first layout because when you rotate the screen the whole Activity is recreated. You have couple of options to deal with this:
Add android:configChanges="orientation" to your <activity element in the AndroidManifest.xml file. This way you're telling the system you want to deal with the rotation yourself (and if needed you can perform some actions in onConfigurationChanged() method).
Use Fragments to display the two "states" you have (I'm assuming those are quiz1 and quiz2). This way you won't need to do multiple setContentView() in your activity.
The second option is the one to go for, as that's basically what Fragments are all about. Not to mention you can do very nice transitions between them (fade-in-out animations, etc) and your UX will be much better than when swapping the setContentView().
Related
I was wondering why not use android:configChanges="keyboardHidden|orientation" in every (almost every ;)) activity?
Goods:
no need to worry about your activity been rotated
it's faster
Not so nice:
need to change your layouts if they are depending on screen size (e.g. layouts with two columns or so)
Bad:
no flexible way to have different layouts on different orientation
not so good when using fragments
But if we don't use different layouts, why not?
Quick Background
By default, when certain key configuration changes happen on Android (a common example is an orientation change), Android fully restarts the running Activity to help it adjust to such changes.
When you define android:configChanges="keyboardHidden|orientation" in your AndroidManifest, you are telling Android: "Please don't do the default reset when the keyboard is pulled out, or the phone is rotated; I want to handle this myself. Yes, I know what I'm doing"
Is this a good thing? We shall soon see...
No worries?
One of the pros you start with is that there is:
no need to worry about your activity been rotated
In many cases, people mistakenly believe that when they have an error that is being generated by an orientation change ("rotation"), they can simply fix it by putting in android:configChanges="keyboardHidden|orientation".
However, android:configChanges="keyboardHidden|orientation" is nothing more than a bandaid. In truth, there are many ways a configuration change can be triggered. For example, if the user selects a new language (i.e. the locale has changed), your activity will be restarted in the same way it does by an orientation change. If you want you can view a list of all the different types of config changes.
Edit: More importantly, though, as hackbod points out in the comments, your activity will also be restarted when your app is in the background and Android decides to free up some memory by killing it. When the user comes back to your app, Android will attempt to restart the activity in the same way it does if there was some other configuration change. If you can't handle that - the user will not be happy...
In other words, using android:configChanges="keyboardHidden|orientation" is not a solution for your "worries." The right way is to code your activities so that they are happy with any restart Android throws at them. This is a good practice that will help you down the road, so get used to it.
So when should I use it?
As you mentioned there is a distinct advantage. Overwriting the default configuration change for a rotation by handling it yourself will speed things up. However, this speed does come with a price of convenience.
To put it simply, if you use the same layout for both portrait and landscape you're in good shape by doing the overwrite. Instead of a full-blown reload of the activity, the views will simply shift around to fill the remaining space.
However, if for some reason you use a different layout when the device is in landscape, the fact that Android reloads your Activity is good because it will then load up the correct layout. [If you use the override on such an Activity, and want to do some magical re-layout at runtime... well, good luck - it's far from simple]
Quick Summary
By all means, if android:configChanges="keyboardHidden|orientation" is right for you, then use it. But PLEASE be sure to test what happens when something changes, because an orientation change is not the only way a full Activity restart can be triggered.
From my point of view: If the layout is the same in both landscape and portrait mode - you might aswell disable one of the two in your app.
The reason why I state this is that I as a user expect the app to provide me with some benefit, when I change orientation. If it doesn't matter how I hold my phone, then I don't need the choice.
Take for instance an app where you have a ListView, and upon clicking a ListItem you want to be shown a detailed view for that item. In landscape you would od this by dividing the screen in two, having the ListView on the left and the detailed view on the right. In Portrait you would have the list in one screen and then change the screen to the detailed view when a ListItem is selected. In that case orientation change makes sense as well as different layouts.
I don see why.... occasional restarts are ok in my opinion... configChanges handles most cases for me... well maybe in some types of applications this can be problem but it depends really on type of app and how you restore state when app restarts... When one of my app restarts user is logged back and last activity opens by my code and user jus loses some steps to go back where he was but not big deal.. In other some state is always persisted and some state is always restored on restart. When activity restarted it had to be that app have not been used or something... so no problem at all... In game for example this can be problem maybe or in some other type of app I don't know...
I say that when you do it this way applications just works fine under normal circumstances. And code is much more readable without ton of logic needed for saving and restoring where u just can make new bugs and have to maintain it all the time... sure if android gets out of power and kill you application window it lose the context and starts again, but this happen just in special situations and on newer devices I belive this is more and more rare...
So kill me, but I use this across applications quite successfully...
android:configChanges="locale|keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
But I understand that for some special kind of applications it may be not good way but most of apps can live with this just OK.
Yeah I think pausing will make it quicker than releasing the player. Still have the pause though.
Have now found a solution that won't pause the song.
State in the manifest that you will handle the config change for screen orientation and then use the onConfigurationChanged method to load the layout file. By doing this in logCat I can see onPause, onCreate & onResume aren't called, and therefore the song isn't paused.
update the manifest to handle the orientation.
android:configChanges="orientation|screenSize"
add this code
#Override
public void onConfigurationChanged(Configuration newConfig) {
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
}
I have a monitoring app that displays a set of four parameters as animations (for example, it displays the temperature using a thermometer graphic). I also have one screen which plots all the four parameter values on a chart.
My requirement is this:
Whenever the device is in Landscape mode, the chart should be displayed.
Whenever the device is back in portrait mode, the earlier animation screen should be displayed.
I'm wondering if it is possible to provide different functionality based on the orientation. I see 2 options
Override Activity.onConfigurationChanged() - but then what? Can i do a setContentView() at this point? Or, can i launch a different Activity (one which displays the Chart in a separate, lanscape-mode-only Activity)?
Override Application.onConfigurationChanged() method. But I frankly haven't a clue as to how to proceed with this.
Yes you can call setContentView() inside Activity.onConfigurationChanged(). You can check orientation and accordingly perform some tasks, i.e. run different code based on orientation.
Normal behaviour is that when orientation changes, system kills Activity and creates a new one. You can prevent this with android:configChanges="orientation" in you activity manifest. In this case you need to override the onConfigurationChanged(..) method, which will be called when change happens. See handling runtime changes.
I am making a game where I will go from my main screen to a battle screen and the back when the battle is finished. Is it better to have the two screens as separate activities or can I get by using the setContentView(R.layout.screen2)?
I've been trying to get the activity screen switching to work but everytime I try it, my phone tells me that the app isn't responding. If it is better to use the activities, then I'll take the time to work it out, but for now I'll take the easy way out to get things working.
Calling setContentView() multiple times is not recommended. The normal way to switch between layouts in the same activity is to use a ViewFlipper or FrameLayout (see Calling setContentView() multiple times and How can i make a dynamic flipping screen(like that of iPhone) in Android)
Alternatively you could use ViewSwitcher, which seems to fit your needs pretty well. There's a good detailed tutorial available at http://inphamousdevelopment.wordpress.com/2010/10/11/using-a-viewswitcher-in-your-android-xml-layouts/
The simplest way to change view of an activity dynamically would be to inflate the target view into the activity's root ViewGroup (FrameLayout preferably). This is just a one line code
inflater.inflate(R.layout.target_view,(ViewGroup)findViewById(R.id.activity_root_viewgroup), true);
Sorry, I know that this topic has been covered a bit. I've read the related posts and am still a bit confused. I am working on an app that while the prototype will have 3 main screens, it will eventually have dozens. Each screen will present either dynmically changing status or take user input. To visualize, it is required to be laid out similar to how MS Word or a typical PC is. It has a status bar at the top and a navigation bar at the bottom that is common to all screens (slight tweaks for some screens, like different icons) in the middle is what I would call a view pane that needs to be updated with a applicable layout.
The status, nav bar, and each screen are defined in their own layout xml file. For my first swag at it I just used a ViewFlipper and loaded the 3 screen layouts into it. However that means that currently I have one main Activity which will not be maintainable as I continue to add screens.
It feels right to me that each screen layout should have an associated Activity class that understands how to control that screen. I need to figure out how to load that into the center pane dynamically. However I thought I read in another post that using multiple Activities can be a CPU and RAM drain.
Currently I tried making one of the screens it's own Activity and kick that off from the main Activity by creating an Intent and than calling startActivity. However that causes the new screen Activity to reside on top of the main Activity. The interesting thing is that then pressing the back button dismissed that activity and returns me to the main.
So far I haven't figured out how to setup having a different Activity control what happens in the center pane.
If I continue down the multiple Activity path, should my main Activity be inheriting from ActivityGroup?
Are using View classes more applicable in this case?
I know this has been a long post. I'd appreciate any advice.
Thanks!
CB
As you noticed, Android will implicitly track a stack of started activities in a task, and the 'back' button ends the top one, reactivating the next one down. I would advise you to think about which kinds of things the user might expect the back button to do, and make it so that activities are separated along those lines.
I haven't played with ActivityGroup so I can't advise you there. If you go with completely separate activities, you can have them all use the same "shell" content view with the common nav/status bar. Have a superclass or utility class handle populating and managing that from there. Then use a a LayoutInflater (you can call getLayoutInflater()) to fill in the middle with your Activity-specific view.
If you want one of the activities to have multiple screens, you might still end up with a ViewFlipper in the center slot. Again, you want to have an Activity transition wherever you want the user to be able to go "back"; that also means you may NOT want to have a change of activities in cases where screens are closely related or part of the same logical thing-being-done. (You can override the back button's behavior, but unless you have a good reason to, it's best to just arrange the app so that Android's basic setup helps your app's UI rather than working at cross purposes.)
If you want to use activities in the fashion you talked about, you might look into using a tab activity. It actually works in the way you want, you just need to hide the tab widget and put your navigation bar there instead. Or, you could go a little deeper and make you own similar tab-like ActivityGroup like Walter mentioned if you have more time.
You could use a view pager with fragments to accomplish the flip between the different views but still allow your activity to have full control over it. The activity can control the menus while the fragment controls your viewing area. This way your back button will properly dismiss the activity containing all pages related to the activity instead of walking down the stack.
I have an NoContentViewActivity which has no Content View (i.e. I did not call setContentView() in the onCreate of my Activity).
My question is how can I keep the content view of the launching activity on the screen? Right now, I am getting a blank screen whenever I launch NoContentViewActivity? I want the content view of the launching activity (the activity which start the NoContentViewActivity) to show on the screen.
Thank you for any help.
Excuse me, people, but my guess is that hap497 wants exactly the thing he wants. There is a bunch of situations where invisible activity would fit while Service will not.
Imaging you want to show a set of dialogs, each next of them is shown after the previous one based on the user choices. And imaging you want to have this (exactly the same) functionality to be available when pressing different buttons on different (lots of them) activities.
To write the same dialog processing logic would be an overkill whether the transparent activity will deal nicely...
Anyway, as stated above, all you need to do is to specify:
android:theme="#android:style/Theme.Translucent"
or
android:theme="#android:style/Theme.Translucent.NoTitleBar"
(if you do not want a titlebar either)
It sounds like you'd be better off using a Service than an Activity. Activities are for code that is to be viewed; Services are for code that runs without a UI, which is what it sounds like you want.
An Activity with no Views assigned is an empty black screen, so it will still obscure the calling Activity. You could make your Activity transparent by assigning it a transparent theme:
android:theme="#style/Theme.Translucent"
Keep in mind though, that your invisible Activity will have focus, so the user won't be able to interact with the Activity underneath.
Why do you want to create a fully transparent Activity? As Daniel suggests, a Service might be a better solution to your problem if you genuinely don't want any user interaction.