私の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"
設定変更への対応 [UPDATE:これはAPI 13以降廃止予定です; 推奨される代替案を参照してください ]
さらに別の方法として、向きやキーボードの表示設定の変更など、再起動を引き起こすイベントをアプリケーションにリッスンさせ、それらをActivity内で処理することもできます。
アクティビティのマニフェストノードにAndroid:configChanges
ノードを追加することから始めます。
<activity Android:name=".MyActivity"
Android:configChanges="orientation|keyboardHidden"
Android:label="@string/app_name">
または Android 3.2(APIレベル13)以降 :
<activity Android:name=".MyActivity"
Android:configChanges="keyboardHidden|orientation|screenSize"
Android:label="@string/app_name">
次にActivity内でonConfigurationChanged
メソッドをオーバーライドし、setContentView
を呼び出してGUIレイアウトを新しい方向に強制的に再作成します。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
Android 3.2以降用に更新します。
注意 :Android 3.2(API level 13)以降、 「画面サイズ」も変更されます デバイスが縦向きと横向きの間で切り替わるとき。したがって、(minSdkVersion属性およびtargetSdkVersion属性で宣言されているように)APIレベル13以上で開発するときに、向きの変更によるランタイムの再起動を防ぐには、
"screenSize"
値に加えて"orientation"
値を含める必要があります。つまり、Android:configChanges="orientation|screenSize"
を宣言する必要があります。ただし、アプリケーションがAPIレベル12以下をターゲットにしている場合、アクティビティは常にこの設定変更自体を処理します(Android 3.2以降のデバイスで実行している場合でも、この設定変更はアクティビティを再開しません)。
onCreate()
が完全に起動されないようにする代わりに、イベントに渡されているBundle
savedInstanceState
がnullかどうかを確認してみてください。
たとえば、Activity
が真に作成されたときに実行する必要があるロジックがあり、すべての向きが変わると実行されるわけではない場合、savedInstanceState
がnullの場合にのみonCreate()
でそのロジックを実行します。
そうでなければ、私はまだレイアウトを向きに合わせて適切に再描画したいです。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
これが最終的な答えであるかどうかわからないが、それは私のために働く。
私がしたこと...
マニフェストの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();
}
あなたが説明するのはデフォルトの振る舞いです。以下を追加して、これらのイベントを自分で検出して処理する必要があります。
Android:configChanges
あなたのマニフェスト、そしてあなたが処理したい変更に。だから、オリエンテーションのために、あなたは使うだろう:
Android:configChanges="orientation"
キーボードを開閉するには、次のようにします。
Android:configChanges="keyboardHidden"
両方を処理したい場合は、次のようにpipeコマンドでそれらを分離するだけです。
Android:configChanges="keyboardHidden|orientation"
これはあなたが呼び出すどんなActivityにおいてもonConfigurationChangedメソッドを引き起こすでしょう。メソッドをオーバーライドすると、新しい値を渡すことができます。
お役に立てれば。
私はちょうどこの伝承を発見しました:
向きを変えてもアクティビティを維持し、onConfigurationChanged
で処理するには、 ドキュメント および 上記のコードサンプル に示すように、マニフェストファイルでこれを実行します。
Android:configChanges="keyboardHidden|orientation"
これは常に機能するという追加の利点があります。
ボーナスは、keyboardHidden
を省略することは論理的に思えるかもしれませんが(少なくともAndroid 2.1のために)失敗を引き起こすということです:orientation
だけを指定すると、エミュレータはOnCreate
とときどきonConfigurationChanged
その他の場合にのみOnCreate
。
私はデバイス上の失敗を見たことがありませんが、私はエミュレータが他の人に失敗することについて聞いたことがあります。そのため、文書化する価値があります。
また、向きを変えてもデータを保持するAndroidプラットフォームの方法(onRetainNonConfigurationInstance()
およびgetLastNonConfigurationInstance()
)を使用することを検討することもできます。
これにより、サーバーのフェッチから取得した情報やonCreate
以降で計算されたその他の情報など、構成の変更にまたがってデータを保持することができます。同時に、現在の向きにxmlファイルを使用してActivity
を再レイアウトすることもできます。使用中で。
すべてのFragments
に切り替えて代わりに保持したいFragment
ごとにsetRetainInstance(true)
を使用することをお勧めします。
この方法は便利ですが、フラグメントを使用する場合は不完全です。
フラグメントは通常、設定変更時に再作成されます。これを実現したくない場合は、
フラグメントのコンストラクタ内のsetRetainInstance(true);
これにより、構成変更中にフラグメントが保持されます。
http://developer.Android.com/reference/Android/app/Fragment.html#setRetainInstance(boolean)
単に追加しました
Android:configChanges="keyboard|keyboardHidden|orientation"
マニフェストファイルで 私の活動に onConfigurationChanged
メソッドを追加しませんでした。
以下のコードを<activity>
のManifest.xml
タグ内に配置します。
Android:configChanges="screenLayout|screenSize|orientation"
AndroidのonCreate
を変更してもorientation
メソッドは呼び出されます。だから、この方法にすべての重い機能を移動することはあなたを助けることにはならないでしょう
それはとても簡単です。
<activity
Android:name=".Test"
Android:configChanges="orientation|screenSize"
Android:screenOrientation="landscape" >
</activity>
これは私のために働く:
注: オリエンテーションはあなたの必要条件によります
onConfigurationChanged is called when the screen rotates. (onCreate is no longer called when screen rotates due to manifest, see: Android:configChanges)
マニフェストのどの部分が「onCreate()
を呼び出さない」と言っていますか?
また、グーグルの文書はAndroid:configChanges
の使用を避けるように言っています(最後の手段としては除く)....しかしそれから彼らが提案する代わりの方法はすべてDOAndroid: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);
}
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();
}
}
これを行うにはいくつかの方法があります。
アクティビティの状態は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);
}
「Androidのやり方」ではありませんが、自分自身で向きの変更を処理し、変更された向きを考慮に入れるためにビュー内でウィジェットの位置を変更するだけで、非常に良い結果が得られました。ビューを保存して復元する必要がないため、これは他の方法よりも高速です。また、再配置されたウィジェットはまったく同じウィジェットで、移動やサイズ変更を行っただけなので、よりシームレスなエクスペリエンスをユーザーに提供します。モデルの状態だけでなくビューの状態もこの方法で保存できます。
RelativeLayout
は時々自分自身の向きを変えなければならないビューには良い選択です。それぞれの子ウィジェットに対して、それぞれに異なる相対配置規則を使用して、一連の縦型レイアウトパラメータと一連の美しいレイアウトパラメータを指定するだけです。次に、あなたのonConfigurationChanged()
メソッドで、適切なものをそれぞれの子のsetLayoutParams()
呼び出しに渡します。子コントロール自体が internal reorientedである必要がある場合は、その子のメソッドを呼び出して方向の変更を実行するだけです。その子も同様に、内部の向きを変更する必要がある その などの子コントロールのメソッドを呼び出します。
これを行うための方法は、onRestoreInstanceState
イベントとonSaveInstanceState
イベントを使用してBundle
に何かを保存することです(変数を保存する必要がない場合でも、Bundle
が空にならないように何かを入れるだけです)。次に、onCreate
メソッドで、Bundle
が空かどうかを確認し、そうでない場合は初期化を行い、そうでない場合はそれを行います。
画面が回転するたびに、開かれたアクティビティは終了し、onCreate()が再度呼び出されます。
1。画面を回転させたときにアクティビティの状態を保存することで、アクティビティのonCreate()が再度呼び出されたときに古いものをすべて復元できます。参照してください これ link
2。アクティビティの再開を防ぎたい場合は、manifest.xmlファイルに次の行を追加してください。
<activity Android:name=".Youractivity"
Android:configChanges="orientation|screenSize"/>
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");
}
オブジェクトを表示するために値を取得して設定するには、画面の回転を処理します。
注: /将来、誰かが私と同じ問題に直面した場合、この回答を投稿します。私にとっては、次の行では不十分でした。
Android:configChanges="orientation"
画面を回転させたときに、メソッド `onConfigurationChanged(Configuration newConfig)が呼び出されませんでした。
解決策: オリエンテーションに問題があったとしても、 "screenSize"を追加しなければならなかった。 AndroidManifest.xmlファイルで、これを追加します。
Android:configChanges="keyboardHidden|orientation|screenSize"
それからメソッドonConfigurationChanged(Configuration newConfig)
を実装します
manifest
のactivityセクションに、以下を追加してください。
Android:configChanges="keyboardHidden|orientation"
マニフェストに次の行を追加します。 Android:configChanges="orientation|screenSize"
人々はあなたが使うべきだと言っています
Android:configChanges="keyboardHidden|orientation"
しかし、Androidで回転を処理するための最善かつ最も専門的な方法は、Loaderクラスを使用することです。それは有名なクラスではありません(私はその理由がわかりません)が、AsyncTaskよりもずっと優れています。詳細については、UdacityのAndroidコースにあるAndroidチュートリアルを読むことができます。
もちろん、別の方法として、onSaveInstanceStateを使用して値またはビューを格納し、onRestoreInstanceStateを使用してそれらを読み取ることもできます。それは本当にあなた次第です。
以下のコードをAndroid Manifest
のActivity
に入れます。
Android:configChanges="orientation"
向きを変えても、これによってアクティビティが再開されることはありません。
異なる方向で異なるタスクを実行するには、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);
}
}
画面の向き(横または縦)をAndroidManifest.xml
で修正
Android:screenOrientation="portrait"
またはAndroid:screenOrientation="landscape"
このためあなたのonResume()
メソッドは呼び出されません。
試行錯誤の後、私はほとんどの状況で私のニーズに合った解決策を見つけました。これがコードです:
マニフェスト設定:
<?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);
}
}
github にあります。
Googleによって導入されたAndroidアーキテクチャの最も優れたコンポーネントの1つは、ViewModelであるあなたのすべての要件を満たします。
それはライフサイクルの方法でUI関連のデータを保存して管理するように設計されています。それに加えて、画面が回転してもデータは生き残ることができます。
class MyViewModel : ViewModel() {
これを参照してください: https://developer.Android.com/topic/libraries/architecture/viewmodel
あなたの活動の中でViewModelオブジェクトを使うことができます。
ViewModelオブジェクトは、設定の変更中に自動的に保持されるため、保持しているデータはすぐに次のアクティビティまたはフラグメントインスタンスで利用できるようになります。続きを読む:
https://developer.Android.com/topic/libraries/architecture/viewmodel
あなたはこのコードを使って画面の現在の向きに固定することができます...
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);
}