Where to check for orientation change in an android fragment - android

In my app, I have a FragmentActivity with multiple Fragments all in portrait mode except for one specific Fragment. I move between Fragments through footer Views in the FragmentActivity.
I have a different layout (actually have the same name but different widget Views) for this specific Fragment when there is an orientation change. When in landscape mode, I want to remove specific widgets from the Fragment layout View and the footer View of the FragmentActivity and when back in portrait, add everything back.
I have saved all the data I need in onSavedInstanceState() in the Fragment, but where best should I possibly test for an orientation change so that I can restore the Views appropriately?
Not sure I can override onConfigurationChange() and test there in my Fragment because I don't have the android:configChanges="orientation" in my android Manifest.

Keep this check in onCreate(). When you rotate your device the app is restarted. So onCreate is called again when the app restarts.
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape
}
else {
// Portrait
}

You can control the orientation change by overriding onConfigurationChanged function of your fragment as well.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE){
Log.v("TAG","Landscape !!!");
}
else {
Log.v("TAG","Portrait !!!");
}
}

Related

Android Rotation (Load Layout) data loss (id and data / Custom Objects etc.)

I am turning a view, which is the same but horizontally. which contains many variables of type TextView, progressbar, imageview, etc .. but I can not load the variables when rotated.
I tried to do:
android: configChanges = "keyboardHidden | orientation | ScreenSize | ScreenLayout"
I find methods that can save my customized classes, my progressbar, my views "My nothing."
http://i.imgur.com/A1ugd3W.png
When there anyway to load a landscape (another layout (with the same id's)) of not losing data?
To change the layout I use:
http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged(android.content.res.Configuration)
Update Code 10/04/2015 (0:45 AM)
My rotation :
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_1);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_2);
}
}
Oncreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.activity_1);
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.activity_2);
}
References : Saving Android Activity state using Save Instance State Can't sabe all objects exits of an activity. "I think"
The easiest way would be to not specify orientation for the configChanges. Correspondingly, you will not need to override onConfigurationChanged -- you can simply load the layout in onCreate and state should for the most part be preserved. If needed state data can be stored in onSaveInstanceState (and restored in onCreate).
can you provide your code?
One possible issue is that you might be loading your layout file in onResume instead of onCreate. You need to create the layout in onCreate so the savedInstanceState info gets "injected" back into your app. But again, please provide codes :)
My guess is that elements of your layout don't have the same ID. Also, why don't you just have an XML for certain specifications - one for landscape and one for portrait? I bet Android would behave better if you did that instead of a different name for a different configuration

save value of a variable in a DialogFragment when the screen rotates

Well, I wanted to save value of a variable contained in a dialogFragment when the screen is rotated in Android. I've tried every method I could find on the internet, and none of them has worked for me. Some kill my application, and others simply were not doing anything.
I need a real and effective way to save the value of an EditText that is reset when the device screen rotates. The EditText is in a DialogFragment turn this into a FragmentActivity.
thank you very much
Set your fragment's retaingInstance flag to true:
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
This prevents Fragment instance from being recreated.
Also be sure you don't recreate the fragment all the time:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if (savedInstanceState == null) {
Fragment f = new Myfragment();
f.setRetainInstance(true);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, f))
.commit();
}
}
Since View state is preserved during Activity recreation and your are keeping the same Fragment instance you don't need to save TextView value all the time.
I don't know if I understood your question, but you can capture the rotation as follows:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
//save value
}
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
//save value
}
}
If you want that your activity don't restart, you should add this into the manifest file:
<activity
.....
android:configChanges="keyboardHidden|orientation|screenSize"
..... >
</activity>
I just found out that you can not apply the methods to save bundles automatically to the dialogues, but these would apply to activities or fragments of these dialogues dependent. If I can fix it by code, will put the solution here. thank you

handle configuration changes using ConfligChanges in the manifest

My app contains two fragments: list fragment, and detail fragment. Everything works fine.But when I change the orientation. everything gets messed up. I tried something like this to change orientation, it works in case of landscape to portrait, but doesn't work in portrait to landscape. Can anyone help me. here is my tried code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Fragment listfragment = getSupportFragmentManager().findFragmentById(
R.id.fragment_container);
Fragment detailfragment = getSupportFragmentManager().findFragmentById(
R.id.fragment_container2);
FrameLayout fragmentLayout2;
fragmentLayout2 = (FrameLayout) findViewById(R.id.fragment_container2);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (listfragment != null) {
replaceFragment(listfragment);
}
if (detailfragment != null) {
replaceNewFragment(detailfragment);
}
}
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
fragmentLayout2.setVisibility(View.GONE);
}
}
You need to override onConfigurationChanged on your mainActivity that extends ActionBarActivity for this to work. Something like this should work:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
getActionBar().setIcon(R.drawable.my_icon_land);//getSupportActionBar() for support library
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
getActionBar().setIcon(R.drawable.my_icon_potrait);
}
}
Call invalidateOptionsMenu() whenever you want to change the icons in the ActionBar. This'll redraw the ActionBar items and hence make a call to onPrepareOptionsMenu(). Inside onPrepareOptionsMenu(), you can check the orientation and set the respective layout for the menu items or just change the icons.
And since you want to recreate the menu on orientation change, you can call the invalidateOptionsMenu() method inside onCreate() because it will be called when the orientation changes.

