Android Studio add Fragment in FragmentManager - java

I'm just getting into Android development and I followed the standard guide for creating a fragment on the official android developer documentation website. However, when I try to add my simple fragment to the fragment container, the add() method claims that the passed parameter of my Fragment class is incorrect.
This is my onCreate() method of my main activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.add(R.id.fragment_container_view, ChatFragment.class, null)
.commit();
}
}
and this is my Fragment class:
public class ChatFragment extends Fragment {
public ChatFragment() {
super(R.layout.chat_layout);
}
}
The compiler error I'm getting is "Required Type: Fragment, Provided: Class", although I just copied the code from the official documentation website. Maybe something changed since they wrote this, but I couldn't find a solution so far.
What I'm trying to do in general is that I've got my bottom navigation bar and depending on which item I click on, another fragment should be displayed, the upper fragment in my code being the "standard" view when starting the app.

use :
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
.add(R.id.fragment_container_view, new ChatFragment(), null)
.commit();

Try below things
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container_view,new ChatFragment(),"ChatFragment").commit();
In Chat Fragment instead of constructor try to inflate in onCreateView
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.chat_layout, container, false);
}

Related

ListView of a Fragment (of a ViewPager inside a Fragment) that implements LoaderCallbacks<Cursor> is empty when I return back to it

The ListView inside of a Fragment that contains a ViewPager is empty when I return back to it. This ViewPager is inside of a Fragment because I'm using a Navigation Drawer Layout. I'll try to explain it in more details now:
I am using a Navigation Drawer layout and, consequently, using Fragments. In the main activity, in onCreate, I set the current Fragment with these lines of code:
#Override
protected void onCreate(Bundle savedInstanceState) {
/* More code */
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
The MainFragment class contains a ViewPager that is initialized with these lines of code in the onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
/* More code */
ViewPager viewPager = (ViewPager) rootView.findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SimpleFragmentPagerAdapter(getActivity(), getActivity().getSupportFragmentManager()));
/* Code for Tablayout */
return rootView;
}
One of the Fragments of the SimpleFragmentPagerAdapter class is this one that implements LoaderManager.LoaderCallbacks
public class ExpensesFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private ExpenseCursorAdapter mExpenseCursorAdapter;
private static final int EXPENSE_LOADER = 1;
public ExpensesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_expenses, container, false);
ListView expensesListView = (ListView) rootView.findViewById(R.id.expenses_list_view);
mExpenseCursorAdapter = new ExpenseCursorAdapter(getContext(), null);
expensesListView.setAdapter(mExpenseCursorAdapter);
getLoaderManager().initLoader(EXPENSE_LOADER, null, this);
return rootView;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(/* arguments */);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
mExpenseCursorAdapter.swapCursor(data);
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
mExpenseCursorAdapter.swapCursor(null);
}
}
On the first run, everything works fine. However, if I click on the navigation drawer menu, which I'm implementing this way, the ListView becomes empty:
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_main) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new MainFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
} else if (id == R.id.nav_blank) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().remove(currentFragment).commit();
currentFragment = new BlankFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragments, currentFragment).commit();
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
The problem also exists when I rotate the device. There is a difference though. When I use the Navigation Drawer menu, none of the methods of the LoaderManager.LoaderCallbacks are called, but when I rotate the device, onLoadFinished is called.
Anyway, the problem persists. Any ideias how to solve it?
Thanks in advance.
I have found the solution!
Basically, I made two mistakes.
The first one is about the rotation of the device.
When the device is rotated, the Activity is destroyed and onCreate is called again. In this case, I should't call new MainFragment(). So, I check if the savedInstanceState is null before I call it, like this:
if (savedInstanceState == null) {
currentFragment = new MainFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().
replace(R.id.layout_for_fragments, currentFragment).commit();
}
The second one is about a fragment within a fragment. In this case, I can't simply call getSupportFragmentManager(). I should call getChildFragmentManager() instead and that's it!

onCreateView() method asking for super class call

