Fragment || onConfigurationChanged || Duplicate

I have problems with fragment when the screen orientation changes. In my code, I have create different layout xml according to the screen orientation. For example, I have header_landscape.xml and header_portrait.xml in the layout directory. And each different header has the same fragment in the linear layout. So when I turn my device, I have the error "duplicate id ..." that corresponding to my fragment.

The differences between layout is the content.When I am in "landscape" I display more informations than I am in "portrait".

On create of my activity :

 setContentView(R.layout.main_landscape); 

                //header
                date=(TextView)findViewById(R.id.headerLandscapeDate);
                routeSens=(TextView) findViewById(R.id.headerLandscapeRouteSens);
                pkHeader=(TextView) findViewById(R.id.headerLandscapePk);

                //Récupération de la listview créée dans le fichier main.xml
                maListViewPerso = (ListView) findViewById(R.id.ListeChoix);      

                //On attribut à notre listView l'adapter que l'on vient de créer
                maListViewPerso.setAdapter(chargeMenu());

$ The code of the modification of layout when the orientation screen changes.

 public void onConfigurationChanged(Configuration newConfig)
 {
        super.onConfigurationChanged(newConfig);


        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE && isLoaded && oldScreenStateOrientation!=newConfig.orientation)
        {

            setContentView(R.layout.main_landscape);

            //header
            date=(TextView)findViewById(R.id.headerLandscapeDate);
            routeSens=(TextView) findViewById(R.id.headerLandscapeRouteSens);
            pkHeader=(TextView) findViewById(R.id.headerLandscapePk);

            maListViewPerso = (ListView) findViewById(R.id.ListeChoix);  
            //On attribut à notre listView l'adapter que l'on vient de créer
            maListViewPerso.setAdapter(chargeMenu());
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT && isLoaded && oldScreenStateOrientation!=newConfig.orientation)
        {

            setContentView(R.layout.main_portrait);


            routeSens=(TextView) findViewById(R.id.headerPortraitRouteSens);
            pkHeader=(TextView) findViewById(R.id.headerPortraitPk);

            maListViewPerso = (ListView) findViewById(R.id.ListeChoix);  
            //On attribut à notre listView l'adapter que l'on vient de créer
            maListViewPerso.setAdapter(chargeMenu());
        }
      }

If anyone have a solution. I developp with the api8 (compatibility library fragment).

Sorry for my english.

Thanks

Answers


You should let android do all that configuration switching for you! Don't do anything in "onConfigurationChanged", remove all configuration changes from your manifest even!

Put your portrait layout in layout/ folder

and put your landscape layout in layout-land/ folder

Make sure they are both named: main.xml (or anything, as long as it is the same)

Then in your activity.onCreate, do something like this:

    // Will automatically select the correct layout
    setContentView(R.layout.main); 

    //header
    // If this is in portrait, date will be null. Check for that later
    date=(TextView)findViewById(R.id.headerDate);
    routeSens=(TextView) findViewById(R.id.headerRouteSens);
    pkHeader=(TextView) findViewById(R.id.headerPk);

    //Récupération de la listview créée dans le fichier main.xml
    maListViewPerso = (ListView) findViewById(R.id.ListeChoix);      

    //On attribut à notre listView l'adapter que l'on vient de créer
    maListViewPerso.setAdapter(chargeMenu());

This way, you can let android worry about which configuration to use. If you only want to display the landscape view on large screens, you could put it in a folder such as layout-w1024dp. This way you can have multiple layouts very easily.


If you need to handle orientation change yourself for some reason, a solution is to remove the fragment before calling setContentView(). Here is the code that worked in my case:

    @Override
    public void onConfigurationChanged(final Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // We must remove the fragment, otherwise we get a duplicate ID error when the
        // onCreateView() method is executed.
            final FragmentManager fm = this.getSupportFragmentManager();
        ExtrasFragment ef = (ExtrasFragment) fm.findFragmentByTag(ExtrasFragment.FRAGMENT_TAG);
        if( ef != null ) {  // for small screens the fragment is not embedded in this activity
            final FragmentTransaction ft = fm.beginTransaction();
            ft.remove(ef);
            ft.commit();
            ef = null;
            fm.executePendingTransactions();
        }
        this.setContentView(R.layout.main); // contains the ExtrasFragment
    ...
}

Need Your Help

scala : no common ancestor available for asInstanceOf[]

scala class inheritance

I created some case classes used as messages in akka.

On-the-fly bank account numbers verification

validation emacs elisp iban

Today I had to copy a bank account number from a real (dead tree) letter to an Emacs buffer and then send it by email. And I made a mistake while copying it from the letter to the Emacs buffer (fo...