私のAndroidアプリケーションでは、デバイスを回転させる(キーボードを引き出す)とActivity
再起動します(onCreate
と呼ばれています。さて、これはおそらくそれが想定されている方法ですが、私は初期設定の多くをやっていますonCreate
メソッドなので、次のどちらかが必要です。
onCreate
再度呼び出されることはなく、レイアウトが調整されるだけです。onCreate
と呼ばれていません。
アプリケーションクラスの使い方
初期化で何をしているかに応じて、拡張する新しいクラスを作成することを検討できます。Application
初期化コードをオーバーライドするonCreate
そのクラス内のメソッド。
public class MyApplicationClass extends Application {
@Override
public void onCreate() {
super.onCreate();
// TODO Put your application initialization code here.
}
}
のonCreate
アプリケーションクラスでは、アプリケーション全体が作成されたときにのみ呼び出されるため、Activityが向きを変えて再起動したり、キーボードの表示設定が変更されたりすることはありません。
このクラスのインスタンスをシングルトンとして公開し、初期化しているアプリケーション変数をゲッターとセッターを使用して公開することをお勧めします。
注:登録して使用するには、マニフェストに新しいApplicationクラスの名前を指定する必要があります。
<application
android:name="com.you.yourapp.MyApplicationClass"
構成変更への対応 [更新:これはAPI 13以降廃止予定です。推奨代替案を参照してください]
さらに別の方法として、向きやキーボードの表示設定の変更など、再起動の原因となるイベントをアプリケーションにリッスンさせ、それらをActivity内で処理することもできます。
を追加することから始めますandroid:configChanges
アクティビティのマニフェストノードへのノード
android:configChanges="keyboardHidden|orientation"
またはのためにAndroid 3.2(APIレベル13)以降:
android:configChanges="keyboardHidden|orientation|screenSize"
次に、アクティビティ内でonConfigurationChanged
メソッドと呼び出しsetContentView
GUIレイアウトを新しい向きで強制的に再作成します。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
android:configChanges
)回避し、最後の手段としてのみ使用する必要があります。設定変更による再起動を適切に処理する方法については、ランタイム変更の処理を参照してください。代わりに、ローテーションイベント間でデータを永続化するには、onSaveInstanceState Bundle
;または@ Jon-Oとして推薦、onRetainNonConfigurationInstance
。 - JeffroonRetainNonConfigurationChanges
よりフォールトトレラントで簡単です。 - Bananeweizen
Android 3.2以降用に更新します。
あぶない:Android 3.2(APIレベル13)以降「画面サイズ」も変わりますデバイスが縦向きと横向きの間で切り替わるとき。したがって、(minSdkVersion属性およびtargetSdkVersion属性で宣言されているように)APIレベル13以上で開発する際の向きの変更によるランタイムの再起動を防ぐには、次のものを含める必要があります。
"screenSize"
に加えて値"orientation"
値。つまり、宣言する必要がありますandroid:configChanges="orientation|screenSize"
。ただし、アプリケーションがAPIレベル12以下をターゲットにしている場合、アクティビティは常にこの設定変更自体を処理します(Android 3.2以降のデバイスで実行している場合でも、この設定変更はアクティビティを再開しません)。
Fragments
そしてsetRetainInstance
代わりに。 - Simon ForsbergscreenSize
アンドロイド3.2以降では、それが私の問題を解決しました、ありがとうございます! - fantouch
停止しようとする代わりにonCreate()
完全に解雇されることから、多分Bundle
savedInstanceState
nullかどうかを確認するためにイベントに渡されます。
たとえば、次のような場合に実行する必要があるロジックがあるとします。Activity
すべての向きの変更ではなく、私は本当にその論理を実行します。onCreate()
の場合のみsavedInstanceState
無効です。
それ以外の場合は、レイアウトを向きに合わせて正しく再描画する必要があります。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
これが最終的な答えであるかどうかわからないが、それは私のために働く。
Intent serverintent = new Intent(MainActivity.this, MessageListener.class);
そしてstartService(serverintent);
を作成するserverSocket = new ServerSocket(0xcff2);
そしてSocket client = serverSocket.accept();
とともにBufferedReader(new InputStreamReader(client.getInputStream()));
そして私のアンドロイドを回転させ、クライアント/サーバー接続をアクティブに保ちながらGUIを回転させることができます。マニュアルによると、savedInstanceStateは最後のアクティビティがシャットダウンされたときに初期化されます。 - Fred F
私がしたこと...
マニフェストのactivityセクションに、次のように追加されています。
android:configChanges="keyboardHidden|orientation"
アクティビティのコードに、次のものを実装した。
//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
//get views from ID's
this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);
//etc... hook up click listeners, whatever you need from the Views
}
//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InitializeUI();
}
//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
InitializeUI();
}
Fragments
そしてsetRetainInstance
代わりに。 - Simon Forsberg
あなたが説明するのは、デフォルトの動作です。以下を追加して、これらのイベントを自分で検出して処理する必要があります。
android:configChanges
あなたのマニフェスト、そしてあなたが処理したい変更に。オリエンテーションのために、あなたは使うでしょう:
android:configChanges="orientation"
キーボードを開閉するには、次のようにします。
android:configChanges="keyboardHidden"
両方を処理したい場合は、次のようにpipeコマンドでそれらを分離するだけです。
android:configChanges="keyboardHidden|orientation"
これはあなたが呼び出すどんなActivityにおいてもonConfigurationChangedメソッドを引き起こすでしょう。メソッドをオーバーライドすると、新しい値を渡すことができます。
お役に立てれば。
android:configChanges="orientation"
少なくともAndroid 2.1では、エミュレータのバグのみを引き起こすようです。 - Liudvikas BukysFragments
そしてsetRetainInstance
代わりに。 - Simon Forsberg
私はちょうどこの伝承を発見しました:
方向を変えても活動を維持し、それを介して処理するためonConfigurationChanged
、ドキュメントそして上記のコードサンプルこれをマニフェストファイルで提案します。
android:configChanges="keyboardHidden|orientation"
これは常に機能するという追加の利点があります。
ボーナスロアは、省略することですkeyboardHidden
論理的に思えるかもしれませんが、エミュレータでエラーが発生します(少なくともAndroid 2.1の場合)。orientation
エミュレータが両方を呼び出すようにしますOnCreate
そしてonConfigurationChanged
時々、そしてただOnCreate
別の時に。
私はデバイス上の失敗を見たことがありませんが、私はエミュレータが他の人に失敗することについて聞いたことがあります。そのため、記録する価値があります。
Fragments
そしてsetRetainInstance
代わりに。 - Simon Forsberg
また、向きを変えてもデータを保持するAndroidプラットフォームの方法を使用することも検討できます。onRetainNonConfigurationInstance()
そしてgetLastNonConfigurationInstance()
。
これにより、サーバーのフェッチから取得した情報やその他の方法で計算されたものなど、構成の変更をまたがってデータを保持できます。onCreate
またはそれ以来、Androidもあなたの再レイアウトを許可しながらActivity
現在使用中の向きにxmlファイルを使用する。
これらのメソッドは現在推奨されていないので、これらのメソッドは推奨されなくなりました(上記の解決策の大部分が示すように向きを処理するよりももっと柔軟です)。Fragments
そして代わりに使うsetRetainInstance(true)
それぞれのFragment
保持したい
この方法は便利ですが、フラグメントを使用する場合は不完全です。
通常、フラグメントは設定変更時に再作成されます。これが起こらないようにするには、
setRetainInstance(true);
フラグメントのコンストラクタ内
これにより、構成変更中にフラグメントが保持されます。
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
setRetainInstance()
メソッド@ Abdoが述べた。 - brianmearns
単に追加しました
android:configChanges="keyboard|keyboardHidden|orientation"
マニフェストファイルに追加しなかったどれかonConfigurationChanged
私の活動の方法。
<application ...android:configChanges="keyboard|keyboardHidden|orientation">
そしてそれは働いています。 build.gradleでの私の設定:minSdkVersion 15, compileSdkVersion 23, buildToolsVersion "23.0.2"
- Junior M
onConfigurationChanged is called when the screen rotates. (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
マニフェストのどの部分がそれを伝えますonCreate()
「?
また、
グーグルの文書は使用を避けるように言うandroid:configChanges
(最後の手段としてを除く)....しかし、その後、彼らはすべてを示唆している代替方法行うつかいますandroid:configChanges
。
エミュレータが常に呼び出すのは私の経験でしたonCreate()
回転時に
しかし、私が同じコードを実行している1〜2台のデバイスは違います。
(なぜ違いがあるのかわからない)
この行をマニフェストに追加してください -
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"
そして、このスニペットのアクティビティは次のとおりです。 -
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
のonCreate
メソッドを変更してもメソッドは呼び出されますorientation
アンドロイドだから、この方法にすべての重い機能を移動することはあなたを助けることにはならないでしょう
以下のコードをあなたの中に入れてください<activity>
日中Manifest.xml
:
android:configChanges="screenLayout|screenSize|orientation"
Androidマニフェストに加えられる変更は次のとおりです。
android:configChanges="keyboardHidden|orientation"
活動の中で行われる追加事項は以下のとおりです。
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();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
それはとても簡単です。
<activity
android:name=".Test"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
</activity>
これは私のために働く:
注意:オリエンテーションはあなたの必要条件によります
これを行うにはいくつかの方法があります。
アクティビティの状態は次の場所に保存できます。onSaveInstanceState
。
@Override
public void onSaveInstanceState(Bundle outState) {
/*Save your data to be restored here
Example : outState.putLong("time_state", time); , time is a long variable*/
super.onSaveInstanceState(outState);
}
それからbundle
状態を復元します。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!= null){
/*When rotation occurs
Example : time = savedInstanceState.getLong("time_state", 0); */
} else {
//When onCreate is called for the first time
}
}
もう1つの選択肢は、自分で向きの変更を処理することです。しかし、これは良い習慣とは考えられていません。
これをマニフェストファイルに追加してください。
android:configChanges="keyboardHidden|orientation"
Android 3.2以降の場合
android:configChanges="keyboardHidden|orientation|screenSize"
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
//Handle rotation from landscape to portarit mode here
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
//Handle rotation from portrait to landscape mode here
}
}
回転を避けるために、あなたの活動を縦モードまたは横モードに制限することもできます。
これをマニフェストファイルのactivityタグに追加します。
android:screenOrientation="portrait"
あるいはあなたの活動の中でプログラム的にこれを実装する:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
私はこれを行うことがわかった方法を使用していますonRestoreInstanceState
そしてそのonSaveInstanceState
に何かを保存するイベントBundle
(変数を保存する必要がなくても、そこに何かを入れてください。Bundle
空ではありません)。それから、onCreate
方法は、Bundle
空の場合は初期化し、そうでない場合は初期化します。
「Androidのやり方」ではありませんが、自分自身で向きの変更を処理し、変更された向きを考慮に入れるためにビュー内でウィジェットの位置を変更するだけで、非常に良い結果が得られました。ビューを保存して復元する必要がないため、これは他の方法よりも高速です。また、再配置されたウィジェットはまったく同じウィジェットで、移動やサイズ変更を行っただけなので、よりシームレスなエクスペリエンスをユーザーに提供します。このようにして、モデルの状態だけでなくビューの状態も保存できます。
RelativeLayout
時々自分自身の向きを変えなければならないビューには、時には良い選択になる可能性があります。それぞれの子ウィジェットに対して、それぞれに異なる相対配置規則を使用して、一連の縦型レイアウトパラメータと一連の美しいレイアウトパラメータを指定するだけです。その後、あなたの中にonConfigurationChanged()
方法では、適切なものをsetLayoutParams()
子供たち一人ひとりに電話してください。任意の子コントロール自体がする必要がある場合内的に向きを変えると、その子のメソッドを呼び出して向きを変えるだけです。その子も同様にのいずれかのメソッドを呼び出しますその内部の向きの変更などを必要とする子コントロール。
注意:将来、誰かが私と同じ問題に直面した場合、私はこの答えを投稿します。私にとっては、次の行では不十分でした。
android:configChanges="orientation"
画面を回転させたときに、メソッド `onConfigurationChanged(Configuration newConfig)が呼び出されませんでした。
溶液:問題が方向性に関係していたとしても、私はまた "screenSize"を追加しなければなりませんでした。 AndroidManifest.xmlファイルで、これを追加します。
android:configChanges="keyboardHidden|orientation|screenSize"
それからメソッドを実装するonConfigurationChanged(Configuration newConfig)
onSavedInstanceStateメソッドを使用して、すべての値をそのパラメータに格納する必要があります。
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outPersistentState.putBoolean("key",value);
}
そして使う
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
savedInstanceState.getBoolean("key");
}
オブジェクトを表示して値を取得して設定する 画面の回転を処理します
画面が回転するたびに、開かれたアクティビティは終了し、onCreate()が再度呼び出されます。
1。画面を回転させたときにアクティビティの状態を保存することで、アクティビティのonCreate()が再度呼び出されたときに古いものをすべて復元できます。 参照してくださいこのリンク
2。アクティビティの再開を防ぎたい場合は、manifest.xmlファイルに次の行を追加してください。
<activity android:name=".Youractivity"
android:configChanges="orientation|screenSize"/>
の活動セクションでmanifest
、追加:
android:configChanges="keyboardHidden|orientation"
この行をマニフェストに追加します。
android:configChanges="orientation|screenSize"
人々はあなたが使うべきだと言っています
android:configChanges="keyboardHidden|orientation"
しかし、Androidでローテーションを処理するための最善かつ最も専門的な方法は、Loaderクラスを使用することです。それは有名なクラスではありません(私はその理由がわかりません)が、AsyncTaskよりもずっと優れています。詳細については、UdacityのAndroidコースにあるAndroidチュートリアルを読むことができます。
もちろん、別の方法として、onSaveInstanceStateを使用して値またはビューを格納し、onRestoreInstanceStateを使用してそれらを読み取ることもできます。それは本当にあなた次第です。
試行錯誤の末、私はほとんどの状況で私のニーズに合った解決策を見つけました。これがコードです:
マニフェスト設定:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pepperonas.myapplication">
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity:
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Fragment mFragment;
private int mSelected = -1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate " + "");
// null check not realy needed - but just in case...
if (savedInstanceState == null) {
initUi();
// get an instance of FragmentTransaction from your Activity
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
/*IMPORTANT: Do the INITIAL(!) transaction only once!
* If we call this everytime the layout changes orientation,
* we will end with a messy, half-working UI.
* */
mFragment = FragmentOne.newInstance(mSelected = 0);
fragmentTransaction.add(R.id.frame, mFragment);
fragmentTransaction.commit();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged " +
(newConfig.orientation
== Configuration.ORIENTATION_LANDSCAPE
? "landscape" : "portrait"));
initUi();
Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
makeFragmentTransaction(mSelected);
}
/**
* Called from {@link #onCreate} and {@link #onConfigurationChanged}
*/
private void initUi() {
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate instanceState == null / reinitializing..." + "");
Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
btnFragmentOne.setOnClickListener(this);
btnFragmentTwo.setOnClickListener(this);
}
/**
* Not invoked (just for testing)...
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState " + "YOU WON'T SEE ME!!!");
}
/**
* Not invoked (just for testing)...
*/
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "onSaveInstanceState " + "YOU WON'T SEE ME, AS WELL!!!");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume " + "");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause " + "");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy " + "");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_fragment_one:
Log.d(TAG, "onClick btn_fragment_one " + "");
makeFragmentTransaction(0);
break;
case R.id.btn_fragment_two:
Log.d(TAG, "onClick btn_fragment_two " + "");
makeFragmentTransaction(1);
break;
default:
Log.d(TAG, "onClick null - wtf?!" + "");
}
}
/**
* We replace the current Fragment with the selected one.
* Note: It's called from {@link #onConfigurationChanged} as well.
*/
private void makeFragmentTransaction(int selection) {
switch (selection) {
case 0:
mFragment = FragmentOne.newInstance(mSelected = 0);
break;
case 1:
mFragment = FragmentTwo.newInstance(mSelected = 1);
break;
}
// Create new transaction
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.frame, mFragment);
/*This would add the Fragment to the backstack...
* But right now we comment it out.*/
// transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
そしてフラグメントのサンプル:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* @author Martin Pfeffer (pepperonas)
*/
public class FragmentOne extends Fragment {
private static final String TAG = "FragmentOne";
public static Fragment newInstance(int i) {
Fragment fragment = new FragmentOne();
Bundle args = new Bundle();
args.putInt("the_id", i);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView " + "");
return inflater.inflate(R.layout.fragment_one, container, false);
}
}
で見つけることができますギトブ。
つかいますorientation
異なる方向で異なるタスクを実行するためのリスナー。
@Override
public void onConfigurationChanged(Configuration myConfig)
{
super.onConfigurationChanged(myConfig);
int orient = getResources().getConfiguration().orientation;
switch(orient)
{
case Configuration.ORIENTATION_LANDSCAPE:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case Configuration.ORIENTATION_PORTRAIT:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
default:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
この下のコードをあなたのActivity
にAndroid Manifest
。
android:configChanges="orientation"
向きを変えても、これでアクティビティが再開されることはありません。
で画面の向き(横または縦)を修正します。AndroidManifest.xml
android:screenOrientation="portrait"
またはandroid:screenOrientation="landscape"
このためあなたのonResume()
メソッドは呼び出されません。
あなたはこのコードを使って画面の現在の向きに固定することができます...
int currentOrientation =context.getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
((Activity) context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
((Activity) context). setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
あなたの活動の中でViewModelオブジェクトを使うことができます。
ViewModelオブジェクトは、構成の変更中に自動的に保持されるため、保持しているデータはすぐに次のアクティビティまたはフラグメントインスタンスで利用できるようになります。 続きを読む:
https://developer.android.com/topic/libraries/architecture/viewmodel