Interface from one fragment to another android - android

I am facing a problem implementing an interface defined in one fragment and using it to another. I know I need to do this through activity but I have added fragments dynamically inside another fragment. Please look at the snapshot to understand more about my problem.
. I have a fragment called ACTIVITY fragment inside which I load fragments dynamically. The Comments textview is clickable and when clicked it a CommentDialogFragment is shown. This dialog fragment is shared by all the fragments. Code when comment clicked:
FragmentTransaction ft = getActivity()
.getSupportFragmentManager().beginTransaction();
CommentDialog fragment = CommentDialog.newInstance(id,
"Activity");
ft.addToBackStack(null);
fragment.show(ft, null);
I want to increment the comment count. For that I made an interface:
public interface IncrementComment {
public void increaseCommentCount(boolean increase);
}
I am unable to use this interface in my fragment inside the ACTIVITY fragment. The interface is detected on the Activity that holds all these fragments. Heres the interface in my MainActivity class I get the data upto this point:
#Override
public void increaseCommentCount(boolean increase) {
// TODO Auto-generated method stub
Log.d("interface main activity", "called");//this is called
}
Now I am unable to pass data from this activity code to my fragment because the fragments are loaded dynamically and there can be any number of fragments(user can see their old post).
So I tried to make a fragment implement the interface to update the value of the textview. But I couldnot get it working as it is never called. Can someone point me in the correct direction. I tried most of the links in SO like this and from other sources like this but none of them fit my requirement.

Related

Simple way to replace and send data to a fragment

I simply want to replace a fragment from the current fragment and add a new one.
I have studied that Replace is Equal to removeCurrent + Add anotherFragment
But in my situation i am facing a Problem. For the first two times it is running properly but after third attempt instead of replacing . it ads the fragment on me.
My approach fails now. Now i am asking that how can i send an id to other fragment like we do in Activities. I have a listView with a ReadMore button. I simply want to show the details in another fragment and want to send the index of a List.
I listen about some Interface but don't know how to implement . or there an easy way for communication. I tried doing it by passing it in Constructor . but it will give me an error . because
how to get currentFragment and hide it?
how to add onBackPressed to fragment.
how to send data between fragments The easy way.
i know how to hide or show a fragment
getFragmentManager().beginTransaction().hide(frag[j]).commit();
getFragmentManager().beginTransaction().show(frag[0]).commit();
also know how to add or replace a fragment
getFragmentManager().beginTransaction().add(R.id.container, frag[i])
//.addToBackStack(null)
.commit();
getFragmentManager().beginTransaction().replace(R.id.container, frag[i])
//.addToBackStack(null)
.commit();
Tell me a better approach to send data and why my layout add instead of replacing.
I recommend using EventBus for Activity/Fragment/Service or any other communication.
There is a good one from Square: http://square.github.io/otto/
Or this one (also very good): https://github.com/greenrobot/EventBus
It makes it simplier and your code gets cleaner.
It is pretty easy to send data to fragment with constructor.
In your fragment class, add constructor like this:
public class MyFragment extends Fragment{
String id;
public MyFragment(String id)
this.id = id;
}
Then, when calling a fragment,you can easily send data like this :
getSupportFragmentManager().beginTransaction().replace(android.r.id.container,new MyFragment("123")).commit();
You can't override onBackPressed within fragment, you can only do that in activity
You can set try set the variables in the fragment as public static then you can declare them before you instantiate your fragment to be shown.
in your onDestroy method of the fragment you can set the variables = null, so they dont take space in memory.
could be smth like this
MyFragment.theString = "A String";
getSupportFragmentManager().beginTransaction().replace(android.r.id.container,new MyFragment()).commit();
And in your fragment
public static String theString;
...
public void onDestroy(){
super.onDestroy();
theString = null;
}

ViewPager with Fragment reload at first and last page

I'm trying to create a ViewPager with six fragments but only 2nd fragment to 5th fragment contain data that I want to show and the first fragment and the last fragment I want to be used to reload the data and set the position to the 2nd fragment again. The overall flow is like this :
1st (reload and go back to 2nd) <- 2nd fragment <-> 5th fragment -> 6th fragment (same with 1st)
what I've tried is I create a callback from the 1st fragment and 6th fragment like this
public static class callbackFragmentLoading implements callbackFragmentLoad {
#Override
public void onLoading() {
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(2,false);
}
}
and I passed the callback to the fragment constructor so I can called the onLoading function in the onActivityCreated. But I everytime I do it the application will be force closed and the logcat shows
recursive entry to executependingtransactions
is there any way to do this? or my method for doing it is wrong?
Thank You
is there any way to do this? or my method for doing it is wrong?
Messing with callbacks between Fragments of a ViewPager isn't probably such a good idea. Instead I would do it like this:
Don't load any data(like with a Loader) in the Fragments from the ViewPager, instead let the FragmentActivity do it(and the Fragments will get it through methods from the Activity).
Your two loading fragments(position 0 and 5) will call in their onResume method a reload action on the parent Activity(like a Loader restart)
At this moment the Activity will load/reload the data and when that finishes it will set the ViewPager to the correct items(either 1 or 4)
in the onResume method of the data fragments you'll refresh the fragment's data(here you may need to use some sort of signaling system because you'll need to duplicate the refresh code in the onCreateView(some fragments may have their view destroyed if they are far apart from the current visible position)).
As I don't know many things about the inner data fragment I've written a basic skeleton sample(without the data loading in the activity).

How to make call backs between Fragments of the same Ativity

I have 4 tabs in an Activity.
Each of them is a Fragment. And every Fragment has a ListView.
So, if i change the ListView in Fragment, it must change the ListView in all other Fragments ie.., Tabs.
The problem i face is while creating the interface instance.
It takes it's own onClick() method.
In case i want a callback to the parent activity i could have done that by overriding onAttach. But how to make a callback to a Fragment?
From Developers site:
Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
So, make a callback to the Activity which in turn makes a callback to other fragments??
Thank You
It's pretty simple,all You need is steps below:
1) From onClick method in your first fragment make a function call of activity:
((IYourActivityInterface) getActivty()).activityMethod();
2) In your activity find fragment by tag or id and run it's method:
public void activityMethod(){
Fragment tabFragment = getFragmentManager().findFragmentByTag("second_fragment");
// or Fragment tabFragment = getFragmentManager().findFragmentById(R.id.frag);
if (tabFragment!=null){
((IFragmentInterface) tabFragment).fragmentMethod();
}
}
Hope this is what you are looking for.)

