Interacting with hidden fragment - Android - android

I'm adding fragments to my activity in way that I first hide current fragment and then add new one. My problem is that when I show my new fragment and start interacting with him, it also interacts with previous one.
The code which I use to add new and hide current fragment is:
public void add(int containerViewId, Fragment fragment, boolean addToBackStack){
FragmentTransaction ft = fragmentManager.beginTransaction().hide(currentFragment).add(containerViewId, fragment);
if (addToBackStack){
ft.addToBackStack(null);
}
ft.commit();
currentFragment = fragment;
backStackCount++;
}
What is going on, and how to hide fragment so I can interact only with the last one added? replace is not an option because I don't want to remove current fragment.

I also had similar problem. I don't know what possibly is creating this issue but what I did to resolve it is that I set an onclick listener to the outermost layout of my fragment.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/top_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:clickable="false"
android:orientation="vertical"
tools:context=".Fragments.TopicsFragment">
...other components
</LinearLayout>
In fragment:
LinearLayout topLayout = (LinearLayout) fragmentView.findViewById(R.id.top_layout);
topLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do nothing
}
});
Also you might see I have added a background #FFFFFF to this outermost layout, because in mycase the content of previous fragment was also visible behind the new one. So this solved that problem too.

Related

Change the view in the Android Studio

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;
}
}
});

Call a Fragment from an Activity (from OnClickListener)

I have a button inside my Activity and when I click on this button I want to call a Fragment.
For example if I want to call an Activity I can use the intent but if I want to call a Fragment, how can I do that?
I have checked other questions but I have not found an answer to what I'm asking.
btnHome.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
What am I going to put inside this?
You can add your fragment dynamically.You want to create a fragment.
To programmatically add or remove a Fragment, you will need the FragmentManager and FragmentTransaction
XML Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/myFrame" <!-- Id which you're gonna use in Java -->
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me" />
</LinearLayout>
Java
btnHome.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager = getFragmentManager ();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction ();
MyFragment myfragment = new MyFragment(); //your fragment
// work here to add, remove, etc
fragmentTransaction.add (R.id.myFrame, myfragment);
fragmentTransaction.commit ();
}
});
See this doc
You cannot open new fragments. Fragments need to be always hosted by an activity. If the fragment is in the same activity (eg tabs) then the back key navigation is going to be tricky I am assuming that you want to open a new screen with that fragment.
So you would simply create a new activity and put the new fragment in there. That activity would then react to the intent either explicitly via the activity class or implicitly via intent filters.
The answer to your problem is easy: replace the current Fragment with the new Fragment and push transaction onto the backstack. This preserves back button behaviour...
Creating a new Activity really defeats the whole purpose to use fragments anyway...very counter productive.
#Override
public void onClick(View v) {
// Create new fragment and transaction
Fragment newFragment = new chartsFragment();
// consider using Java coding conventions (upper first char class names!!!)
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
https://developer.android.com/guide/components/fragments.html#Transactions
Quotation

Android fragments cant hide

I have an app in which I swap two fragments. The fragments are in a LinearLayout. Below the linearlayout I have icons (ImageViews) that when clicked hides or shows the appropriate fragment. When the app first loads, everything is fine. After I exit my app and use another app then return to my app the fragments dont hide/show when I click the icons (ImageView). WHy is this happening? Does it have something to do with the activity life cycles?
xml_layout:
<LinearLayout
android:id="#+id/Linearlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</LinearLayout>
onCreate()
{
ft = this.getSupportFragmentManager()
.beginTransaction();
frag1= new Frag1();
frag2= new Frag2();
ft.add(R.id.linearlayout,frag1);
ft.add(R.id.linearlayout, frag2);
ft.hide(frag1).show(frag2);
ft.commit();
icon1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ftt = MainActivity.this.getSupportFragmentManager()
.beginTransaction();
ftt.hide(frag2).show(frag1);
ftt.commit();
}
});
}
I think your problem is in this line:
ft.hide(frag2).show(frag2);
You want to hide frag1 and show frag2:
ft.hide(frag1).show(frag2);
Yes, the answer relates to the activity cycle. You need to override onCreateView and put your onClickListener inside of that. The onCreate is only getting called when the activity is first created. OnCreateView is called immediately after that, but it is also called when your activity is brought back to the front after you return from another activity.

How to replace Fragments of different types?

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.

No view found for ID xxx for fragment (nested fragments)

I have an activity that has a ViewPager in the layout.
I have two fragments which display, one for each tab.
One of the fragments is designed to host other fragments - this is the CustomerMainFragment which inflates fragment_customer_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lyt_customer_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragment_customer_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
This then adds CustomerSearchFragment to the FrameLayout which inflates fragment_customer_search.
CustomerSearchFragment also has the following override to switch out the search fragment for a detail fragment on a button press:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button btnSearch1 = (Button) view.findViewById(R.id.button1);
if (btnSearch1 != null) {
btnSearch1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// This is important bit
Fragment customerDetailFragment = new CustomerDetailFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.fragment_customer_content, customerDetailFragment).commit();
}
});
}
}
After clicking the button I get the following error:
java.lang.IllegalArgumentException: No view found for id 0x7f080006
(com.chrisbeckyapps.sample:id/fragment_customer_content) for fragment
CustomerDetailFragment{4280b0b8 #0 id=0x7f080006}
I'm new to fragments and understand the concepts, but I'm stumped by this. I originally had the search fragment going straight into the pager, but then replacing it with the detail fragment mean it just showed over the top, and my research led to this being a better solution.
I have wondered about trying to move the search logic to the CustomerMainFragment but this means hooking up a lot of logic and I thought you could embed logic within fragments.
Suggestions?
Sorry, just found such a simple fix.
In my onclick handler, I just had to change from getChildFragmentManager to getFragmentManager

Categories

Resources