简体   繁体   English

片段在屏幕旋转时崩溃

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM