I'm new to android programming and I'm trying to make an app that uses tabs in a viewpager from one main fragmentactivity.
The viewpager and tabs work fine but I want to have an options menu that when an item is selected, opens a completely new fragment, but I don't seem to be able to remove the view pager. I would like to just be able to put the new fragment over the viewpager on the main screen but trying to do that with a fragmenttransaction doesn't seem to work
Any ideas?
Thank you for your time
Ensure that:
1) your Fragment (e.g.: ViewPagerFragment1), which will be selected by the viewpager, has a FrameLayout as root layout with the id "container" e.g:
<FrameLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/container"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout.... and so on
</FrameLayout>
2) Inside the ViewPagerFragment1 class, you have to replace/add the new fragment to the FrameLayout after an action has been triggered. E.g.:
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.selection:
// Create new fragment and transaction
NewFragment newFragment = new NewFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container, newFragment, "NewFragment");
transaction.addToBackStack(null);
transaction.commit();
break;
default:
break;
}
}
Well, you will be adding the Fragment to some FrameLayout using the ID of the FrameLayout I assume. Just make sure the FrameLayout you are adding the Fragment to is on top of the ViewPager.
For example if both the ViewPager and FrameLayout are in a RelativeLayout container then make sure the FrameLayout is declared below the ViewPager in the XML. This will stack the FragmeLayout on top of the ViewPager. When the Fragment is added to the FrameLayout it will be drawn on top.
Related
I try on another forum, thanks for answer but this was too hard tho!! :)
You should create specific layout for your fragment in activity layout and specify its id in replace method. For more information read fragment documentation
here is the documentation of FragmentTransaction.replace()
The first parameter is the ID of the container view which contains your Fragments and not the ID of your layout
The second is the instance of the Fragment you want to display.
Generally, something like this is done :
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, myFragment);
fragmentTransaction.commit();
First of all you need to have a frame layout in your main activity where you can place fragments and show to your users. That can be done like this:
<android.support.constraint.ConstraintLayout
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".HomeActivity"
tools:showIn="#layout/app_bar_home">
<FrameLayout
android:id="#+id/frm"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
</FrameLayout>
Now in the frame layout (id = frm), you can place various fragments based on button clicks by your users. Now, by default place the first fragment in the frame layout and have a button in that fragment. Which can be done by adding the below line in your main activity:
fragmentTransaction.replace(R.id.frm,new FirstFragment()).addToBackStack(null).commit();
Once that button is clicked, you can write logic to replace the 1st fragment with 2nd fragment. Use the sample code below:
Your 1st fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#color/litegrey">
<Button
android:id="#+id/frag2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go to fragment 2" />
</LinearLayout>
Logic to move to next slide (this should be added in your 1st Fragment):
frag2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragmentTransaction.replace(R.id.frm,new SecondFragment()).addToBackStack(null).commit();
}
});
You can create one activity that contains a frameLayout with an id similar to fragment_container.
then from your activity you do the following:
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
that will place one fragment inside your Activity's layout. When you want to replace that, you just create the second fragment and do the same. If you want to make it easier just use it as a method:
public void replaceFragment(Fragment fragment, Context context) {
FragmentTransaction transaction = context.getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
and use it when you need to either display a fragment or swap one for an already displaying fragment. As Context use the activity that holds the fragments.
The idea is that you have one activity as a wrapper to the fragment. In its layout file you create a space for the fragment to be displayed, and with the above method, you replace the empty space with your fragment's layout. If you call it again with a different fragment in the arguments, it will automatically replace that space with the layout of the new fragment.
EDIT: If you want to switch back and forth using a button, add a button in your activity's layout and set an onClick listener. Then use a flag to choose which fragment to display.
boolean isFragmentOneDisplayed;
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isFragmentOneDisplayed) {
FragmentTwo fragment = new FragmentTwo();
replaceFragment(fragment, MainActivity.this);
isFragmentOneDisplayed = false;
} else {
FragmentOne fragment = new FragmentOne();
replaceFragment(fragment, MainActivity.this);
isFragmentOneDisplayed = true;
}
}
});
I found so many similar questions and so many different answers, but none of them helped me. I will try to post a clear question to get a clear answer if it's possible.
So I have an Activity that has a ViewPager with FragmentStatePagerAdapter containing (for now) only one fragment (HomeScreenFragment).
Inside HomeScreenFragment I have a RecyclerView with a list of several kind of different icons which should open a different fragment for each item click.
HomeScreenFragment has a FrameLayout as a root layout with id name "container". This is the method I'm calling to replace HomeScreenFragment with MainTypesFragment in this case:
private void openAllTypesFragment() {
MainTypesFragment fragment = new MainTypesFragment();
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(HomeScreenFragment.class.getName());
transaction.commit();
eventBus.post(new Event(null, Event.EVENT_FRAGMENT));
}
Since FragmentStatePagerAdapter is initialized in MainActivity, I'm sending an event which will MainActivity catch and call adapter.notifyDataSetChanged();
Doing it this way, nothing happens.. I tried with getChildFragmentManager() instead of getActivity().getSupportFragmentManager() and in that case, previous fragment (HomeScreenFragment) is visible underneath new one (MainTypesFragment)..
Any ideas what am I doing wrong here?
The container you are using is wrong.Maintain one container in the activity xml and use that container to load all the fragments.
transaction.replace(R.id.container, fragment);
The container here is to be the activity container in which viewpager and other views should be present.
You can try my code :
private void addFilmDetailFragment(Movie movie){
android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FilmDetailFragment fragment = new FilmDetailFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("movie", movie); // Key, value
fragment.setArguments(bundle);
fragmentTransaction.replace(R.id.mainContentStore, fragment);
// fragmentTransaction.replace(R.id.mainContent, fragment, Config.TAG_FILM_DETAIL);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
In a fragment of viewpager :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainContentStore"
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerFilm"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
It worked for me, i hope it will help your problem!
You need container inside activity for ViewPager and inside fragments(pages), containers for opening new fragments inside pages.
And if you want to open new fragment you should user something like this
in page fragment
getChildFragmentManager().beginTransaction()
.replace(R.id.page_fragment_container, fragment)
.addToBackStack(name)
.commit()
where R.id.page_fragment_container container inside page fragment.
I've the following situation:
Linear Layout
ToolBar
SlidingTabLayout
ViewPager
FrameLayout
Initially, I only add a fragment to the FrameLayout, and all works. Next I remove this fragment, create new Adapter, and bind adapter to the SlidingTabLayout. All works again, but now I need to set tab visibility to false, and I do this with
slidingTabLayout.setVisibility(View.GONE);
but I also need to replace the current view with a new fragment.
Usually I do this with:
getFragmentManager().replace(parent, newFragment);
but now I can't do this because
getFragmentManager().replace(ViewPager, newFragment);
doesn't works. So how can I do this? And if is possible, can I add the ViewPager replacing in the backstack?
I find a solution. I made the following update to my layout:
Linear Layout
ToolBar
Linear Layout (id: parentScroll)
SlidingTabLayout
ViewPager
Frame Layout (id: parent)
So when I need to hide all the tabs and the ViewPager, in order to inflate a new Fragment in the Frame Layout, I do the following:
parentScroll.setVisibility(View.GONE);
MyFragment myFragment= new MyFragment ();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.parent, myFragment, "MYTAG");
transaction.commit();
In the onBackPressed of this new fragment:
MyFragment myFragment= (MyFragment) getSupportFragmentManager.findFragmentByTag("MYTAG");
if (myFragment!= null && myFragment.isVisible()) {
parentScroll.setVisibility(View.VISIBLE);
getSupportFragmentManager().beginTransaction().remove(myFragment).commit();
}
I got a xml layout for main activity with some buttons on top of the screens. Below them is placed ViewPager:
<ViewPager android:id="#+id/viewpager">
I also got two fragments in mainactivity.class, each with it's own layout:
frag1 = new Fragment1(); frag2 = new Fragment2(); and viewpager = (ViewPager) findViewById(R.id.viewpager);
Now whats the simplest way to add these two fragments to ViewPager (but without using ActionBar TABS)? I also need to run some code according to which fragment is selected by user, for example make Toast with text "Fragment 2 is selected" when swiped to frag2.
Ok, now I have extended FragmentPagerAdapter: Public class frAdapter extend FragmentPagerAdapter {
public Fragment getItem(int i) { ... }
What I'm supposed to do in getItem() method to add these fragments to viewpager?
Good morning. I'm developing an app in which I have a main layout that extends from activity and inside this one I have one fragment of one data type, in my case FragmentCover (it's a class).
During my app, I push a button and I want to change this fragment layout for another layout that extends from fragment but of different type, called SongList.
My problem is that I have defined this fragment for the class of Cover and when I change I don't have any problem, but when I want to get the views and set to one variable of my class, the funciont songList = (ListView) getView().findViewById(R.id.songList); it's null and it gives me error.
I put it here what I do.
layout
<fragment android:name="es.xxx.ui.FragmentCover"
android:id="#+id/pruebaa"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/songBar"
android:layout_below="#id/header"/>
mainclass change
public void onClick(View v) {
if(isCoverFragment){
FragmentSongList fragmentSongList = new FragmentSongList();
transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.pruebaa, fragmentSongList);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("LIST");
transaction.commit();
isCoverFragment=false;
}
else{
transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.pruebaa, fragmentCover);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("COVER");
transaction.commit();
getSongCover();
isCoverFragment=true;
}
The problem is not the change, is when I try to make the findViewById, it's probabbly because it doesn't load the view associated with FragmentSongList.
You need to use a FrameLayout inside your layout file, instead of defining the Fragment in .xml
Into that FrameLayout, you can inflate any Fragment you want.
Just inflate the First Fragment you want to be displayed directly in your onCreate(...) method.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
This is how to inflate the Fragments programatically into the FrameLayout.
FragmentSongList fragmentSongList = new FragmentSongList();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame, fragmentSongList);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("LIST");
transaction.commit();
You can leave the code inside your onClick() method just the way it is, just change the id to "content_frame". Furthermore, as mentioned above you will have to inflate the first Fragment that should be displayed inside your onCreate(...) method.