Setting the orientation for only 1 fragment in my activity while the rest is in portrait

My app needs to be in portrait mode so I set it in the manifest by:
android:screenOrientation="portrait"
But I just recently added another fragment (FragA) that just looks and functions 10x better in landscape. Is there something I can put inside of my FragA to just make that fragment in landscape while retaining the rest of the app in portrait or by doing this will I have to add something to my other fragments to keep them retained as portrait?
Use the following code line in the fragment where you want a specific (in this case portrait) orientation.
getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
If you want to have a orientation in a fragment, that is based on the way the user holds his device, then use the following code line.
getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
Hope, this will give you the intended solution.
In each of your fragments, set the requested orientation.
Reference doc: http://developer.android.com/reference/android/content/pm/ActivityInfo.html
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Fragment locked in portrait screen orientation
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Fragment locked in landscape screen orientation
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// Fragment screen orientation normal both portait and landscape
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
Orientation attribute is per activity so you can declare the orientation for only the activity that contains the fragment so that it is in landscape and the rest of the activities will remain as they are.
So I'm dealing with this issue now. We have only portrait mode application (for now). But there is one fragment that needs to be in landscape. We are using single Activity approach so the accepted answer will not help me.
The fastest solution I could think of is this one.
private var swappingOrientation = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(savedInstanceState == null) {
swappingOrientation = true
activity?.apply {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
}
override fun onDestroy() {
super.onDestroy()
if(!swappingOrientation) {
activity?.apply {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
swappingOrientation = false
}
You hold the information if you are swapping orientation or not in swappingOrientation variable. At the beggining when the fragment is created it will change orientation, only when there is no saved state. And orientation is changed back again only when it is not being currently changed.
This is a super quick solution and it can produce screen blinking when you return to previous fragment. I also did not fully test it so it can have other issues, so keep that in mind.
First Fragment:
#Override
public void onResume() {
super.onResume();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Second Fragment:
#Override
public void onResume() {
super.onResume();
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
This is old question but answering this just incase anyone wanted the solution as the OP needed. The simple way to achieve this is as follows.
public class LandscapeFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
public View onDestroyView() {
super.onDestroyView();
getActivity().setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Then extend this LandscapeFragment from any of your fragment to which you want to launch it in landscape mode.
ok after i almost blew my head off this worked for me with jetpack navigation components fragments
so this is the base fragment class
abstract class BaseFragment : Fragment(){
var rotated = false
fun rotate() {
val currentOrientation = activity?.resources?.configuration?.orientation //this is diffrent from Configuration.ORIENTATION_LANDSCAPE
Log.e("currentOrientation--->",currentOrientation.toString())
if (currentOrientation != null) {
if (currentOrientation != Configuration.ORIENTATION_LANDSCAPE) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}else{
rotated=true
}
}else{
//impossible
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
}
override fun onDestroyView() {
super.onDestroyView()
if (rotated)
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
}
and i put this in any fragment i wish it to be landscaped
override fun onStart() {
super.onStart()
rotate()
}

After orientation switch, TextView is no longer updating

I have an Activity with a TextView, created in the usual findViewById method, using the definition from my xml layout file.
I'm updating the text in the TextView using a handler, created in the onCreate() method.
When I switch orientation, the TextView no longer updates from the same Handler.
If my xml definition states a value for android:text="blabla", then I see "blabla" in the view, but cannot update it anymore.
What's happening?!
When u switch orientation, android create new view.
I'd suggest making that mHandler volatile.
If u decide just to use only one orientation, for landscape add android:screenOrientation in activity tag in android manifest
The reason why you cannot update anymore is because Activity reference is different.
Your first created Activity 'A', has handler 'a'.
Now handler 'a' only can update view that belong Activity 'A'.
So when orientation happened, Activity 'A' is destroyed and Activity 'B' and handler 'b' is created.
So 'a' cannot update 'B's view in front of screen.
For quick solution I recommend you disable re-create activity when mobile orientation rotated.
AndroidManifest.xml
<activityandroid:name=".MyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name">
Activity
#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();
}elseif(newConfig.orientation ==Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this,"portrait",Toast.LENGTH_SHORT).show();
}
}
now onCreate will not be called when orientation.
Try using,
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//your code
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
//your code
}
}

Categories

Resources