如何正确恢复旋转后的视图状态

问题描述:

我正在手动处理complex view的旋转,包括恢复propper的位置和大小。在这一刻,我正在尝试在onLayout(更好的想法是快速)中做到这一点。有时候它很好,但第一次轮换通常是错误的,或者没有孩子的观点。如何正确恢复旋转后的视图状态

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); 
    } 
    } 

在这段代码中,我尝试轮换,之后恢复初始上海技术交易所时onLayout被调用,然后将其移动到的地方,有观点旋转前(有4个状态,出creen的左,出屏幕右侧,屏幕顶端或右下角)。

编辑:

<?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

<?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> 
+0

为什么ü没有使用清单吧..?你可以忽略旋转,如果你没有做一些特殊的旋转... –

+0

@sourabhbans你是'android:configChanges =“locale | keyboardHidden | orientation | screenSize” '?我使用它,这就是为什么我问关于手动处理的观点(而不是活动) – Yarh

+0

好吧..我认为这是错误的.. –

您纷纷伸出ViewGroup而不是View,但还没有添加任何childDraggableView在XML或代码。我在DraggableView中看不到任何addChild或任何与儿童有关的代码。您已使用topFragment,bottomFragment等,并且您使用addFragmentToView()ViewGroup内部进行碎片交易。馊主意!

我知道这很难,很费时间。但是你需要退后一步,思考这个视图的设计。我强烈建议你把这些topFragment等作为子女加入DraggableView,并且在这个视图里面没有FragmentManager并执行addTransaction

一旦您开始将片段作为孩子添加到您的ViewGroup,很多并发症就会消失。我从过去的经历中这样说。 onLayout()用于在ViewGroup内安排Child Views。一旦你旋转设备,onLayout()将再次被调用,并会按你的意愿安排子视图。这将是非常简单的。一旦你像这样开始概念化,拖动操作将变得非常简单。

如果您认为作为ViewGroup中的孩子是荒谬的,请参阅ViewPager代码here。这使用片段作为输入,但仍将它们视为布局中的子项。

  1. 尽量处理所有与onLayout()本身相关的东西。
  2. 请勿在onSaveInstanceState()中保存位置数据。在此仅保存textdrawable数据。
  3. 总是建议不要覆盖onCofigurationChanged()

您现在可能无法做到这一点,但从长远来看,您可能需要重构并按照这种方式进行。

记住的onLayout()的真正目的:

从布局时调用这个观点应该在大小和位置分配给每个 其子。带孩子的衍生课程应覆盖此方法,并调用其每个孩子的布局。

如果你想深入的布放你View是你对于不需要这些你ViewActivity

android:configChanges="keyboardHidden|orientation|screenSize" 

如果在旋转后设置了这个,android care更少的是否重新创建你的Activity,从而重新绘制,重新测量,重新定位等等。

所以如果你在的位置[10 100]开始你的应用程序,你的ImageView有时候会被假定放置[10 100],有时它甚至会给你离奇的屏外坐标。

+0

sithout它会在视频流中暂停 – Yarh

尝试使用onConfigrationChange()重写方法 此方法将处理旋转。

假设您正在创建自己的自定义视图。如果是这样,你应该使用View类提供的标准机制。

@Override 
protected void onRestoreInstanceState(Parcelable state) { 
    // Restore state 
} 

@Override 
protected Parcelable onSaveInstanceState() { 
    // Save state 
} 

我想这是一个很好的方式

@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 
    }