I have extended fragmentActivity class , as far as I read onCreateView is available in lifecycle of fragmentActivity but its not supposed to be calling super class , but its giving me error in #override asking me to call super class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Initializing
MarkerPoints = new ArrayList<>();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override --> error Here
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_maps,
container, false);
Button button = (Button) view.findViewById(R.id.reportButton);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(getApplicationContext(),"Report Button Works",Toast.LENGTH_SHORT).show();
}
});
return view;
}
#Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
return super.onCreateView(parent, name, context, attrs);
}
Not
#Override --> error Here
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
You need you Fragments;
Step 1 - You need create one Fragment.
public class ExampleFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
//Create the view from XML layout.
final View view = inflater.inflate(R.layout.fragment_example, null);
//Perform additional configuration on layout components here.
return view;
}
}
Step 2 - Create Fragment:
public class Fragment1 extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.YOUR_LAYOUT, container, false);
}}
Step 3 - Create FragmentPagerAdapter
public class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
private Fragment1 fragment1;
public PagerAdapter(FragmentManager fm) {
super(fm);
this.fragment1 = new Fragment1();
this.fragmentList = new ArrayList<>();
this.fragmentList.add(this.fragment1);
}
#Override
public Fragment getItem(int position) {
//Get fragment in list position
return fragmentList.get(position);
}
#Override
public int getCount() {
//return size of fragments list.
return fragmentList.size();
}}
Step 4 - Add FragmentPagerAdapter in your FragmentActivity:
this._viewPager.setAdapter(new PagerAdapter(this.getSupportFragmentManager()))
FragmentActivity doesn't actually have a method called onCreateView(LayoutInflater, ViewGroup, Bundle), I think you're confusing it with Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) for which the default implementation only returns null in which case you don't actually need to call the super method.
FragmentActivity can act as a host for Fragments provided by the support library (regular Activity can only host android.app.Fragment). In your code you're using the SupportMapFragment which extends Fragment and overrides Fragment.onCreateView(LayoutInflater, ViewGroup, Bundle) to provide its view to the hosting Activity.
For an Activity, you'd typically just set your button click listeners in onCreate after calling setContentView.
You should try overriding onCreate and changing it from protected to public.
Plus, either get rid of setContentView(R.layout.activity_maps); or change it to getActivity().setContentView(R.layout.about_main_layout);
setContentView isn't availible only in a fragment Activity's java it must have getActivity(). in front of it.
Also, you need a blank public constructor, it's required, public BlankFragment() {
// Required empty public constructor
}
Finally, to my knowledge onCreateView is fine, it's what's around it, so please consider the above posibilites.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setContentView(R.layout.about_main_layout);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
// Initializing
MarkerPoints = new ArrayList<>();
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this); }
FragmentActivity is used to hold a Fragment prior to API 3.0. If you're targeting an app prior to Honeycomb then you should use FragmentActivity but if you're targeting an app after Honeycomb then you should use an Activity. And remember that the FragmentActivity holds a Fragment, which means that you should attach a Fragment and call OnCreateView() and other fragment methods on the Fragment and not on FragmentActivity.
The way to attach a Fragment to FragmentActivity is
android.support.v4.app.FragmentManager fm = myFragmentActivity.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(CONTENT_VIEW_ID, myFragment).commit();
Check out this excellent SO post explaining the difference between FragmentActivity and Fragments
Difference between Fragment And FragmentActivity

How to extend Activity in main class that extends "Fragment"?

I have an Android project and I use Navigation Drawer in it, and in the MainActivity, I have a switch-case, with options and your respective positions for to open when the user clicks. But, in a class called TelaQUEMSOMOS, the parameters that are there:
public class TelaQUEMSOMOS extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.telaquemsomos, container, false);
return rootView;
}
}
are extending from Fragment and not Activity. It's bad, because I need to put a Toast.makeText or findViewById, and I can't. How can I handle it?
Link for download my project(the project is in portuguese): https://goo.gl/pm5dIC
In your fragment you can call getActivity() to get instance of the activity.
Please check the code below. First we will have an activity Home.java
final String[] fragments = {
"com.locate.Establishment", "com.locate.Settings"};
ActionBarDrawerToggle mDrawerToggle;
DrawerLayout drawer;
public class Home extends Home {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
.
.//your other code here.
.
// Here I am going to call the Fragment called Establishment
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.main, Fragment.instantiate(Home.this, fragments[0]));
tx.commit();
setToolbar(0);
}
}
Implementation for Fragment. Here I am going to user support Fragment V4.
public class Establishment extends android.support.v4.app.Fragment{
SupportMapFragment mapFragment;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_establishment, null);
mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
//Now will able to all you need here. By using getActivity().
}
}

FragmentStatePagerAdapter NullException

