更改方向时片段重新启动

时间:2015-06-09 23:47:36

标签: java android android-fragments orientation screen-orientation

我的Android应用程序中有这个层次结构

Activity包含FragmentGame片段,其中包含FragmentTypeOfGame;

活动>> FragmentGame >> FragmentTypeOfGame

在FragmentGame里面,我有一个计时器和另一个标签,所以,当我改变屏幕方向时,我的游戏似乎重新启动,但我可以检查计时器是否继续运行(因为它是另一个线程,我猜)。

所以我的问题是,如何在不重新启动的情况下保持所有屏幕运行。

我已经看似这些链接,但我无法找到解决方法吗?

Why not use always android:configChanges="keyboardHidden|orientation"?

Forcing Android to not redraw activity on orientation change

这是我的清单:

    

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    >
    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="orientation"
        >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name="com.facebook.FacebookActivity"
        android:configChanges=
            "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"
        android:label="@string/app_name" />

    <provider android:authorities="com.facebook.app.FacebookContentProviderXXXXXXXXX"
        android:name="com.facebook.FacebookContentProvider"
        android:exported="true" />
</application>

这是我的GameFragment OnCreateView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    //Default components start
    defaultComponentsStarting(inflater, container);

    FourBlocksGameStyle f = new FourBlocksGameStyle();
    frgManager.beginTransaction().replace(R.id.rl_root, f, "4blocks").addToBackStack(null).commit();

    if (savedInstanceState != null) {
        // Restore last state
        actualGameTime = savedInstanceState.getDouble("actualGameTime");
    }

    handler = new Handler(Looper.getMainLooper());
    mainRunnable = new Runnable() {
        @Override
        public void run() {
            // Do something and reschedule ourself

            if(GAMETIME <= actualGameTime){
                cancelTimer();

                setLabel(txtTimer, 0, GAMETIME / 1000);
                int countSum = Integer.parseInt(txtHits.getText().toString());

                //Devolve pra main cuidar da finalização
                Intent i = new Intent(ctx, MainActivity.class);
                i.putExtra("CountSum", countSum);
                startActivity(i);
            }
            else {
                actualGameTime += GAMEDELAY;
                double floatingTime = actualGameTime / 1000;

                setLabel(txtTimer, 0, floatingTime);
                handler.postDelayed(this, GAMEDELAY);
            }
        }
    };
    return view;
}

在这里我的MainActivity onCreate?

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FacebookSdk.sdkInitialize(getApplicationContext());
    setContentView(R.layout.activity_main);

    this.setVolumeControlStream(AudioManager.STREAM_MUSIC);

    final SharedPreferences prefs = getSharedPreferences("hitColor", MODE_PRIVATE);
    int startHighscore = prefs.getInt("highScore", 0);

    gameOver = new GameOverFragment();
    highScoreGameOver = new HighScoreFragment();
    game = new GameFragment();

    Intent i = getIntent();
    int countSum = i.getIntExtra("CountSum", -1);

    if(countSum == -1) {
        //Log.d("GSS", "Primeira entrada");
        if(savedInstanceState == null) {
            Log.d("GSS", "savedInstace null");
            getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.layout_root_view, game)
                    .addToBackStack(null)
                    .commit();
        }
    }
    else {
        Log.d("GSS", "COUNT: " + String.valueOf(countSum));
        Log.d("GSS", "HIGH: " + String.valueOf(startHighscore));

        finishGame(countSum, startHighscore, prefs);
    }
}

2 个答案:

答案 0 :(得分:1)

使用活动configChanges的当前配置,您的片段将在您更改方向时重新创建UI。由于它将是全新的布局,因此很有意义。

但你的片段不会再次调用onCreate。它会在调用onCreateViewonPause后从onStop开始,以销毁片段的用户界面。

因此,当Orientation更改时,意味着当片段进入onPause时,您应该将您的UI数据保存在Bundle对象中(在片段内将其定义为全局变量){{1 }}。由于片段将从onPause开始,因此您可以在onCreateView方法中对版面进行充气后恢复UI数据。

onCreateView将为null。当配置发生变化时,它不会存储您的数据,因此您不能依赖它。

答案 1 :(得分:0)

以下是如何手动从Fragment获取数据的示例..

public class RetainedFragment extends Fragment {

// data object we want to retain
private MyDataObject data;

// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // retain this fragment
    setRetainInstance(true);
}

public void setData(MyDataObject data) {
    this.data = data;
}

public MyDataObject getData() {
    return data;
}
 public Bitmap getBitmap() { return bitmap; }
 public void setBitmap(Bitmap bmp) { bitmap = bmp; }
}

然后在您的MainActivity中,您可以在片段重新启动时获取数据,

public class MyActivity extends Activity {

private RetainedFragment dataFragment;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // find the retained fragment on activity restarts
    FragmentManager fm = getFragmentManager();
    dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

    // create the fragment and data the first time
    if (dataFragment == null) {
        // add the fragment
        dataFragment = new DataFragment();
        fm.beginTransaction().add(dataFragment, “data”).commit();
        // load the data from the web
        dataFragment.setData(loadMyData());
    }

    // the data is available in dataFragment.getData()
    ...
}

@Override
public void onDestroy() {
    super.onDestroy();
    // store the data in the fragment
    dataFragment.setData(collectMyLoadedData());
}
}

但是,您可以恢复对象,但是您永远不应该传递与Activity绑定的对象,例如Drawable,Adapter,View或与Context关联的任何其他对象。希望这会有所帮助..

此外,您可以使用以下方法设置恢复,

@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();
     // code for landscape configurtion // load the previous data.
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
    Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    // code for landscape configurtion // load the previous data.
}
}