I am trying to add multiple fragments to a FrameLayout. I need to add them one below another. But they are overlapping.
main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
MainActivity.java
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
// Create instance of fragments
FragmentPrimaryList firstFrag = new FragmentPrimaryList();
FragmentSecondaryList secFrag = new FragmentSecondaryList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// add fragment to the fragment container layout
fragmentTransaction.add(R.id.fragment_container,firstFrag);
fragmentTransaction.add(R.id.fragment_container,secFrag);
fragmentTransaction.commit();
}
}
They looks like this. How can I solve this?
Use the replace method instead of the add method.
The replace method hides the current fragment before adding new one, the add method simply adds the new fragment without disposing off the older fragment.
In order to retain the back stack, use the fragment transaction with backstack management.
I need to display both fragments at same time, one below another
You can try the following layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
Now add fragmments using:
fragmentTransaction.add(R.id.fragment_container1,firstFrag);
make sure you Fragment's layout_height = "wrap_content"
Add background to your fragments and make "android:clickable="true" to parent layout.
Do this way:
First fragment
FragmentPrimaryList firstFrag = new FragmentPrimaryList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// add fragment to the fragment container layout
fragmentTransaction.add(R.id.fragment_container,firstFrag);
fragmentTransaction.commit();
second fragment
FragmentSecondaryList secFrag = new FragmentSecondaryList();
fragmentManager = getSupportFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_container,secFrag);
fragmentTransaction.commit();
Related
On the click of a button I want to navigate from one fragment to another. The problem is that when I press the button the second fragment overlaps the other.
I searched for some answers but it doesn't seem to word in my case. I tried adding a background color but it still overlaps.
So after I click the button the following thing happens:
Here are my codes:
I gave the first fragment an ID:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment"
android:background="#FFF">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="1dip"
app:layout_constraintBottom_toTopOf="parent"
android:background="#FFF"/>
The ID of the button is: nextFragment
The code inside the class of the first fragment is:
nextFragment = v.findViewById(R.id.nextFragment);
nextFragment.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
Fragment fragment = new NotificationsFragment();
FragmentManager fragmentManager = getParentFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
}
});
Hope i gave enough information, if not don't hesitate to ask for more! Thanks in advance.
The problem is that you are using fragment_container as the first fragment instead of the container for your first fragment.
In your MainActivity you have to load your first fragment inside that container. Not use it as a fragment.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
Fragment firstFragment = new YourFirstFragment();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.fragment_container, firstFragment);
transaction.commit();
}
}
After that, in your first fragment, when you will replace the fragment it will work great.
So the solution was simple.. I gave an Id to a framelayout inside the first fragment instead of to the root layout.
Now the next thing is that the tab on the bottom also has to change when the button is pressed.
I have created an Activity containing a FrameLayout with the ID "container", though I cannot refer to this view, I have tested it in a simple reference:
activity layout:
<FrameLayout 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"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="app.chrono.name.LoginActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</FrameLayout>
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
FragmentManager fragmentManager = activity.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(current);
fragmentTransaction.add(R.id.container, new LoginFragment()); //container is written in red
}
I do not understand why this container cannot be refered to. It should be accessible. It is written in red and seems to not exist.
Your code is right,
Click on the line that is below your code findviewbyid and one suggestion comes press alt+enter that's all.
Also try to invalidate cache and restart :
Go to file and invalidate cache and restart.
Container is a view but in specific it is a layout view i.e FrameLayout.
So change the type to FrameLayout instead of View.
FrameLayout container = (FrameLayout)findViewById(R.id.container);
EDIT:
Also if you find first solution not working add the id directly in the fragment transition like this.
fragmentTransaction.add(R.id.container, new LoginFragment());
You should commit(); your fragment transaction.
FragmentManager fragmentManager = activity.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(current);
fragmentTransaction.add(R.id.container, new LoginFragment());
fragmentTransaction.commit();
First remove this line from your code
container = findViewById(R.id.container);
Use this function for opening fragment
public void loadFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(current);
fragmentTransaction.add(R.id.container, new LoginFragment());
}
and call in onCreate like this
loadFragment(new LoginFragment());
And make sure you import these
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
I try to create an application that has two pages. First page is a tabbed page and second page is a detail page.
I create a tapped page using this guide. I have a mainactivity that contains view pager and 3 tabs(Tab1, Tab2, Tab3). Tab3 contains a button to navigate detail page. Each tab has own .java(extends Fragment) and .xml file. I edit fragmentThree.xml layout :
<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"
android:id="#+id/fragmentThree"]>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/goToDetail"
android:text="GO TO DETAIL" />
I create a new fragment for detail page. I set onclick method inside of Tab3.java;
goToDetail.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.mainActivity, new Detail());
transaction.commit();
}
});
When I press the button, it doesn't do anything. I don't replace the fragment.
Use you viewpager id instead of main layout id, where you set the tab layout fragment.
transaction.replace(R.id.viewpager, new Detail());
use Frame layout in Main Activity
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/parent">
In clicklistiner :-
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.parent, new Detail());
transaction.commit();
I am trying to add a fragment inside another fragment which is added in view pager. All fragment inside view pager are same. I am just viewing them with swipe. On button click, i add a fragment inside our main fragment by using add fragment. On doing this, this new fragment is being added to last fragment of view pager instead of current one.
Reason which seems to me is when we look for fragment, we still have last fragment active and that fragment adds this new fragment on top of it.
Everything works fine for first
public void onAddFragmentClick(View view) {
if (!isInfoShown) {
FragmentTransaction fragmentTransaction = this.getActivity().getSupportFragmentManager().beginTransaction();
fragment = new MainFragment();
fragmentTransaction.replace(R.id.fragment, fragment, "detail fragment");
fragmentTransaction.commit();
isInfoShown = true;
} else {
FragmentTransaction fragmentTransaction = this.getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
isInfoShown = false;
}
}
Main Fragment which is added in viewpager is
<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">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true" >
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.wedm.wedme.ui.fragment.PictureScreenFragment"
android:id="#+id/fragment"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal|top" />
</FrameLayout>
</RelativeLayout>
For nested fragments you should use the child fragment manager of the fragment where you want to add fragments. Hope this helps.
I haven't been able to find a way how to dynamically add fragment into existing dynamically added fragment. Do you know, if it is possible?
I am generating fragments this way:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xact = fragMgr.beginTransaction();
if(null == fragMgr.findFragmentByTag(FRAG1_TAG)) {
xact.add(10101010, new DateTime(), FRAG1_TAG);
}
if(null == fragMgr.findFragmentByTag(FRAG4_TAG)) {
xact.add(7777, new loginForm(), FRAG4_TAG);
}
xact.commit();
How to add into FRAG4_TAG fragment another one?
Edit2:
I hard coded it's id to be able to work with it in future (where ll is my linearLayout in XML):
FrameLayout frml4 = (FrameLayout)inflater.inflate(R.layout.frame,null);
frml4.setId(7777);
frml4.setBackgroundColor(Color.YELLOW);
ll.addView(frml4);
I assume the problem that you are running into is that there is not an inflated view to add the fragment to because the original fragment, FRAG4_TAG, has not been inflated before you are trying to add it.
You can pass enough information to FRAG4_TAG in the Arguments to let it know that it should create and add a fragment (or what all fragments you need it to have) to itself during it's onCreateView, after the view has been inflated...
The layout for the activity...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="MyActivity"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/main_frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The Activity...
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragOne = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", true);
fragOne.setArguments(arguments);
ft.add(R.id.main_frag_container, fragOne);
ft.commit();
}
}
The layout for the fragment...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="20dp">
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Some fragment"/>
<LinearLayout
android:orientation="vertical"
android:id="#+id/frag_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
The fragment...
public class MyFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.frag_layout, container, false);
boolean shouldCreateChild = getArguments().getBoolean("shouldYouCreateAChildFragment");
if (shouldCreateChild) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.beginTransaction();
Fragment fragTwo = new MyFragment();
Bundle arguments = new Bundle();
arguments.putBoolean("shouldYouCreateAChildFragment", false);
fragTwo.setArguments(arguments);
ft.add(R.id.frag_container, fragTwo);
ft.commit();
}
return layout;
}
}
This example covers the case where you need to dynamically add fragments to a fragment that HAS NOT already been inflated and added to the hierarchy. Adding a fragment to a fragment that HAS already been inflated and added to the hierarchy is as simple as just specifying the target fragments container that you want to add to by ID like you would normally.
As the documentation states "A fragment must always be embedded in an activity".
So when you add a "sub-fragment" it will always belong to the activity even if you add it within your fragment class. For example if you later decide to remove the containing fragment the sub fragments won't be automatically removed.
When I had to do the same I had to store in a vector the sub fragments and manually remove them in the onDestroy methods of my container fragment.
I think that fragments are not thought to be used like this
You cannot insert Fragments into other Fragments. (At least, not yet)
You can however replace Fragments with other Fragments with FragmentTransaction.replace(containerViewId, Fragment).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.linear1, new activity()).commit();
}