I have looked at many of the similar question But still I'm unable to replace container layout (FrameLayout) of My Main Activity from a fragment that is visible in that container.
Here is what I'm trying to do I have a main activity with navigation drawer and On navigation drawer item click I'm changing fragment accordingly, I'm successful till this. These fragments are Login, Register, Categories, Contact Us etc. I'm changing/replacing fragments with FragmentManager, FragmentTransaction its method replace. Check the code below
public void changeFragment(int position) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragment fragment = new Fragment();
BlankFragment blankFragment = new BlankFragment();
switch (position) {
case 0:
fragment = new FragMain();
break;
case 1:
fragment = new FragPrivacyPolicy();
break;
case 2:
fragment = new SettingsFragment();
break;
case 101:
fragment = new FragLogin();
break;
case 102:
fragment = new FragRegister();
break;
case 103:
fragment = new FragEditAccount();
break;
case 104:
fragment = new FragOrderHistory();
break;
case 105:
fragment = new FragForgotPass();
break;
case 106:
fragment = new FragOrderDetail();
break;
case 108:
fragment = new FragAboutUs();
break;
case 109:
fragment = new FragContactUs();
break;
case 110:
fragment = new FragMain();
break;
}
transaction.replace(R.id.flFragments, fragment);
transaction.commit();
}
Which is working fine as all my fragments extends Fragment. The problem comes when I try to call this method in one of the fragments visible in this mainActivity's container. Suppose I have a textView in FragLogin saying "Don't have an account Register" so on click this textView I have to open FragRegister in the same container of mainActivity. When I do it like this in my FragLogin App Crashes pointing to the transaction.commit();
MainActivity activity = new MainActivity();
activity.changeFragment(102);
And when I try like this
FragRegister fragRegister = new FragRegister();
// Fragment fragRegister = new FragRegister();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.Id.flFragments, fragRegister).commit();
It does not recognize the R.Id.flFragments as its inside the mainActivity not in FragLogin.
So how can I replace that FragRegister in mainActivity's container from FragLogin?
Dont use getChildFragmentManager() because it belongs to the fragment manager and the container that is holding current fragment is the activity container.Instead use getSupportFragmentManager().
Also see this stament
MainActivity activity = new MainActivity();
activity.changeFragment(102);
You are creating a new object of mainactivity which is already created.You have to call the activity method from fragments using getActivity().Call the changeFragment method like this.
((MainActivity)getActivity()).changeFragment(102);
Related
I'm having the problem that when I trying to switch between the menu item. The menu item will not pointing to the correct icon.
here is the flow when i found this problem
starting at the (Home)fragment,then press on the second menu item (Features )
case R.id.nav_home:
//home fragment transaction
actionBar.setTitle("Home");
HomeFragment fragment1 = new HomeFragment();
FragmentTransaction fragmentTransaction1 = getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.content, fragment1, "");
fragmentTransaction1.commit();
break;
second menu item (features) will go to features activity
case R.id.nav_features:
//features fragment transaction
startActivity(new Intent(DashboardActivity.this, FeaturesActivity.class));
break;
close features activity and back to (Home) fragment
onBackPressed();
bottom navigation still pointing to second menu item (features).
how can I make the system point to the correct menu item ?
You should return a boolean for this method:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
//...
}
do this :
case R.id.nav_home:
//home fragment transaction
actionBar.setTitle("Home");
HomeFragment fragment1 = new HomeFragment();
FragmentTransaction fragmentTransaction1 =
getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.content, fragment1, "");
fragmentTransaction1.commit();
return true; // add this line and remove break;
if you don't want to select icon after click, you can return false.
I have this code:
public void replaceFragment(int i) {
fragmentTransaction = getSupportFragmentManager().beginTransaction();
TextView headerName = (TextView) findViewById(R.id.HeaderName);
switch (i) {
// Login Fragment
case 0:
headerName.setText("Member Login");
fragmentTransaction.replace(R.id.main_container, new
LoginActivity());
break;
// Register Fragment
case 1:
headerName.setText("Sign Up");
fragmentTransaction.replace(R.id.main_container, new RegisterFragment());
break;
}
}
My problem is on the case 0, I put the other cases as examples. My login is not a Fragment, but an Activity. So how do I manage to keep it here? With an Intent?
Instead of
fragmentTransaction.replace(R.id.main_container, new
LoginActivity());
Use
Intent inntent = new Intent(this,LoginActivity.class);
startActivity(inntent);
Just build a new intent in case 0 and start your activity instead of trying to replace a fragment with activity which is impossible unless you turn your activity to fragment
If you need both you can turn your activity to fragment and then build an empty activity to contain it when necessary
So here's the code:
private void selectItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new DoctorFragment();
break;
case 2:
fragment = new HospitalFragment();
break;
case 3:
fragment = new SpecialClinicFragment();
break;
case 4:
fragment = new PharmacyFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
//the parameter "fragment" in this line of code gives an error message.
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
getActionBar().setTitle(mNavigationDrawerItemTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
Log.e("MainActivity", "Error in creating fragment");
}
It seems like I haven't properly initialised fragment instance.
The error message was "Wrong 2nd argument type" but I'm pretty sure I put in the right parameter.
Problem is not with the argument.You have used Fragment from
android.support.v4 library but you are making transaction on android.app.fragment.
Solution:
import android.app.fragment instead of android.support.v4.fragment
Because you cannot mix up with support.v4 library and android.app.*
I have a FragmentActivity in which I am implementing navigation drawer, like if I select any item from drawer list then its fragment is opened in activity. Now my XML layout code to display fragments looks like this
<!-- Framelayout to display Fragments -->
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
This means I have not any fragment tags in xml file but I open fragments dynamically from activity as below
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
if(session.isLoggedIn())
{
fragment = new SlidingFragment();
}
else
{
fragment = new LoginFragment();
}
break;
case 1:
fragment = new HomeFragment();
break;
case 2:
fragment = new LoginFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();}
Now I want to use putFragment to keep fragment state alive for one fragment when orientation changed.so, I coded below on my FragmentActivity's onSaveInstanceState method
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Log.v(TAG, "In frag's on save instance state ");
FragmentManager manager = getSupportFragmentManager();
fr = new RandomFragment();
manager.putFragment(outState, "randomFragment", fr);
}
here fr is an instance of fragment declared globally Fragment fr and RandomFragment is the fragment that I call in onPostExecute method of homeFragment AsyncTask class. I don't know initiation of RandomFragment is right or not that is fr = new RandomFragment();
Because I don't know how to find fragment by id or tag because there is no fragment tag in my activity layout file. I have just a fragment classes that extends Fragment and i call them like above. I am very confused here. I get the error
02-28 16:28:37.809: E/AndroidRuntime(4336): java.lang.IllegalStateException: Fragment RandomFragment{4247d248} is not currently in the FragmentManager
When I try to change the orientation to landscape. I got this error in putFragment Line. And in onRestoreInstanceState method I write code for getFragment
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction t = manager.beginTransaction();
if(savedInstanceState != null)
{
fr = (FragmentRandom)manager.getFragment(savedInstanceState, "randomFragment");
}
else
{
fr = new FragmentRandom();
}
t.add(fr, "randomFragment");
t.commit();
}
But when putFragment on onSaveInstanceState is execute that time I get error and my application stops forcefully so onRestoreInstanceState is not executing.
My actual problem is I don't know I initiate fragment in right way or not. And if it is right then why I get the error? Should I have to do anything with onSaveInstanceState method of fragment also.
You seem to be trying to put a completely new instance of your fragment into the fragment manager. Not only will this cause the issue that you are seeing, if it had worked you wouldn't have been restoring the instance state of that fragment. Try finding the current fragment using the fragment manager.
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
FragmentManager manager = getSupportFragmentManager();
Fragment fr = manager.findFragmentById(R.id.frame_container);
manager.putFragment(outState, "randomFragment", fr);
}
http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/
hi all, I have succeeded apply this Android Sliding Menu in my project.
however, how can i add some activity in diffferent page?
In MainActivity, displayView function controls the fragment which i have selected.you can see it only use in "Fragment fragment = null;",so , the CESDemo class is extends Fragment.But i cannot add my activity in the CESDemo, such as onTouch and so on.If i change it to FragmentActivity, it does not allow me for "ragmentManager.beginTransaction().replace(R.id.frame_container,fragment).commit();"
So, how can i apply some activity in different fragment,even i can design the layout but no any activity i can create.
MainActivity.java
private void displayView(int position) {
// update the main content by replacing fragments
//Fragment fragment = null;
Fragment fragment =null;
switch (position) {
case 0:
fragment = new CESHome();
break;
case 1:
fragment = new CESAll();
break;
case 2:
fragment = new CESPending();
break;
case 3:
fragment = new CESInProgress();
break;
case 4:
fragment = new CESCompleted();
break;
case 5:
fragment = new CESDemo();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
CESDemo.java
public class CESDemo extends Fragment {
public CESDemo(){}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_cesdemo, container, false);
return rootView;
}