How to correctly restore view state after rotation

I am trying to handle the rotation for a complex view manually, including restoring the position and size of the prefix. At this moment I am trying to do this in onLayout (better ideas are welcome). Sometimes this works well, but often the first rotation is misuse or viewing is drawn without children.

 private int oldOrientation = -1; /** * Override method to configure the dragged view and secondView layout properly. */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.e("mylayout", "onLayout " + df.format(new Date(Calendar.getInstance().getTimeInMillis()))); if (isInEditMode()) { super.onLayout(changed, left, top, right, bottom); } else { dragView.setVisibility(INVISIBLE); if (isDragViewAtTop() && (oldOrientation != getResources().getConfiguration().orientation || oldOrientation == -1)) { dragView.layout(left, top, right, transformer.getOriginalHeight()); secondView.layout(left, transformer.getOriginalHeight(), right, bottom); ViewHelper.setY(dragView, top); ViewHelper.setY(secondView, transformer.getOriginalHeight()); ViewHelper.setX(dragView, left); ViewHelper.setX(secondView, left); oldOrientation = getResources().getConfiguration().orientation; } else if (isClosedAtLeft() && ( oldOrientation != getResources().getConfiguration().orientation || oldOrientation == -1)) { dragView.layout(left, top, right, transformer.getOriginalHeight()); secondView.layout(left, transformer.getOriginalHeight(), right, bottom); ViewHelper.setY(dragView, top); ViewHelper.setY(secondView, transformer.getOriginalHeight()); ViewHelper.setX(dragView, left); ViewHelper.setX(secondView, left); closeToLeft(); oldOrientation = getResources().getConfiguration().orientation; } else if (isClosedAtRight() && ( oldOrientation != getResources().getConfiguration().orientation || oldOrientation == -1)) { dragView.layout(left, top, right, transformer.getOriginalHeight()); secondView.layout(left, transformer.getOriginalHeight(), right, bottom); ViewHelper.setY(dragView, top); ViewHelper.setY(secondView, transformer.getOriginalHeight()); ViewHelper.setX(dragView, left); ViewHelper.setX(secondView, left); closeToRight(); oldOrientation = getResources().getConfiguration().orientation; } else if ((oldOrientation != getResources().getConfiguration().orientation || oldOrientation == -1)) { dragView.layout(left, top, right, transformer.getOriginalHeight()); secondView.layout(left, transformer.getOriginalHeight(), right, bottom); ViewHelper.setY(dragView, top); ViewHelper.setY(secondView, transformer.getOriginalHeight()); ViewHelper.setX(dragView, left); ViewHelper.setX(secondView, left); smoothSlideTo(SLIDE_BOTTOM); oldOrientation = getResources().getConfiguration().orientation; } dragView.setVisibility(VISIBLE); } } 

In this code, I try to restore the initial stte after rotation, when onLayout is called, and then moves it into place, the view was before rotation (there are 4 states, from the cross to the left, from the screen to the right, the upper part of the screen or the lower right corner).

Edit:

 <?xml version="1.0" encoding="utf-8"?> <manifest package="com.github.pedrovgs.sample" xmlns:android="http://schemas.android.com/apk/res/android"> <uses-sdk android:minSdkVersion="8" /> <!-- Permissions --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:glEsVersion="0x00020000" android:required="true" /> <!-- Application configuration --> <application android:name=".DraggablePanelApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <!-- Maps API KEY --> <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyC1rMU-mkhoyTvBIdTnYU0dss0tU9vtK48" /> <!-- Main Activity --> <activity android:name=".activity.MainActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- Places sample --> <activity android:name=".activity.PlacesSampleActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/places_sample_activity_title" /> <!-- TV Shows sample --> <activity android:name=".activity.TvShowsActivity" android:label="@string/tv_shows_sample_activity_title" /> <!-- Youtube Sample --> <activity android:name=".activity.YoutubeSampleActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/youtube_sample_activity_title" /> <!-- Video Sample --> <activity android:name=".activity.VideoSampleActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/video_sample_activity_title" /> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> </application> </manifest> 

xml sample activity

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:draggable_panel="http://schemas.android.com/apk/res-auto" android:id="@+id/fl_container" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Movie Thumbnail --> <ImageView android:id="@+id/iv_thumbnail" android:layout_width="fill_parent" android:layout_height="fill_parent" style="@style/image_view"/> <!-- DraggablePanel --> <com.github.pedrovgs.DraggablePanel android:id="@+id/draggable_panel" android:layout_width="fill_parent" android:layout_height="fill_parent" draggable_panel:x_scale_factor="@dimen/x_scale_factor" draggable_panel:y_scale_factor="@dimen/y_scale_factor" draggable_panel:top_fragment_height="@dimen/top_fragment_height" draggable_panel:top_fragment_margin_right="@dimen/top_fragment_margin" draggable_panel:top_fragment_margin_bottom="@dimen/top_fragment_margin" draggable_panel:enable_horizontal_alpha_effect="false"/> </FrameLayout> 
+6
source share
5 answers

You expanded the ViewGroup instead of the View and yet you did not add the child to the DraggableView in xml or in the code. I do not see any addChild or any child code in the DraggableView . You used topFragment , bottomFragment , etc., and you used addFragmentToView() to transaction the fragment inside the ViewGroup . Bad idea!

I know this is complicated and time consuming. But you need to step back and think about the design of this view. I highly recommend you handle these topFragment etc. Like children with a DraggableView and do not have a FragmentManager inside this view and perform addTransaction .

As soon as you start adding child fragments to your ViewGroup , many complications will disappear. I say this from my past experience. onLayout() used to host Child Views inside the ViewGroup . After turning the device, it will call onLayout() again and arrange the child views as you wish. That would be very simple. The drag and drop operation will be made very simple as soon as you start conceptualization as follows.

If you think that Framgents , since the child in the ViewGroup is absurd, kindly look at the ViewPager code here . This uses fragments as input, but still treats them as children in the layout.

  • Try handling all things related to position in onLayout() .
  • Do not save location data in onSaveInstanceState() . Save only text or drawable .
  • It is always recommended not to override onCofigurationChanged() .

You may not be able to do it now, but in the long run, you may want to reorganize and do it this way.

Remember the true purpose of onLayout() :

Called from the layout when this view should assign size and position to each of his children. Derived classes with children must override this method and call layout for each of their children.

+1
source

If you are trying to delve into Laying out View , you will not need it for View Activity

  android:configChanges="keyboardHidden|orientation|screenSize" 

if this is specified after rotation, caring for android is less than re-creating your Activity , therefore re-drawing, -re-measurement, -re-positioning re-etc-etc.

therefore, if you start your application from the ImageView placement [10,100] after the boy rotates, your ImageView will be considered placed [10,100], sometimes it may even give you strange coordinates on the screen.

+2
source

Try using the onConfigrationChange() override method onConfigrationChange() this method will handle the rotation.

0
source

Assuming you create your own custom view. If so, you should use the standard mechanisms provided by the View class.

 @Override protected void onRestoreInstanceState(Parcelable state) { // Restore state } @Override protected Parcelable onSaveInstanceState() { // Save state } 
0
source

I think this is a good way.

 @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); return new YourParcelableObject(superState, yourValues); } @Override protected void onRestoreInstanceState(Parcelable state) { YourParcelableObject savedState = (SavedState) state; super.onRestoreInstanceState(savedState.getSuperState()); //restote other values from YourParcelableObject } 
0
source

All Articles