Switch current fragment on item click

I am trying to write a file manager for android as an university project. My idea is to use fragments in it to create a tabbed vew for it with a viewpager. Practically, the first view you get when you load the app is a path selection fragment, where you have sdcard, music, etc. That fragment contains a listview of said folders. When I click on an item, i want another fragment to be added to the pager, and that works fine. But I also want the current fragment to be replaced with a grid view of the "clicked" folder. That doesn't work. I use an arraylist of File[] to store files in each folder i selected. I also added methods inside the fragment adapter to add and replace fragments in my fragment arraylist. Tried with transaction and with my list, the list is correctly updated but the view is not. The following code is the method inside my fragment adapter to replace a fragment. It is called inside an onItemclicklistenr set to my listview:
public void replaceFragment(SherlockFragment newFragment, int pos) {
SherlockFragment old=fragments.get(pos);
fragments.set(pos, newFragment);
notifyDataSetChanged();
}
I read several answers about this issue, tried almost everything, nothing seems to work. Any help would be apreciated.
I found an horrible solution. After updating the fragment list (without fragmenttransaction) I re-set the adapter for the view pager and restore the current Item. This way I force the fragments layouts to be built. Not beautiful, but whatever. This is the interface that gets called onclick:
#Override
public void onPathSelected(int position) {
// TODO Auto-generated method stub
Log.d("positioninsideintfc", Integer.toString(position));
firstrun.add(true);
int current=mPager.getCurrentItem();
root=(File) filepaths.get(position);
fragmentfilelists.add(root.listFiles());
initpath=MainActivity.root.getAbsolutePath();
Gridfragment newfrag=Gridfragment.newInstance(current);
mAdapter.addFragment(Selectpathfragment.newInstance(current+1));
mAdapter.replaceFragment(newfrag, current);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(current);
}
You should learn your Activity to speak the language your frament use. In general your Activity should implement Interface which then your fragments will use for communication. So in your case, when user tap the list item, the fragment with listview shall tell its parent Actity (using said interface) something like "user clicked on this". And your parent activity should do the rest, replacing/adding fragments. Your fragment, like in OOP, shall be not aware of existence of other fragments.

android fragments in different tabs

I'm building an app that the interface is based on this http://code.google.com/p/android-playground/, and I need to have a fragment inside of each tab (that are fragments). The tabs are all inflated from the same xml, and in that xml I have a fragment tag.
The problem is that when the activity is created, as the id of each fragment in the tabs are equal, the contents that should go to the second tab, go in the first.
I'm using this code to replace the fragment in the tab
FragmentTransaction ft = x.getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
I don't know if is possible to correct this.
do you want all the tabs to have the exactly the same content?
Usually when putting fragments in tabs each tab would be showing differnt content, so a xml file per tab would not be uncommon. You can have a seperate xml layout for each tab that just declares your fragment with a different id each time. Without declaring a seperate (read unique) id for each fragment there is no efficent / simple operation i know to get a handle to a specific fragment (as the id is the unique handle).
You also may be able to use a FragmentPagerAdapter depending on your needs. You could then fade your current tab fragment out, then call public void notifyDataSetChanged () and provide a new fragment. This is not really the standard way of doing it though and will not be preserved on the back stack.
Optionally you could create each tab programatically in the PagerAdapter and set a tag for each fragment when calling FragmentTransaction.add(..) and then use this tab-unique tag in future fragment transactions Ignore this, it does not look like you can switch fragements with a tag, id only im afraid. Go with my first suggestion I would!
I've struggled with ths as well and the way I reference a Fragment from its Activity later on is by accessing the Adapter for the tabs.
Assuming you use an Adapter, you could do something like this
private mTabsAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// etc
this.mTabsAdapter = new TabsAdapter(this, this.mViewPager);
// Tab1
Tab tab = actionBar.newTab();
this.mTabsAdapter.addTab(tab, MyFragment1.class, null);
// Tab2
tab = actionBar.newTab();
this.mTabsAdapter.addTab(tab, MyFragment2.class, null);
}
public MyFragment1 getTab1() {
return (MyFragment1)this.mTabsAdapter.getItem(0);
}
public MyFragment2 getTab2() {
return (MyFragment2)this.mTabsAdapter.getItem(1);
}
Then inside your fragment, you would have a method to access
public class MyFragment1 {
// ...
public void reloadData() {
// reload data here
}
}
Now you can access the Fragment such as
this.getTab1.reloadData();
This feels like a sad way to access a fragment, but you can't rely on a Tag in every scenario. Also, you must take care to only reference this where the reference to the Fragment exists.
There may be times that this will be null. For example if you nave a bunch of tabs, they may become garbage collected at some point. you should communicate between Fragments via a callback. This example is for only a few scenarios.
The callback method is described at Communicating with the Activity and I'd suggest this method if it fits your application. This will prevent the need for directly accessing tabs in most cases.

Categories

Resources