简体   繁体   中英

Prevent activity from reload after rotation in xamarin, monodroid

Ok... So my problem is to prevent from activity to reload after orientation is changed. Basically, what I did is this:

[Activity(Label = "migs", ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation)]

This is worked fine, until I changed "Target API" to 14. If I'm changing it back to 12, then everything is working, but on 14, activity is being restarted (OnCreate method is fires after rotation). So... You'll ask why do I need "Target API" 14? - Easy! Because in my app, I'm playing video, and for that I need "true full screen". All API's below 14 adding "Settings" (three dots) button. In case of HTC, it's big and ugly button, that I was unable to get rid of.

If you know how to do one of the two (Get rid of the "settings" button in API 12, or prevent activity from reload after orientation changed in API 14), I'll be very thank full for your help.

Ok... At last I solved it! :) Saving activity state instead of preventing activity from reload, from first sight can seem to be a little tricky, but in fact is really easy and it's the best solution for situations like this. In my case, I had a ListView, that populates from the internet with items, that stored in custom list adapter. If device orientation was changed, the activity was reloaded, so does the ListView, and I was loosing all the data. All I needed to do is to override the OnRetainNonConfigurationInstance method. Here's a quick sample of how to do it.
First of all, we need a class, that can handle all of our stuff.

Here is a wrapper for all the things we need to save:

public class MainListAdapterWrapper : Java.Lang.Object
{
    public Android.Widget.IListAdapter Adapter { get; set; }
    public int Position { get; set; }
    public List<YourObject> Items { get; set; }
}

In our activity, we need to hold variables, to store all the data:

ListView _listView; //Our ListView
List<YourObject> _yourObjectList; //Our items collection
MainListAdapterWrapper _listBackup; //The instance of the saving state wrapper
MainListAdapter _mListAdapter; //Adapter itself

Then, we overriding the OnRetainNonConfigurationInstance method in the activity:

public override Java.Lang.Object OnRetainNonConfigurationInstance()
{
    base.OnRetainNonConfigurationInstance();
    var adapterWrapper = new MainListAdapterWrapper();
    adapterWrapper.Position = this._mListAdapter.CurrentPosition; //I'll explain later from where this came from
    adapterWrapper.Adapter = this._listView.Adapter;
    adapterWrapper.Items = this._yourObjectList;
    return adapterWrapper;
}

And the final stage is to load saved state in OnCreate method:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.list);

    this._listView = FindViewById<ListView>(Resource.Id.listView);

    if (LastNonConfigurationInstance != null)
    {
        this._listBackup = LastNonConfigurationInstance as MainListAdapterWrapper;
        this._yourObjectList = this._listBackup.Items;
        this._mListAdapter = this._listBackup.Adapter as MainListAdapter;
        this._listView.Adapter = this._mListAdapter;

        //Scrolling to the last position
        if(this._listBackup.Position > 0)
            this._listView.SetSelection(this._listBackup.Position);
    }
    else
    {
        this._listBackup = new MainListAdapterWrapper();
        //Here is the regular loading routine
    }

}

And about the this._mListAdapter.CurrentPosition ... In my MainListAdapter , I added this property:

public int CurrentPosition { get; set; }

And the, in the `GetView' method, I did that:

this.CurrentPosition = position - 2;

PS

You don't have to implement exactly as I showed here. In this code, I'm holding a lot of variables, and making all the routine inside the OnCreate method - that is wrong. I did that, just to show how it can be implemented.

what happen when orientation change (consider you enable rotation in your phone) ?

Android restart activity onDestroy() is called, followed by onCreate() , you can distinguish between onDestroy() call to kill activity or restart app throw old answer .

Prevent Activity restart

just set ConfigurationChanges to both Orientation , ScreenSize

[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]

why this may be not working ?

I dont think this will not working but set RetaintInstance to true read more about RetainInstance

class myFragment: Fragment
    {

        public override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            this.RetainInstance = true;
          // this to change screen orientation 
            Activity.RequestedOrientation = ScreenOrientation.Landscape;


        }

       .....

}

hope this help

Above API 13, you need to include screensize in your ConfigChanges.

As denoted here.

Maybe adding that tag to your activity for API13+ will help?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM