Android DialogFragment started inside a Fragment - android

I have a few fragments, and in one of them I have to ask the user to select time, so from the fragment I open up a DialogFragment with TimePicker and Button, so I want when the button is clicked to update the view in the Fragment which opened the dialog, how can I do that?

public interface DialogListener {
public void onDialogEnded(Bundle bundle);
}
in the Parent Fragment listen to this DialogListener.
in the Dialog fragment call the DialogListener with null or any kind of bundle with data this will call the listener in the parent Fragment with what you need.
in the DialogFragment create a setup Listener example :
private DialogListener mListener;
public void setListener(DialogListener listener) { mListener = listner; }
when you call the Dialog call the Listener before.

The easiest way is to replace the fragment calling your context, like this:
public void replaceFrag(){
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, new YourNewFragment());
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
Call this method in your button's onClick() event
this assmumes, that your fragment was programmatically commited into a fragment_container xml tag, which you might need to adapt accordingly.

Related

DialogFragment doesn't show up in the listener

I know there is one question with same title, but my scenario is a bit complex. In FragmentA, once click the button will start a new activity to show FragmentB, if then click one button in FragmentB, i need to dismiss FragmentB and go back to FragmentA and show DialogFragmentC. What i do is define one listener in FragmentB and implement it in FragmentA.
The sample snippet is as below:
class FragmentA extends Fragment implements FragmentBDelegate {
.......
#Override
public void onButtonClicked() {
DialogFragment popup = new DialogFragmentC();
popup.show(((AppCompatActivity)getContext()).getSupportFragmentManager(), null);
}
......
}
class FragmentB extends Fragment{
......
private void onButtonClicked(View v) {
getActivity().finish();// to dismiss current activity
if(mListener != null) {
mListener.onButtonClicked();
}
}
public interface FragmentBDelegate {
void onButtonClicked();
}
......
}
Why the DialogFragment doesn't show up? If listener cannot implement this requirement, how to implement?
#ADM's comment guide me to one workaround. I define one showWithStateLoss() method with commitAllowingStateLoss() to commit the FragmentTransaction in DialogFragmentC. Then it works.
public void showWithStateLoss(FragmentManager manager, String tag) {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss(); //original it's commit()
}
You should not (maybe you can, but should not) use callback method between different activities.
If this is exactly what you need to do, you need to start 2nd activity for result with startActivityForResult(). Then decide if you want to show dialog based on 2nd activity result. FragmentB will set result rather than trying to call 1st activity's callback.

Sending data from activity to fragment with interface listener

