I am new to Android development and have added an additional item to a Navigation menu which successfully opens an external browser window but clears the app screen (except for the navigation menu) when startActivity in onActivityCreated is performed.
I am not making any more progress despite working on this for several days so I am asking for help now. Perhaps this is a simple question for someone with more experience. I have spent a week looking at all the other answers in SO, YouTube and Google Developer Courses trying to solve this so I am asking for help now.
WebsiteFragment.java
public class WebsiteFragment extends Fragment {
View myFragment;
RecyclerView websiteList;
LinearLayoutManager layoutManager;
private static final String COMMON_TAG="CombinedLifeCycle";
private static final String ACTIVITY_NAME =WebsiteFragment.class.getSimpleName();
private static final String TAG=ACTIVITY_NAME;
public static WebsiteFragment newInstance() {
WebsiteFragment websiteFragment = new WebsiteFragment();
return websiteFragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
//Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_website, container, false);
Log.i(TAG,ACTIVITY_NAME+" onCreateView");
websiteList = (RecyclerView)view.findViewById(R.id.websiteList);
layoutManager = new LinearLayoutManager(getActivity());
websiteList.setHasFixedSize(true);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://english-alps.com"));
// App Window is cleared??
getActivity().startActivity(i);
Log.i(TAG,ACTIVITY_NAME+" onActivityCreated");
}
}
fragment_webiste.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WebsiteFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/websiteList"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</FrameLayout>
Edit 21-08-2018
Added the following code to try and save Fragment state but it generates the error:
java.lang.NullPointerException: Attempt to read from field 'int androidx.fragment.app.Fragment.mIndex' on a null object referen.
I am having trouble with the parameters to getFragmentManager. How should the variables to getFragmentManager be initialized?
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState!=null){
Log.i(TAG,ACTIVITY_NAME+" calling onSaveInstanceState");
onSaveInstanceState(savedInstanceState);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState,TAG,myFragment);
Log.i(TAG,ACTIVITY_NAME+" onSaveInstanceState");
}
Edit#2 21-08-2018
Home.Java which adds WebsiteFragment to the Activity
public class Home extends AppCompatActivity {
BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment selectedFragment = null;
switch (menuItem.getItemId()) {
case R.id.action_category:
selectedFragment = CategoryFragment.newInstance();
break;
case R.id.action_ranking:
selectedFragment = RankingFragment.newInstance();
break;
case R.id.action_website:
selectedFragment = WebsiteFragment.newInstance();
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, selectedFragment);
transaction.addToBackStack(String.valueOf(R.id.frame_layout)); /* 21.08.2018 */
transaction.commit();
return true;
}
});
setDefaultKeyMode();
}
}
Edit #3 21-08-2018 activity_home.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Home">
<FrameLayout
android:id="#+id/frame_layout"
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/navigation"></FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorPrimary"
app:itemIconTint="#drawable/nav_item_color_state"
app:itemTextColor="#drawable/nav_item_color_state"
app:menu="#menu/bottom_menu"
/>
</RelativeLayout>
Related
I'm creating an app that contains 5 tabs in the bottom navigation menu. One of these tabs contains a default settings activity that I created with Android Studio. The onClick event on every tab displays a different fragment. When I click on the "Settings" button the fragment for the settings activity is loaded with no errors, however it is empty. I've looked elsewhere, but still haven't found an answer. My problem is not about displaying a group of settings in a different fragment, rather generating for the first time the Settings fragment itself.
I listen for the click event in the main activity. Then I load the right fragment class, this class calls the .SettingsActivity class that generates the view using settings_activity.xml and loads the "settings" from root_parameters.xml. I've changed nothing from the default activity created by Android Studio. And I'm loading it the same way I load the other fragments and they all work, including a Google Maps fragment.
This is my .MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.map_nav:
selectedFragment = new MapFragment();
break;
case R.id.settings_nav:
selectedFragment = new OldSettingsFragment();
break;
case R.id.user_nav:
selectedFragment = new UserFragment();
break;
case R.id.test_settings_nav:
selectedFragment = new SettingsFragment();
break;
default:
selectedFragment = new HomeFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment).commit();
return true;
}
};
}
Here is my .SettingsFragment
public class SettingsFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.settings_activity, container, false);
}
}
This is the .SettingsActivity as created by Android Studio
public class SettingsActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
}
This is settings_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".TestSettings.SettingsActivity">
<FrameLayout
android:id="#+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
And finally this is my root_preferences.xml
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="#string/app_name">
<EditTextPreference
app:key="signature"
app:title="#string/signature_title"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:defaultValue="reply"
app:entries="#array/reply_entries"
app:entryValues="#array/reply_values"
app:key="reply"
app:title="#string/reply_title"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
<PreferenceCategory app:title="#string/sync_header">
<SwitchPreferenceCompat
app:key="sync"
app:title="#string/sync_title" />
<SwitchPreferenceCompat
app:dependency="sync"
app:key="attachment"
app:summaryOff="#string/attachment_summary_off"
app:summaryOn="#string/attachment_summary_on"
app:title="#string/attachment_title" />
</PreferenceCategory>
PLEASE HELP.
You can not set an Activity in one of BottomNavigationView tabs instead of a fragment.
So, you need to replace SettingsActivity with a Fragment, I will name it as PreferenceFragment as you already has an inner SettingsFragment.
So modify your SettingsActivity with:
public class PreferenceFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_settings, container, false);
ActionBar actionBar = requireActivity().getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
return view;
}
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
}
So, now delete settings_activity.xml and you need to create fragment_settings.xml instead to have a static fragment for the inner SettingsActivity Fragment
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="#+id/settings_root"
android:layout_height="match_parent">
<fragment
android:id="#+id/settingsFragment"
class="com.xx.PreferenceFragment$SettingsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Note: replace the com.xx with your package name that holds the PreferenceFragment
You are loading the SettingsFragment on test_settings_nav click which inflate R.layout.settings_activity and the entire layout has a FrameLayout under a LinerLayout and you don't load anything in that FrameLayout so its Empty. Load something on that frame layout will appear in screen.
I'm doing an app so when you click on a login button, it will then display a screen with a bottom menu. But I'm having problems with setting the listener to the items in the menu. The problem is when I try to use findViewById to find my BottomNavigationView it will look for it in my activity_main instead of the fragment (welcome_fragment) where I have put it, because I only want it to show when someone has logged in. And therefore I will get null as the BottomNavigationView.
I have tried setting setContentView(R.layout.welcome_fragment) in my method "welcomePage", which does make it so that so that it will find it and it won't be null. However this results in a lot of other errors such as
" No view found for id 0x7f080032 (com.example.MyAPP:id/container) for fragment WelcomePage{9547e9f #1 id=0x7f080032}", so I don't believe it to be the right way to go about it.
Here is my MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getFragmentManager();
Login loggingIn= new Login();
fm.beginTransaction().replace(R.id.container, loggingIn).commit();
}
//When button is pressed we get into this function
public void finishProcess(){
WelcomePage wp = new WelcomePage();
FragmentManager fm = getFragmentManager();
fm.beginTransaction().addToBackStack(null);
fm.beginTransaction().replace(R.id.container, wp).commit();
try {
//Here is where I get null, because we are looking in activity_main
BottomNavigationView bottomNav=findViewById(R.id.bottomnavigate);
bottomNavigation.setOnNavigationItemSelectedListener(menuListener);}
catch (Exception e) {
System.out.println(e);
}
}}
//Have tried this one and it works fine
private BottomNavigationView.OnNavigationItemSelectedListener menuListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {...}
}
Here is my WelcomeFragment:
public class WelcomePage extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.welcome_fragment, container, false)}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Here is my layout to the welcome_fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WelcomePage"
android:background="#drawable/welcomegradient">
<FrameLayout
android:id="#+id/showing_page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/bottomnavigate">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottomnavigate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:menu="#menu/mymenu"
android:background="?android:attr/windowBackground" />
</RelativeLayout>
As I mentioned earlier the problem is that findViewById can't find the BottomNavigationView because it is looking in the activity_main instead of welcome_fragment and I don't want to put my menu in activity_main because I only want to display it when a user has logged in. How do I fix this problem?
Try this, it should work.
WelcomePage
public class WelcomePage extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.welcome_fragment, container, false);
//Have tried this one and it works fine
BottomNavigationView.OnNavigationItemSelectedListener menuListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {...}
BottomNavigationView bottomNav = view.findViewById(R.id.bottomnavigate);
bottomNav.setOnNavigationItemSelectedListener(menuListener);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fm = getSupportFragmentManager();
Login loggingIn= new Login();
fm.beginTransaction().replace(R.id.container, loggingIn).commit();
}
//When button is pressed we get into this function
public void finishProcess() {
WelcomePage wp = new WelcomePage();
fm.beginTransaction().addToBackStack(null);
fm.beginTransaction().replace(R.id.container, wp).commit();
}
}
I have an app that has 1 Main Activity and 5 main fragments. When the MainActivity is created I create a List containing each of the 5 fragments. The user is presented with a tab bar on the bottom of the screen which he/she can use to navigate between fragments. How do I set this up so as when the user selects a tab, the corresponding fragment is shown without creating a new instance of it? Just want to change the view on the screen to the already created fragment.
I am using a BottomBar from https://github.com/roughike/BottomBar which calls a "onTabSelected" interface method when a tab is pressed.
You can use 5 Fragments with the library you specified like this. The layout file should look like this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- This could be your fragment container, or something -->
<FrameLayout
android:id="#+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottomBar" />
<com.roughike.bottombar.BottomBar
android:id="#+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
app:bb_tabXmlResource="#xml/bottombar_tabs" />
</RelativeLayout>
The containing Activity class will replace the Framelayout with Fragment depending on the Fragment selected from the BottomBar View. A simple example
public class Main3Activity extends AppCompatActivity {
private Fragment fragment;
private FragmentManager fragmentManager;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_three_tabs);
BottomBar bottomBar = (BottomBar) findViewById(R.id.bottomBar);
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
#Override
public void onTabSelected(#IdRes int tabId) {
if(tabId == R.id.tab_home){
fragment = new HomeFragment();
}
if(tabId == R.id.tab_favorite){
fragment = new FavoriteFragment();
}
}
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.contentContainer, fragment).commit();
});
bottomBar.setOnTabReselectListener(new OnTabReselectListener() {
#Override
public void onTabReSelected(#IdRes int tabId) {
Toast.makeText(getApplicationContext(), TabMessage.get(tabId, true), Toast.LENGTH_LONG).show();
}
});
}
}
Then you can create individual Fragment with their content like below
public class FavoriteFragment extends Fragment {
public FavoriteFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_favorite, container, false
);
}
}
I have problems with incorporating the world map on a fragment android
Since an activity is performed in this way :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RajawaliSurfaceView surface = new RajawaliSurfaceView(this);
surface.setFrameRate(60.0);
surface.setRenderMode(IRajawaliSurface.RENDERMODE_CONTINUOUSLY);
// Add mSurface to your root view
addContentView(surface, new ActionB
ar.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT));
renderer = new Renderer(this);
surface.setSurfaceRenderer(renderer);
}
But when I want to do it in a fragment gives me error line
addContentView(surface, new ActionBar.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT));
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RajawaliSurfaceView surface = new RajawaliSurfaceView(getActivity());
surface.setFrameRate(60.0);
surface.setRenderMode(IRajawaliSurface.RENDERMODE_CONTINUOUSLY);
// Add mSurface to your root view
addContentView(surface, new ActionBar.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT));
renderer = new Renderer(getActivity());
surface.setSurfaceRenderer(renderer);
}
Well i think you are misunderstanding the difference between a Fragment and Activity, this error message:
cannot find symbol method addContentView()
points that this method doesn´t exist!
This is a very basic example of how to load the Rajawali3D map into fragment Android.
Create the Activity, adding the Fragment transaction, the fragment is loaded into the map_fragment container, defined in act_frag_map layout:
public class Map3DFragActivity extends AppCompatActivity {
public RajawaliSurfaceView rajawaliTexture;
Renderer renderer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_frag_map);
setFragment();
}
protected void setFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment mapFragment = new FragmentMap();
FragmentTransaction ft =
fragmentManager.beginTransaction();
ft.add(R.id.map_fragment, mapFragment).commit();
}
}
This is the layout containing a fragment, adding in the property android:name the name of our class fragment:
act_frag_map
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentExampleActivity" >
<fragment
android:id="#+id/map_fragment"
android:name="com.test.FragmentMap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
/>
</RelativeLayout>
This is the Fragment that creates the map!
FragmentMap
import org.rajawali3d.surface.RajawaliSurfaceView;
public class FragmentMap extends Fragment {
public RajawaliSurfaceView rajawaliTexture;
Renderer renderer;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_frag_map,
container, false);
rajawaliTexture = (RajawaliSurfaceView) view.findViewById(R.id.rajawali_surface);
renderer = new Renderer(getActivity());
rajawaliTexture.setSurfaceRenderer(renderer);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // make sure this line exists
}
}
activity_frag_map
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:surfaceview="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<org.rajawali3d.surface.RajawaliSurfaceView
android:id="#+id/rajawali_surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
surfaceview:frameRate="60.0"
surfaceview:renderMode="RENDER_WHEN_DIRTY"/>
</FrameLayout>
What I am trying to do: Starting from a Master/Detail flow project, I am trying to enable the user to press an item in the ActionMenu which should show a fragment where new data can be put in.
Problem: I get an error when I try to start the fragment. What am I doing wrong?
After pasting the code I think I have made a mess of it. Still need help.
Error:
java.lang.IllegalArgumentException: No view found for id 0x7f090040 (com.example.androidtest:id/AddItem_fragment) for fragment AddItem{5b161e7 #1 id=0x7f090040}
ItemListActivity.java:
public class ItemListActivity extends ActionBarActivity implements
ItemListFragment.Callbacks {
private boolean mTwoPane;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
mTwoPane = true;
((ItemListFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_actions, menu);
setTitle("Shoppinglistan");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add:
openAddItem();
return true;
case R.id.action_send:
//openSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onItemSelected(String id) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id);
ItemDetailFragment fragment = new ItemDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment).commit();
} else {
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction()
.add(R.id.AddItem_fragment, additem).commit();
}
public static class AddItem extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.additem_layout,
container, false);
return rootView;
}
}
}
activity_item_detail.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/item_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.androidtest.ItemDetailActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:name="com.example.androidtest.AddItem"
android:id="#+id/AddItem_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
/>
</FrameLayout>
additem_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
your problem is this line
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction()
.add(R.id.AddItem_fragment, additem).commit();
}
you already have it here
<fragment
android:name="com.example.androidtest.AddItem"
android:id="#+id/AddItem_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
/>
you can not recreate it programmatically, all you need to do is remove the programmatically added fragment,and this will be there, since (in a different language its stack)..
EDIT
to address your comment,first of all add a tag to your fragments when calling ItemDetailFragment for instance "ItemDetailFragment" & instead of the previous code in openAddItem() replace them with this
public void openAddItem() {
getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().
findFragmentByTag("ItemDetailFragment"));
getSupportFragmentManager().popBackStackImmediate(); //
// if your fragment is still not showing then uncomment the below line
//getSupportFragmentManager().beginTransaction().show(getSupportFragmentManager().
findFragmentById(the_id_of_ur_fragment));
}
hope its good enough
From the documentation, the add method:
abstract FragmentTransaction add(int containerViewId, Fragment fragment)
Calls add(int, Fragment, String) with a null tag.
In your code:
public void openAddItem() {
AddItem additem = new AddItem();
getSupportFragmentManager().beginTransaction().add(R.id.AddItem_fragment, additem).commit();
}
This code will find in your views a view with the id R.id.AddItem_frament and it will try to attach to it the view associated to the fragment passed. Since in your layout there is not a ViewGroup that serves as a container it is launching you a legitimate IllegalArgumentException since the id is not present. What you have to do is provide a container in which you can add all the fragments and passing to the add method of the transaction this id.