I'm creating a view pager in my app and using a class that extends Fragment on it. When I create an instance I can pass all the elements (an image, text, etc) and store it with the Bundle to use it in the onCreate. But I can't store a listener for the button in the fragment. Here is my class:
public class RegWizardFragmentInfo extends Fragment {
private static final String IMAGE = "image";
private static final String TEXT = "text";
private static final String BUTTON = "buttonText";
private View.OnClickListener buttonCallBack;
private Button button;
private int image;
private int text;
private int buttonText;
public RegWizardFragmentInfo newInstance(int image, int text, int buttonText, View.OnClickListener callback) {
RegWizardFragmentInfo fragment = new RegWizardFragmentInfo();
Bundle bundle = new Bundle();
bundle.putInt(IMAGE, image);
bundle.putInt(BUTTON, buttonText);
bundle.putInt(TEXT, text);
fragment.setArguments(bundle);
fragment.setRetainInstance(true);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.onActivityCreated(savedInstanceState);
this.image = getArguments().getInt(IMAGE);
this.text = (getArguments() != null) ? getArguments().getInt(TEXT)
: -1;
this.buttonText = (getArguments() != null) ? getArguments().getInt(BUTTON)
: -1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.fragment, container, false);
//Extract all the views and add the image and texts
return rootView;
}
So, how can I store the listener that I get in the newInstance to add it to the button on the onCreateView method?
Thanks for the help.
You can use a callback in your Fragment
:
public class RegWizardFragmentInfo extends Fragment {
private Button button;
private OnClickCallback callback;
public interface OnClickCallback {
void onClick();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
callback = (OnClickCallback) context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onClick();
}
});
}
}
and implement this new interface in your parent Activity
The other answers assign the listener in onAttach
. While this will work, it requires that the calling Activity
(and not, say, an anonymous class) implement your interface. Moreover, it forces you to cast the Context
given to you in onAttach
to an instance of your interface, which can cause crashes and is generally considered bad form. You might instead create a method to set the listener inside your Fragment
:
public class RegWizardFragmentInfo extends Fragment {
private OnClickListener mListener;
public interface OnClickListener {
void onClick();
}
/**
* Call at any time after this fragment has been constructed.
*/
public void setListener(OnClickListener listener) {
mListener = listener;
}
/* ...other stuff... */
}
I can think of three disadvantages to this approach:
Fragment
.mListener
is set at any time. You may need to pepper your Fragment
code with null checks.I suppose you want to re-use the Fragment
with various different listeners. So your approach is not ideal since you can not use the Bundle
for that. A better approach would be to use the callback design pattern e.g.
public class RegWizardFragmentInfo extends Fragment {
public interface RegWizardCallback {
void onClick();
}
}
Your Activity
would implement that interface. Since a Fragment
only lives inside an Activity you can get the callback instance from it by using the lifecycle method onAttach()
. It would look like this
public class RegWizardFragmentInfo extends Fragment {
private RegWizardCallback callback;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
callback = (RegWizardCallback) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement RegWizardCallback ");
}
}
public interface RegWizardCallback {
void onClick();
}
}
With that you can simply call callback.onClick
inside the listener of the Button.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With