I'm trying to send data from an activity to a fragment. I'm not sending data from a fragment to an activity. I've got everything set up correctly other than instantiating the interface listener object in the activity.
public class Activity extends AppCompatActivity {
private FragmentInterface fragmentInterfaceListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This line below is actually in a button onClick()
fragmentInterfaceListener.sendDataMethod(dataToSend);
}
public interface FragmentInterface {
void sendDataMethod(SampleData sampleData);
}
}
Then in the fragment, I have:
public static class CustomFragment extends Fragment implements Activity.FragmentInterface {
#Override
public void sendDataMethod(final SampleData sampleData) {
}
}
When I put a log line in the button onClick(), the log line appears when the button is clicked. No, I'm not going to put the sampleData in a fragment bundle. Yes, I need to send the data through an interface. So how do I correctly instantiate the fragmentInterfaceListener object in the Activity? Am I missing anything else in the Activity or CustomFragment?
What your are missing here is the registering part.
The fragment has to register itself with the activity listener for the activity to send data when an event occurs.To do this create a method in activity
private void setOnDataListener(FragmentInterface interface){
fragmentInterfaceListener=interface;
}
And in the oncreate of your fragment set the listener like this
((YOUR_ACTIVITY_NAME)getActivity()).setOnDataListener(this);
You don't need to use listener in the Fragment because you can directly communicate with the Fragment from its host Activity.
As #lq-gioan says, you can create a public method in your Fragment then call it from your activity. So, create a public method to set the data, something like this:
public static class CustomFragment extends Fragment {
// public method to be accessed by host activity.
public void sendDataMethod(final SampleData sampleData) {
}
}
Then you can call the method within your host activity:
CustomFragment fragment = (CustomFragment)getSupportFragmentManager()
.findFragmentById(R.id.fragment_id);
// or use find by tag if you adding the fragment by tag
// CustomFragment fragment = (CustomFragment)getSupportFragmentManager()
// .findFragmentByTag("FragmentTag");
// now you can call it
fragment.sendDataMethod(yourSampleData);
For sending data from Activity to Fragment we don't need an interface.
You can directly call the method in Fragment or pass as setArguments in Bundle
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
if (articleFrag != null) {
// If article frag is available, we're in two-pane layout...
// Call a method in the ArticleFragment to update its content
articleFrag.updateArticleView(position);
} else {
// Otherwise, we're in the one-pane layout and must swap frags...
// Create fragment and give it an argument for the selected article
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
You can refer https://developer.android.com/training/basics/fragments/communicating.html

Call Fragment B from Fragment A using ViewPager Tabs

I have done many programs, where I have implemented multiple Fragments inside a Single Activity, but not when using Single Activity to host multiple Fragments as Tabs and then on Tap show another Fragments...
Using MaterialViewPager library, in which I am calling different different Fragments to show views in their respective Tabs.
Like For the First Tab, I am using two Fragments, where
In First Fragment, I am using RecyclerView... to show list of Menus.
And in Second Fragment, I am using RecyclerView... to show list of Items under particular Menu.
So here my question is How to call Fragment from Fragment.
mRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), mRecyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Value value = valueList.get(position);
List<Learning> learning = value.getLearning();
// using when putting "item" data into same recyclerview
// but on back press just exiting, not showing list of Menus again
/**
learningAdapter = new LearningAdapter(learning, R.layout.card_learning, getActivity());
mRecyclerView.setAdapter(learningAdapter);
**/
ItemFragment fragment = new ItemFragment();
replaceFragment(fragment);
}
Method replaceFragment
public void replaceFragment(Fragment someFragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// using Fragment not Activity, so where can I use frame_container in xml
transaction.replace(R.id.frame_container, someFragment);
transaction.addToBackStack(null);
transaction.commit();
}
you can have a callback interface that is implemented by the activity which hosts these two fragments. Fragment A will use the call back to notify the activity to replace A with fragment B. Depending on your need, you can pass parameters across through the callback method itself.
Your callback interface:
public interface YourCallback {
public void methodWhichReplacesFragmentAwithB(params...);
}
Your Activity hosting fragments:
public class YourActivity extends ... implements YourCallback {
..
..
#Override
public void methodWhichReplacesFragmentAwithB(params...) {
//insert replace fragment code here
}
}
Your fragment will have a callback object, YourCallback callbackObj;. This callback object can be initialised using the activity (pass as this from activity) itself since the activity has the implementation of the interface. Now, you can use
callbackObj.methodWhichReplacesFragmentAwithB(actual_params...);
to replace the fragment. This callback interface can be exploited for other communications to parent Activity as well as other fragment hosted in that activity.
To replace fragment,
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, someFragment).addToBackStack("null").commit();
You can try this:
YourFragment fragment = new YourFragment();
FragmentTransaction transaction = ((AppCompatActivity) mContext).getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
There is One option which i have been using from long time before. I will added the solution with clear example.
So you want to pass the value from fragment A to fragment B
So, here what you want to do is, you have pass the value through the activity.
1) you pass the value from fragment A to activity
2) then activity to fragment B
Step 1: first create an Interface Like below in fragment A
public interface HomePage {
void onHomeButtonsClicked(String clickedButton);
}
public void setOnHomeButtonClicked(HomePage homePage) {
this.homePage = homePage;
}
Step 2: then create the instance like below in Activity. where fragment created in PagerAdapter
((FragmentA) fragment).setOnHomeButtonClicked(new FragmentA.HomePage() {
#Override
public void onHomeButtonsClicked(String buttonClicked) {
pageSelected.onHomeButtonsClicked(selectedPage);
}
}
});
Step 3: then create the interface in Activity like below.
public interface PageSelected {
void onHomeButtonsClicked(String clickedButton);
}
public void setOnHomeButtonClicked(PageSelected pageSelected) {
this.pageSelected = pageSelected;
}
step 3: then add the following method in fragment B in onCreateView or onResume()
((MainActivity) getActivity()).setOnHomeButtonClicked(new MainActivity.PageSelected() {
#Override
public void onHomeButtonsClicked(String clickedButton) {
//fragment B received the value here
}
});
Step 5: finally add the line in fragment A in button click or where you want to pass the value.
homePage.onHomeButtonsClicked("Some String , by this code it is in String. you can change in your own data type");
You can rise your question if you face any difficulties.