I have two fragments that contains ViewPager. The first fragment that contain viewPager works very well. As I come to second fragment that contain ViewPager, I start to get FragmentStatePagerAdapter NullException. I knew what is the problem, I need to implement onDetach function to get rid this problem. I search around the internet, there is a lots of solutions. And I'm currently using API 19. So maybe this solution very suitable for me. But I don't know how to use the solution.
getSupportFragmentManager().beginTransaction().detach(mFragment1).replace(R.id.main, mFragment2).attach(mFragment2).addToBackStack(null).commit();
What is exactly mFragment1 and mFragment2 and R.id.main ?
Fragment 1
public class fragment1 extends fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_restaurantprocess, container, false);
adapter = new RestaurantProcessPageAdapter(getActivity().getSupportFragmentManager());
...
}
}
Fragment 2
public class fragment2 extends fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_feedpage, container, false);
adapter = new RestaurantFeedPageFragment(getActivity().getSupportFragmentManager());
...
}
}
I'm using slide animation to fragment
public void changeFragment_toRight(Fragment frag) /* Slide to right screen */ {
if (getSupportFragmentManager().findFragmentByTag("frag")!=null)
getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.right_slide_in, R.anim.right_slide_out).replace(R.id.container, frag, "frag").commit();
else
getSupportFragmentManager().beginTransaction().add(R.id.container, frag, "frag").commit();
}
changeFragment_toRight(new fragment1());
changeFragment_toRight(new fragment2());
Source: Click here to view the source
It looks like the problem is that you are manually using a FragmentTransaction to change fragments. A ViewPager will do this automatically when you supply it with an adapter, so when you change fragments, you are trying to remove a fragment that has already been removed.

Using FragmentManager and FragmentTransaction in a DialogFragment

The gist of the issue is this: I'm trying to Launch a DialogFragment from a FragmentActivity. This DialogFragment's view contains a FrameLayout which I would like to populate with a Fragment. Basically the FragmentActivity launches the DialogFragment, then the DialogFragment populates it's FrameLayout with a Fragment. I've scoured the internet for tutorials and I've pieced together something that (in my mind) should work. However, no matter what I try I continuously get errors. This is what I have so far:
This is my FragmentActivity's layout (file name is "activity_interact"):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/activity" >
<Button
android:id="#+id/btnLaunchDialog"
style="#style/btn" />
This is my DialogFragment's layout (file name is "dialog_overview"):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/dialog" >
<FrameLayout
android:id="#+id/frameDisplay"
style="#style/frame" />
This is my Fragment's layout (file name is "fragment_stats"):
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/table" >
<TableRow style="#style/table" >
<TextView
style="#style/display"
android:gravity="right"
android:text="#string/textStr" />
</TableRow>
Here is the java code for my FragmentActivity:
public class ActivityInteract extends FragmentActivity implements
OnClickListener {
Button btnLaunchDialog;
#Override
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_interact);
btnLaunchDialog = (Button) findViewById(R.id.btnLaunchDialog);
btnLaunchDialog.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnLaunchDialog:
FragmentManager fm = getSupportFragmentManager();
DialogOverview dialogOverview = new DialogOverview();
dialogOverview.show(fm, "dialog_overview");
break;
}
}
}
Here is my DialogFragment's code:
public class DialogOverview extends DialogFragment implements OnClickListener {
public DialogOverview() {
}
#Override
public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) {
View view = li.inflate(R.layout.dialog_overview, vg);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.frameDisplay, new FragmentStats());
ft.commit();
return view;
}
}
Here is my Fragment's code:
public class FragmentStats extends Fragment {
#Override
public View onCreateView(LayoutInflater li, ViewGroup vg, Bundle b) {
View view = li.inflate(R.layout.fragment_stats, vg);
return view;
}
}
And finally, here is the logcat error:
06-11 10:07:29.382: E/AndroidRuntime(30013): java.lang.IllegalArgumentException: No view found for id 0x7f060003 for fragment FragmentStats{4169c928 #1 id=0x7f060003}
I can see that it's saying that I don't have a view for the Fragment, but I do...(or do I?) I'm lost here, any help would be appreciated. Also, am I going about this the right way? Would it be more efficient to re-use a FragmentManager? (i.e. pass it from the FragmentActivity into the DialogFragment)
Update: I removed the code to load my Fragment into the DialogFragment and the DialogFragment displays without issue now. So obviously (as the logcat error suggests) there is something wrong with my Fragment itself...however, it matches examples that I've seen on the internet. Which is making me wonder: Is there an issue with nesting fragments in this way? A FragmentActivity displaying a DialogFragment that displays a Fragment makes me want to quip that "we can't go any deeper" but I don't know. Could I nest more fragments?
Actually, you CAN add nested fragment to a DialogFragment, BUT it cannot be based on a wrapped Dialog.
Instead of overriding onCreateDialog, inflate the View that contains the ViewGroup that will use the Fragment in onCreateView.
A consequence of this is that you cannot use a DialogFragment that wraps an AlertDialog - so if you want positive and negative buttons you need to manually create them in the content view.
Also, keep in mind that you cannot set the fragment in the XML. You need to declare the container view in XML and perform the fragment transaction programmatically.
public class MyDialogFragment extends DialogFragment {
[...]
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.dialog_layout, container);
if (savedInstanceState == null) {
final ChildFragment fragment = [...];
getChildFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit();
}
return view;
}
}

Categories