Reputation: 71
Using the FAB button the app alternates between two fragments. 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.
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
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:
<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:
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
<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>
Upvotes: 0
Views: 3405
Reputation: 1747
Write this line:: android:configChanges="orientation|screenSize|keyboardHidden"
on your AndroidManifest.xml
on which activity where you added fragment.
<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>
Upvotes: 4
Reputation: 138
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. So you should firstly "find" the fragment when savedInstanceState is not null. ---
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. Your mainActivity needs to know which fragment was visible when the activity was destroyed. 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.
Upvotes: 2
Reputation: 10316
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:
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.
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. 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).
Upvotes: 1