活动重新启动关于转安卓
-
19-08-2019 - |
题
在我的机器应用程序,当我转动设备(滑出键盘)然后我的 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
在应用程序类是只有当整个应用是创建的,所以将活动重新启动定向或键盘视性的变化不会触发它。
这是好的做法获得的此类的实例作为一个单独和暴露的应用程序变你的初始化使用吸气,并制定者。
注:你只需要指定名称的新的应用程序类清单中将其注册和使用:
<application
android:name="com.you.yourapp.MyApplicationClass"
反应结构的变化 [更新:这已被否决,因为API13; 看到所建议的替代]
作为进一步可选择的,你可以有你听应用程序的事件会导致重启样取向和键盘视性的变化和处理它们在你的活动。
开始加入的 android:configChanges
节点活动的清单中节点
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
<activity android:name=".MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name">
然后内的活动复盖的 onConfigurationChanged
方法和呼叫 setContentView
为力图形用户界面布局将重新在新的方向。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.myLayout);
}
其他提示
更新安卓3.2和更高:
谨慎:开始与安卓3.2(API level13), "屏幕大小"也改变 当设备的交换机之间的纵向和横向。因此,如果您想要防止运行时重新启动由于改变方向时,发展中API13级或更高(如宣布的minSdkVersion和targetSdkVersion属性),必须包括的
"screenSize"
值在外"orientation"
值。也就是说,你必须声明android:configChanges="orientation|screenSize"
.然而,如果应用程序的目标API12级或较低,然后您的活动始终是处理这种配置变化本身(这一结构改变并不重新启动您的活动,即使在运行的机器3.2或更高的设备)。
而不是试图停止 onCreate()
从被解雇,也许试图检查 Bundle
savedInstanceState
正在通过进入的事件来看如果它是空或者没有。
例如,如果我有一些逻辑,应当 Activity
是真正的创建,不能在每一个方向改变,我只运行逻辑 onCreate()
只有如果 savedInstanceState
是空。
否则,我仍然想要重新布局,以正确的方向。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_list);
if(savedInstanceState == null){
setupCloudMessaging();
}
}
不知道,如果这是最终答案,但它为我工作。
我做了什么...
在清单,该活动的部分,增加:
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"
如果你要处理这两个你可以单独与他们的管命令,如:
android:configChanges="keyboardHidden|orientation"
这将触发onConfigurationChanged方法的任何活动的呼吁。如果复盖的方法可以通过在新的价值观。
希望这会有所帮助。
我只是发现了这个传说:
为保持的活动还活着通过一个方向变化,并处理它通过 onConfigurationChanged
, 该文件 和 代码样本上 建议这个清单中的文件:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name">
其具有额外的好处,它始终有效。
奖金的传说是省略了 keyboardHidden
可似乎是合乎逻辑的,但是它会导致失败在模拟器(用于安卓2.1至少):仅指定 orientation
将模拟器呼叫两个 OnCreate
和 onConfigurationChanged
有时,只有 OnCreate
其他时间。
我还没有看到的失败,在一个装置,但是我听到关于模拟器无法为其他人。所以这是值得记录。
你也可以考虑使用平台的方式保持数据方向的变化: onRetainNonConfigurationInstance()
和 getLastNonConfigurationInstance()
.
这可以让你坚持的数据结构的变化,例如信息,你可能已经得到了从服务器获取或别的东西,已经计算 onCreate
或者因为,同时也允许机器的重新布局 Activity
采用xml文件的定向现在在使用。
应当指出,这些方法现在已经过时(虽然仍然比更灵活的处理方向改变自己,因为大多数上述方案建议)的建议,即每个人都开关 Fragments
和而不是使用 setRetainInstance(true)
在每 Fragment
你想要保留。
该方法是有用的,但是不完整时使用的碎片。
碎片通常得到重新配置而改变。如果你不希望发生这种情况,使用
setRetainInstance(true);
在该段的构造(s)
这将导致碎片留在结构改变。
http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)
我只是简单地加入
android:configChanges="keyboard|keyboardHidden|orientation"
在清单和文件 没加 任何 onConfigurationChanged
方法在我的活动。
的 onCreate
方法仍然是所谓的即使你改变 orientation
。所以移动的所有重功能以这种方法是不会帮你的
这是很简单只要做到以下步骤:
<activity
android:name=".Test"
android:configChanges="orientation|screenSize"
android:screenOrientation="landscape" >
</activity>
这个工作对我来说:
注: 方向取决于你的requitement
把代码下面的内部 <activity>
标记 Manifest.xml
:
android:configChanges="screenLayout|screenSize|orientation"
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);
}
变化作出卓清单:
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
}
}
处理方向改变自己
另一个选择是到处理的方向变化。但这不被认为是良好做法。
添加到清单的文件。
android:configChanges="keyboardHidden|orientation"
对于安卓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
}
}
限制的旋转
你还可以把你的活动,纵向或横向模式,以避免旋转。
添加这一活动的标签在你的清单文件:
android:screenOrientation="portrait"
或实施这种编程方式在你的活动:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
我们发现要这样做是使用 onRestoreInstanceState
和 onSaveInstanceState
事件保存的东西的 Bundle
(甚至如果你不需要任何变量的保存,只是把东西在里面所以 Bundle
不是空的)。然后,上 onCreate
方法,检查看看 Bundle
是空的,如果是,那么做的初始化,如果不,那么做。
即使它不是"卓方式"我已经得到了很好的结果通过处理自己的方向变化和简单的重新定位的部件内,以采取改变方向考虑在内。这是速度比其他任何方法,因为你的意见不具有被保存和恢复。它还提供了一个更完美的体验要用户,因为respositioned件是完全相同的小部件,只是移动和/或调整。不仅型国家,但是也查状态时,可以保存在这种方式。
RelativeLayout
有时可以是一个良好选择一个观点,即已经重新调整本身的时间。你只是提供一套纵向布局,params和一组景观的布局params,与不同的相对位规则》的每一个,每个孩子部件。然后,在您的 onConfigurationChanged()
方法,通过合适的一对一 setLayoutParams()
呼吁每个孩子。如果有任何儿童控制本身的需要 内部 重新调整,你刚才叫一个方法上的儿童执行的重新定向。那个孩子同样的呼吁方法的任何 它的 孩子的控制,需要内部调整方向,等等。
每当屏幕上旋转,打开活动是完成和onCreate()称为。
1.你可以做一件事保存的状态的活动时,视是旋转所以,你可以恢复所有的旧东西的时候活动的onCreate()称为。请参阅 此 链接
2.如果您想要防止重新启动的活动刚刚发生以下行你的manifest.xml 文件。
<activity android:name=".Youractivity"
android:configChanges="orientation|screenSize"/>
注: 我后这个答案如果有人在未来面临同样的问题,因为我。我下面的线没有足够多的:
android:configChanges="orientation"
当我转动的屏幕,该方法`onConfigurationChanged(配置newConfig)不得被称为。
方案: 我也不得不添加"屏幕尺寸",即使如果问题不得不这样做的方向。所以在这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");
}
以检索并设置价值查的对象 它将处理屏幕上旋转
在活动部分 manifest
, 加上:
android:configChanges="keyboardHidden|orientation"
添加这一行清单: android:configChanges="orientation|screenSize"
人们都说你应该利用
android:configChanges="keyboardHidden|orientation"
但最好的和最专业的方式来处理转在安卓是使用的装载舱。这不是一个着名的类(我不知道为什么),但它是更好的方式比际关.更多信息,你可以读卓教程中发现的私的课程。
当然,作为另一种方式,可以储存的价值观或观点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>
重置:
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()
方法不叫。
最好的一个组成部分安卓architechure介绍通过谷歌会满足你所有的要求,即被视图模型.
就是设计用来存储和管理用户界面相关的数据,在生命周期的方式加,这将使数据生存作为屏幕上旋转
class MyViewModel : 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);
}