[英]fragment crashing on screen rotation
Using the FAB button the app alternates between two fragments.使用 FAB 按钮,应用程序在两个片段之间交替。 I am trying to make the current fragment persist when rotating the screen but everytime the screen rotates the app crashes.
我试图在旋转屏幕时使当前片段保持不变,但每次屏幕旋转时,应用程序都会崩溃。 I tried many solutions but none worked.
我尝试了很多解决方案,但没有一个奏效。 Why is it crashing?
为什么会崩溃? I am using NetBeans so I'm not sure who to post logcat.
我正在使用 NetBeans,所以我不确定向谁发布 logcat。
public class agendaFalante extends AppCompatActivity
{
/** Called when the activity is first created. */
private Toolbar toolbar;
private FloatingActionButton fab ;
private listViewFrag lvfrag;
private newEventFrag nef;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
toolbar = (Toolbar) findViewById (R.id.toolbar);
setSupportActionBar(toolbar);
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
if (savedInstanceState == null) {
lvfrag = new listViewFrag();
fragmentTransaction.replace(R.id.ll, lvfrag, "lvfrag");
fragmentTransaction.commit();
}else{
if(lvfrag!=null && lvfrag.isVisible()){
fragmentTransaction.replace(R.id.ll, lvfrag);
fragmentTransaction.commit();
}else if(nef!=null && nef.isVisible()){
fragmentTransaction.replace(R.id.ll, nef);
fragmentTransaction.commit();
}
}
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
fragmentTransaction = fragmentManager.beginTransaction();
if(nef!=null && nef.isVisible()){
lvfrag = (listViewFrag) getSupportFragmentManager().findFragmentByTag("lvfrag");
fragmentTransaction.replace(R.id.ll,lvfrag);
}else{
if(lvfrag.isVisible()){
nef = (newEventFrag) getSupportFragmentManager().findFragmentByTag("nef");
if(nef==null){
nef = new newEventFrag();
fragmentTransaction.replace(R.id.ll,nef,"nef");
}else{
fragmentTransaction.replace(R.id.ll,nef);
}
}
}
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
}
public boolean OnCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.menu_layout,menu);
return true;
}
}
main xml主文件
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/root"
tools:context=".agendaFalante">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ll"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="@drawable/ic_done"
app:layout_anchor="@id/ll"
app:backgroundTint="#CE93D8"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
Fragment 1 xml片段 1 xml
public class listViewFrag extends Fragment{
private ListView atividadesView;
private ArrayList<String> alist;
private ArrayAdapter<String> aDapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.listviewfrag, container, false);
atividadesView = (ListView) view.findViewById(R.id.listView);
alist = new ArrayList<String>();
alist.add("oi");
aDapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1,alist);
atividadesView.setAdapter(aDapter);
return view;
}
public void addText(String text){
alist.add(text);
aDapter.notifyDataSetChanged();
}
}
Fragment xml:片段xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Fragment 2:片段2:
public class newEventFrag extends Fragment{
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.neweventfrag, container, false);
return view;
}
}
Fragment xml片段xml
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
<TableRow
android:layout_height="0dp"
android:layout_weight="1">
<EditText
android:text="Insira o título"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
>
</EditText>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:id="@+id/record"
android:src="@drawable/ic_mic"
>
</Button>
</TableRow>
<TableRow
android:layout_height="0dp"
android:layout_weight="1">
<DatePicker
android:id="@+id/dpResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:datePickerMode="spinner"
android:calendarViewShown="false"
/>
</TableRow>
</TableLayout>
Fragments are not destroyed when the screen is rotated, onlt the activity.当屏幕旋转时,片段不会被破坏,在活动中。 However, the field lvfrag will not be the fragment you created prior to rotation until you find the fragment and assign it to the field.
但是,字段 lvfrag 不会是您在旋转之前创建的片段,直到您找到该片段并将其分配给该字段。 So you should firstly "find" the fragment when savedInstanceState is not null.
因此,当savedInstanceState 不为空时,您应该首先“找到”片段。 ---
---
if (savedInstanceState == null) {
lvfrag = new listViewFrag();
fragmentTransaction.replace(R.id.ll, lvfrag, "lvfrag");
fragmentTransaction.commit();
}else{
lvfrag = (listViewFrag)this.getSupportFragmentManager().findFragmentByTag("lvfrag");
if(lvfrag!=null)
.... you will need to reset any of the fragment's fields and then replace and commit again here } .... 您将需要重置任何片段的字段,然后在此处再次替换和提交 }
I show here for lvfrag only but you can do the code to include for nef as well.我在这里只显示 lvfrag,但您也可以执行包含 nef 的代码。 Your mainActivity needs to know which fragment was visible when the activity was destroyed.
您的 mainActivity 需要知道当活动被销毁时哪个片段是可见的。 You should overwrite an onSaveInstanceState method to send back which frag is visible in the bundle when the activity is destroyed on rotation and then capture that when replacing the fragment.
您应该覆盖 onSaveInstanceState 方法,以在 Activity 在旋转时销毁时发回 bundle 中可见的 Frag,然后在替换 Fragment 时捕获它。
When the screen is rotated, the savedInstanceState
parameter in onCreate()
will contain a Bundle
allowing you to return your Activity
to the state it was in. But you still need to treat it as a brand new Activity
and load up all the controls again:当屏幕旋转时,
onCreate()
的savedInstanceState
参数将包含一个Bundle
允许您将Activity
返回到它所处的状态。 但是您仍然需要将其视为一个全新的Activity
并再次加载所有控件:
if (savedInstanceState == null) {
lvfrag = new listViewFrag();
fragmentTransaction.replace(R.id.ll, lvfrag, "lvfrag");
fragmentTransaction.commit();
} else {
// even though savedInstanceState is not null
// lvfrag still needs to be created
if(lvfrag.isVisible()){
I've shown a portion of your code above - in it, you are assuming that lvfrag
is already created if savedInstanceState
is not null - this is wrong.我已经在上面展示了你的一部分代码——在其中,你假设
lvfrag
已经创建,如果savedInstanceState
不为空——这是错误的。
Every time the screen is rotated, Android recreates your Activity from new - you must recreate any fragments (and any other controls) and reinitialize all the fields in your Activity.每次屏幕旋转时,Android 都会从新重新创建您的 Activity - 您必须重新创建任何片段(和任何其他控件)并重新初始化您的 Activity 中的所有字段。 The most likely reason your App is crashing is because you are attempting to call
lvfrag.isVisible()
when lvfrag
hasn't been initialized (and so, is null).您的应用程序崩溃的最可能原因是您试图在
lvfrag
尚未初始化(因此为空)时调用lvfrag.isVisible()
)。
Write this line:: android:configChanges="orientation|screenSize|keyboardHidden"
on your AndroidManifest.xml
on which activity where you added fragment.在您添加片段的活动的
AndroidManifest.xml
上写下这一行:: android:configChanges="orientation|screenSize|keyboardHidden"
。
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:configChanges="orientation|screenSize|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.