Different Instance of Fragment inside an Activity

We are going to write an app, in one section of app user enter to an Activity that call it PostDetailsActivity.
In this Activity we have a fragment call it PostDetailsFragment. We apply an Interface to communicate between this fragment and activity
public interface changeFragment{
void replaceFragment(Fragment fragment, String backStack);
}
In PostDetailsFragment we have post and it's related posts. related post listed in recyclerview bu an adapter. when user click on Item in adapter, adaoter act like this:
PostDetailsFragment fragment = PostDetailsFragment.newInstance(GsonString);
mListener.replaceFragment(fragment, fragment.getFragmentKey());
and in Activity we act like this:
#Override
public void replaceFragment(Fragment fragment, String backstackName) {
if(fragment instanceof PostDetailsFragment){
fragmentPostDetails = (PostDetailsFragment) fragment;
}
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(backstackName);
fragmentTransaction.commitAllowingStateLoss();
}
What we doing: we create one Activity and if user click on related posts, activity just replace fragment with new instance of PostDetailsFragment with new data.
Issue: after five or more and less, App crashed and got OoutOfMemory Error!
I attache MAT too
How we should manage this problem?

How to replace a Fragment on button click of that fragment?

I have an activity containing multiple fragments. Activity initially have fragment and in it have two buttons. Upon clicking this button I have to replace the fragment by new fragment. Each fragment has various widgets and replace the current fragment as various events.
This is my problem. How can I achieve this?
Suggest me ideas.
you can replace fragment by FragmentTransaction.
Here you go.
Make an interface.
public interface FragmentChangeListener
{
public void replaceFragment(Fragment fragment);
}
implements your Fragment holding activity with this interface.
public class HomeScreen extends FragmentActivity implements
FragmentChangeListener {
#Override
public void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();;
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(mContainerId, fragment, fragment.toString());
fragmentTransaction.addToBackStack(fragment.toString());
fragmentTransaction.commit();
}
}
Call this method from Fragments like this.
//In your fragment.
public void showOtherFragment()
{
Fragment fr=new NewDisplayingFragment();
FragmentChangeListener fc=(FragmentChangeListener)getActivity();
fc.replaceFragment(fr);
}
Hope this will work!
NOTE: mContainerId is id of the view who is holding the fragments inside.
You should override Fragment's onString() method as well.
Well even I am learning android...
I solved same problem recently, "How to Change Fragment On button's click event".
buttonName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = getActivity()
.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame1, new Homefragment());
fragmentTransaction.commit();
}
});
Here frame1 is id of FrameLayout which have define in my DrawerLayer's XML.
So now whenever I want fragment transaction I use this code. Each time it will replace frame1 instated of your last fragment.
FragmentTransaction fragmentTransaction = getActivity()
.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame1, new newfragment());
fragmentTransaction.commit()
Hope this will help..
You can use the following to replace a fragment on button click of that fragment:
getFragmentManager().beginTransaction().replace(R.id.main_content, new insertFragmentNameHere()).addToBackStack(null).commit();
Define an interface and call it IChangeListener (or something like that) and define a method inside which will do the work (ex, changeFragment()) (or call another method which will do the work) for changing the fragment).
Make your activity implement the interface, or make an anonymous class within the activity implement it.
Make a paramerized constructor of your fragment, which accepts a IChangeListener parameter.
When initializing the fragment, pass your IChangeListener implementation (the anonymous class or the activity, implementing it)
Make the onClick listener of the button call the changing method of the IChangeListener.
From the future 2017 and after, there exists different libraries that triggers Events using Bus and now you can use it to tell the activity when an event is trigger in a fragment that it owns.
Refer to:
RxBus with RxJava
You can check new architectures suggested by Google
ViewModel
Don't use the approach in the accepted answer, get really ugly with more than 3 different events from fragments
you can try this code it's work fine with me , inflate the layout to view , Define the buton and on click ,
Button btn_unstable;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home,container,false);
btn_unstable = (Button)view.findViewById(R.id.btn_unstable);
btn_unstable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_replace, new UnstableFragment()).commit();
}
});
return view;
}

Categories

Resources