I have a problem and I am stuck as to how to implement the following structure:
class A extends FragmentActivity{
//In this I click a button which loads a fragment say class B
}
class B extends Fragment implments Interface{
//This has a button which opens up an activity of list view say class C
function replaceFragment(){
try{
FragmentManager fm = B.this.getFragmentManager();
fm.beginTransaction().replace(R.id.main_frame, new D()).commit();
}catch(Exception e){
Log.v("error",""+e.getMessage());
}
}
}
class C extends Activity{
//It has an async task which loads something when the list view is clicked
//The async task onPostExecute calls back the class B interface function
onPostExecute(){
callback.replaceFragment();
}
}
Now when the interface function is called I want to replace the fragment B with another fragment say D which has its own layout. Can anyone help me in giving this suggestion or the solution to the problem I am having?
Another method I thought was instead of calling the callback function I would start class A all over again and changing the fragment to D when it gets loaded, but then the previous class A wasn't removed off the stack and when I press back I get the class A fragment activity again and this is causing a problem. Need a solution as I am stuck badly in this.
When interface function is called, you can replace the existing Fragment with Fragment D as follows
Fragment d = new D();
fragmentManager.beginTransaction().replace(R.id.frame_container, d).commit();
R.id.frame_container1 is the ID of the FrameLayout where you add/replace youre fragments
You can try calling replace in your interface call back. I think this should work well.
Related
I have implemented fragment in viewpager and Fragment has some buttons. Also viewpager is in activity_main layout.
I want that when button is clicked then it implement a method which is mentioned in mainActivity.java.
How can I do this?
I am a beginner.
You can get MainActivity method from fragment like below.
Make sure your methid is public if MainActivity and ViewPager are not in same package.
((MainActivity) getActivity()).getMethodOfMain();
You can call getActivity Method from your fragment and cast it to the your respective Activity.
lets take an example : You Have MainActivity class
MainActivity {
public void check() {}
}
And you have fragment : MainFragment
MainFragment{
Activity mainActivity = (MainActivity) getActivity();
mainActivity.check();
}
Thats how you can call the Respective Activity Method.
Problem in short:
I have an MainActivity that holds BottomNavigationView and FrameLayout on top of it. BottomNavigationView has 5 tabs and when tab is clicked, I add some fragment on that FrameLayout. But, from some fragment, I need to open another fragment. From that another fragment, I need to open the other one. Every time when I need to show fragment, I notify MainActivity from fragment, that it needs to add the another one. Every fragment checks does its activity implement interface. And it is annoying. So, if I have 100 fragments, MainActivity implements too many interfaces. It leads to boilerplate code. So, how to properly navigate between fragments if you have a lot?
Problem in detail:
Please, read problem in short section first.
As I've said I have BottomNavigationView that has 5 tabs. Let's call the fragments that responsible for each tab as FragmentA, FragmentB, FragmentC, FragmentD, FragmentE. I really know, how to show these fragments when tab is clicked. I just replace/add these fragments in activity. But, wait, what if you wanna go from FragmentA to FragmentF? After that from FragmentF to FragmentG? This is how I handle this problem: from FragmentF or FragmentG I notify MainActivity that I wanna change the fragment. But how they communicate with MainActivity? For this, I have interfaces inside of each fragment. MainActivity implements those interfaces. And here is problem. MainActivity implements too many interfaces that leads to boilerplate code. So, what is the best way to navigate through Fragments? I don't even touch that I also need to handle back button presses :)
Here is how my code looks like:
MainActivity implementing interfaces to change fragments if necessary:
class MainActivity : AppCompatActivity(), DashboardFragment.OnFragmentInteractionListener,
PaymentFragment.BigCategoryChosenListener, PaymentSubcategoryFragment.ItemClickedListener, PayServiceFragment.OnPayServiceListener, ContactListFragment.ContactTapListener, P2PFragment.P2PNotifier
Here is my PaymentFragment's onAttach method for example:
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof BigCategoryChosenListener) {
listener = (BigCategoryChosenListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement BigCategoryChosenListener");
}
}
And using this listener I notify activity to change fragment. And in EACH fragment I should do so. I don't think that it is best practice. So, is it ok or there is a better way?
Ok What you need is something like this in activity where you would initialized on your BottomNavigationView.
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_1://Handle menu click -
//Call Navigator helper to replace Fragment to Fragment A
break;
case R.id.menu_2:
//Call Navigator helper to replace Fragment to Fragment B
break;
case R.id.menu_3:
//Call Navigator helper to replace Fragment to Fragment C
break;
}
return true;
}
});
So i have a working solution, it seems not to be ideal but just need to confirm - so i have an activity with 3 fragments showing one at a time - i need to block the default back operation for two of those fragments so that when the back button is pressed nothing happens(for now, still developing).
So what i did was that i used an interface
//top of activity snippet
public class StudyKitActivity extends AppCompatActivity implements OnStudyKitBackListener{
private int fragment_id;
.
.
.
.
//interface method
#Override
public void onBackChanged(int fragment_id) {
this.fragment_id = fragment_id;
}
to set a variable on the activity
when i am changing the current fragment in the activity e.g set 1 for fragment A, 2 for fragment B and 3 for fragment C, so this is code snippet within fragment 2 when moving to fragment 3 -
onStudyKitBackListener.onBackChanged(3);
StudyKitResultFragment studyKitResultFragment = StudyKitResultFragment.getInstance(examResult);
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, studyKitResultFragment).addToBackStack("exam_result").commit();
and i did an overwrite in my activity's onBackpressed to check the value of that variable and either execute the default OnBackPressed or do nothing like so -
#Override
public void onBackPressed() {
if(this.fragment_id==2||this.fragment_id==3){
}
else{
super.onBackPressed();
}
}
i came up with this cos other solutions like setting a tag and trying to get the fragment's tag or by checking current fragments id did not work for me, this is working like i expected but i have not seen it anywhere just want to know if there is an alternate solution.
I'm trying to call this function public void arrowClick()
is inside my main fragment public class CounterMain extends Fragment implements View.OnClickListener{
the fragment is extend android.support.v4.app.Fragment
I want to call this function from another Custmoe Dialog fragment
public class CustmoeDialog extends DialogFragment {
I tried ((CounterMain)getActivity()).arrowClick();
but I can't use it it says android.support.v4.app.Fragment cannot be cast to my.example.CounterMain
and the
CounterMain x = new CounterMain(); x.arrowClick();
it makes my app to stop working when I call it
any help?
You can call activity method by this way
((YourActivityClassName)getActivity()).yourPublicMethod();
and from activity you can directly call by this way
FragmentManager fm = getSupportFragmentManager();//if added by xml
YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentById(R.id.your_fragment_id);
fragment.yourPublicMethod();
if you added fragment via code and used a tag string when you added your fragment, use findFragmentByTag instead:
YourFragmentClass fragment = (YourFragmentClass)fm.findFragmentByTag("yourTag");
First of all, you can not cast from ACTIVITY to FRAGMENT
But to cast from GLOBAL ACTIVITY to your ACTIVITY
Or create INTERFACE and implement it in ACTIVITY
Then cast it in FRAGMENT from ACTIVITY to INTERFACE
And on the question:
See here the right way how to implement
Basic communication between two fragments
The main fragment activity in my application has the following function
private final void insertFragmentIntoView(final SherlockFragment fragment,
String tag) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_content, fragment, tag);
ft.commit();
}
The R.id.fragment_content is a frame layout and i basically insert a new fragment into this frame. Now the frame that i insert has a button that should take me onto a new screen. What i want is that all navaigation in my application should take place in my FragmentActivity. How can i call my FragmentActivity from with a child fragment ?
Kind Regards
Make a listener class in your fragment and your parent activity will implement that listener .
Now register listener in your fragment and call method in which you want to perform some action.
More you can see this link http://developer.android.com/training/basics/fragments/communicating.html
Example how fragment and activity communicate.
class MyFragment extends Fragment{
class interface MyFragmentListener {
doSomeAction();
}
MyFragmentListener myListener;
onAttach(){
myListener=(MainActivity )getActivity();
}
onButtonClick(){
myListener.doSomeAction();
}
}
class MainActivity extends FragmentActivity implements MyFragment.MyFragmentListener
{
doSomeAction(){
//TODO perform some action from your fragment to activity
}
}
Using listeners is the recommended way of communicating between Fragment and your activity.
See this Android documentation section for infromation. Long story short they just implement a listener interface by the Activity class and cast getActivity() result in a fragment to a listener.
From my personal experience this is very convenient because lets you to:
Easilly switch underlying activity (e.g. you host entire fragment in a wrapper activity for compatibility in pre-3.0 and host this fragment along with others in 11+)
Easilly control if the wrapper activity supports callbacks or not. Just check is it does implement the listener and do your app specific actions if it doesn't.