I have two buttons in MainActivity, the first one opens a custom DialogFragment with some spinners and in the other button it resets the spinners of this DialogFragment.
When I click the reset button it calls this method that is in the DialogFragment:
public class FilterDialogFragment extends DialogFragment {
private View view;
// ...
#Nullable
#Override
public View onCreateView(#NotNull LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.dialog_filters, container, false);
// start the spinners and adapters here
return view;
}
public void resetFilters() {
if (view != null) {
categorySpinner.setSelection(0);
productSpinner.setSelection(0);
priceSpinner.setSelection(0);
}
}
// some more codes here
}
My MainActivity:
public class MainActivity extends AppCompatActivity {
private FilterDialogFragment filterDialog;
private Button button_clear;
private Button button_filter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_clear = findViewById(R.id.button_clear);
button_filter = findViewById(R.id.button_filter);
filterDialog = new FilterDialogFragment();
button_filter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Show the dialog containing filter options
filterDialog.show(getSupportFragmentManager(), FilterDialogFragment.TAG);
}
});
button_clear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//reset all filters
filterDialog.resetFilters();
}
});
//some more codes here
}
//some more methods here
}
But by clicking the button that opens the DialogFragment, the values of the Spinners remain the same instead of returning the data of position 0 of each spinner.
Would anyone know how to solve this? I've tried everything and I can not.
The simplest way I ended up finding, was to delete the resetFilters method, and instead I did so:
button_clear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//reset all filters
filterDialog = new FilterDialogFragment(); }
});
Related
I am using BottomSheetDialogFragment in my android app. I am using Java. I show the bottomsheet by:
ActionBottomDialogFragment dialogFragment = ActionBottomDialogFragment.newInstance();
showButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogFragment.show(getActivity().getSupportFragmentManager(), ActionBottomDialogFragment.TAG);
}
});
What I see is it calls onCreateDialog method and then calls onViewCreated methods. For the first time this is okay.
Now I hide the bottom sheet using:
ImageButton close = view.findViewById(R.id.closeButton);
close.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
Then when I press the show button again, it calls onCreateDialog method again. I have a dynamic list of choice chips which I want the state to be just as I left it. If I left it on checking 'Choice A', it should show up selected the next time I open the bottom sheet. I need the state to be maintained.
What is happening is it rebuilds the choice chips from start, so the state is lost.
How can I just show / hide the bottom sheet without recreating?
UI will be always created again when you call show(). It's better to use a sharedViewModel in bottomSheetFragment and the parent activity/fragment. You should save the fields being selected in the viewmodel and use it the bottomSheet. This way the state will be maintained.
You can use show() & hide() of the dialog itself; this will keep the fragment alive.
So, in your case:
To show it:
ActionBottomDialogFragment dialogFragment;
showButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (dialogFragment == null) {
dialogFragment = ActionBottomDialogFragment.newInstance();
dialogFragment.show(getActivity().getSupportFragmentManager(), ActionBottomDialogFragment.TAG);
} else {
dialogFragment.getDialog().show();
}
}
});
And to hide it:
ImageButton close = view.findViewById(R.id.closeButton);
close.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialogFragment.getDialog().hide();
}
});
But this requires to handle the side effects when dismissing the fragments using the back button and when touching outside.
Here's a custom DialogFragment that handles that:
public class BottomSheet extends BottomSheetDialogFragment {
public BottomSheet() {
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_layout, container, false);
return view;
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
return new BottomSheetDialog(requireContext(), getTheme()) {
#Override
public void onBackPressed() {
getDialog().hide();
}
};
]
}
#SuppressLint("ClickableViewAccessibility")
#Override
public void onStart() {
super.onStart();
setCancelable(false);
getDialog().setCanceledOnTouchOutside(false);
final View outsideView =
requireDialog().findViewById(com.google.android.material.R.id.touch_outside);
outsideView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP)
getDialog().hide();
return false;
});
}
}
I have a activity which prompts a dialog fragment. I want to call a method in the parent activity when the dialog fragment is dismissed. Here is the activity that contains the dialog fragment.
public class HomScr extends AppCompatActivity {
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.das_boa);
initialize();
}
private void initialize(){
tv = findViewById(R.id.tv);
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProEdiCon dia_fra = new ProEdiCon();
dia_fra.show((this).getSupportFragmentManager(), "pro_edi_con");
}
}
}
private void method_to_run_onDismiss(){
tv.setText("method to run is executed");
Toast.makeText(this, "method to run successfully executed on dismiss Dialog Fragment", Toast.LENGTH_SHORT).show();
}
}
And the below code is the DialogFragment which gets dismissed in certain point and after that the parent activity must call the method to run on dismiss.
public class ProEdiCon extends DialogFragment {
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle bun) {
View pro_vie = inflater.inflate(R.layout.pro_edi_dat, container, false);
TextView tv = pro_vie.findViewById(R.id.tv);
tv.setText("I am the Dialog Fragment who is gonna be dismissed soon");
Button btn = pro_vie.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
}
return pro_vie;
}
}
So can anybody help me do this?
You can use Dialog and set Dismiss listener and listen for the event when dialog will be dismissed
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProEdiCon dia_fra = new ProEdiCon();
dia_fra.show();
dia_fra.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
//do some action here
}
});
}
}
and your Dialog will be like this:
public class ProEdiCon extends Dialog {
public ProEdiCon (#NonNull Context context) {
super(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pro_edi_dat);
TextView tv = pro_vie.findViewById(R.id.tv);
tv.setText("I am the Dialog Fragment who is gonna be dismissed soon");
Button btn = pro_vie.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
}
}
You must create interface like this
CallBackListener.java
public interface CallBackListener {
void onDismiss();
}
Then in your fragment
public class ProEdiCon extends DialogFragment {
private CallBackListener callBackListener;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//getActivity() is fully created in onActivityCreated and instanceOf differentiate it between different Activities
if (getActivity() instanceof CallBackListener)
callBackListener = (CallBackListener) getActivity();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle bun) {
View pro_vie = inflater.inflate(R.layout.pro_edi_dat, container, false);
TextView tv = pro_vie.findViewById(R.id.tv);
tv.setText("I am the Dialog Fragment who is gonna be dismissed soon");
Button btn = pro_vie.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(callBackListener != null)
callBackListener.onDismiss();
dismiss();
}
}
return pro_vie;
}
}
And finally in your Activity
public class HomScr extends AppCompatActivity implements CallBackListener {
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.das_boa);
initialize();
}
private void initialize(){
tv = findViewById(R.id.tv);
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProEdiCon dia_fra = new ProEdiCon();
dia_fra.show((this).getSupportFragmentManager(), "pro_edi_con");
}
}
}
private void method_to_run_onDismiss(){
tv.setText("method to run is executed");
Toast.makeText(this, "method to run successfully executed on dismiss Dialog Fragment", Toast.LENGTH_SHORT).show();
}
#Override
public void onDismiss() {
method_to_run_onDismiss();
}
}
You might want to use a DialogListener interface inside your Dialog class and call it before the dialog is dissmissed.
Interface with your method
public interface MyInterface {
void method_to_run_onDismiss();
}
Dialog - create an instance of the interface and call it right before dismiss();
public class ProEdiCon extends DialogFragment {
private MyInterface myInterface;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle bun) {
...
myInterface = (MyInterface) context;
Button btn = pro_vie.findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myInterface.method_to_run_onDismiss();
dismiss();
}
}
return pro_vie;
}
}
Activity class implement the interface and use the method you already have
Public class HomScr extends AppCompatActivity implements MyInterface {
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.das_boa);
initialize();
}
private void initialize(){
tv = findViewById(R.id.tv);
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ProEdiCon dia_fra = new ProEdiCon();
dia_fra.show((this).getSupportFragmentManager(), "pro_edi_con");
}
}
}
private void method_to_run_onDismiss(){
tv.setText("method to run is executed");
Toast.makeText(this, "method to run successfully executed on dismiss Dialog Fragment", Toast.LENGTH_SHORT).show();
}
}
I have a class which extends DialogFragment. When I click on a button, the dialog shows. The first time is normal, I mean the size is the one of the layout of the dialog. However, when I dismiss the dialog and I click on the button for the second, third,... time, the dialog covers all the screen and I don't know why at all. All methods are always called, so why this happens?
Here is the implementation of the DialogFragment:
public class DialogFragmentAzione extends DialogFragment
{
private View view;
private SetVocabulary setVocabulary;
private LinkedList<String> linkedListGruppi;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if(getArguments().getSerializable(Constants.codiceArgomentoDialogFragment) instanceof Set)
setVocabulary = (SetVocabulary) getArguments().getSerializable(Constants.codiceArgomentoDialogFragment);
else
linkedListGruppi = (LinkedList<String>) getArguments().getSerializable(Constants.codiceArgomentoDialogFragment);
view = inflater.inflate(R.layout.layoutdialogfragment, container);
view.findViewById(R.id.aggiungiDialog).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
EditText editText = (EditText)view.findViewById(R.id.editTextAggiungi);
String text = editText.getText().toString();
if(text.contains(" ")||text.contains(".")||text.contains(",")||text.contains(";")||text.contains("-")||text.contains("_")
||text.contains(":")||text.contains("#")||text.contains("ç")||text.contains("°")||text.contains("#")||text.contains("§")
||text.contains("{")||text.contains("}")||text.contains("[")||text.contains("]")||text.contains("(")||text.contains(")")
||text.contains("(")||text.contains("!")||text.contains("%")||text.contains("£")||text.contains("&")||text.contains("/")
||text.contains("=")||text.contains("?")||text.contains("'")||text.contains("^")||text.contains("<")||text.contains(">")
||text.contains("<")||text.contains("|")||text.contains("€")||text.contains("+")||text.contains("*"))
Toast.makeText(getActivity(),"Il testo contiene caratteri non ammessi",Toast.LENGTH_SHORT).show();
else if(text.length()<3)
Toast.makeText(getActivity(),"Il testo è troppo corto",Toast.LENGTH_SHORT).show();
else if(text.length()>15)
Toast.makeText(getActivity(),"Il testo è troppo lungo",Toast.LENGTH_SHORT).show();
else
{
if(setVocabulary!=null)
setVocabulary.add(text);
else
linkedListGruppi.add(text);
dismiss();
}
}
});
return view;
}
#Override
public void onActivityCreated(Bundle bundle)
{
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme);
super.onActivityCreated(bundle);
}
}
Here is the creation of the dialog:
dialogFragment = new DialogFragmentAzione();
bundleFragment = new Bundle();
bundleFragment.putSerializable(Constants.codiceArgomentoDialogFragment,setVocabulary);
dialogFragment.setArguments(bundleFragment);
getActivity().findViewById(R.id.floatingActionButton).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialogFragment.show(getActivity().getFragmentManager().beginTransaction(), "Dialog");
}
});
The first 4 lines are exectued only one time
Remove this line of code:
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme);
In this way the dialog will be always of the same size.
Fragment 1:
public class homePage extends Fragment {
private OnFragmentInteractionListener mListener;
private View view;
public homePage() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_home_page, container, false);
Button btnLogin = (Button) view.findViewById(R.id.login);
Button btnRegister = (Button) view.findViewById(R.id.register);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loginView();
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
registerView();
}
});
return view;
}
public static homePage newInstance() {
homePage fragment = new homePage();
Bundle args = new Bundle();
return fragment;
}
public void registerView(){}
public void loginView(){}
public interface OnFragmentInteractionListener {
}
}
Acitivty :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
homePage homepage = new homePage();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, homepage)
.commit();
}
}
}
My fragment1 has two buttons with the id's "login" and "register". Whenever login is clicked, I want to go to my fragment_login.xml, and when register is clicked I want to go to my fragment_register.xml. Should I create these functions in my activity or in my fragment? And how should I do this? I'm fairly new to android and I'm trying to learn these basic things atm. Thanks for the help :(
Login context: "com.example.hoofdgebruiker.winkelskortrijk.login"
Register context: "com.example.hoofdgebruiker.winkelskortrijk.register"
You have to make a communication between Fragment objects via an Interface.
The Activity that make the switch between your fragments needs to implement that Interface.
So, in your case your classes must be defined as follows. This is your Interface, it helps you to tell your activity that a button has been clicked from within your Fragment:
public interface HomeClickListener {
void onLoginClick();
void onRegisterClick();
}
Your Activity needs to implement the above interface in order to be notified when a button has been clicked:
public class HomeActivity extends Activity implements HomeClickListener {
void onLoginClick() {
// Your activity code to replace your current Fragment with your Login fragment
}
void onRegisterClick() {
// Your activity code to replace your current Fragment with your Register fragment
}
}
Your fragment is hosted by an Activity, so you need to have a reference to it and notify it via an Interface:
public class LoginFragment extends Fragment {
final HomeClickListener homeClickListener
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
homeClickListener = (homeClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_home_page, container, false);
Button btnLogin = (Button) view.findViewById(R.id.login);
Button btnRegister = (Button) view.findViewById(R.id.register);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
homeClickListener.onLoginClick();
}
});
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
homeClickListener.onRegisterClick();
}
});
return view;
}
}
More information here.
I have a button in a fragment class that I'd like to have trigger a method in the parent activity. I've implemented an interface for this.
My issue is that the View.onClickListener is giving me the following error:
Class 'Anonymous class derived from onClickListener' must either be declared abstract or implement abstract method 'onClick(View)' in 'onClickListener'
Which is odd, because I'm implementing onClick(View).
Here is the code in my Fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(com.zlaporta.chessgame.R.layout.gamedescfragment, container, false);
final Button make_move = (Button) v.findViewById(R.id.make_move);
make_move.setOnClickListener(new ***View.OnClickListener()*** {
public void OnClick(View v) {
makeMoveCallback.makeMoveMethod();
}
});
The stars indicate the portion of the code that Android Studio doesn't like.
Do it using Anonymous inner class in an object:
//declaring OnClickListener as an object
private OnClickListener btnClick = new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
};
//passing listener object to button
make_move.setOnClickListener(btnClick);
Hope this will help :)
Just a typo: Replace the method name
OnClick
with
onClick
Could you try passing the OnClickListener from a method
e.g.,
private View.OnClickListener getButtonOnClickListener() {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
// this is the code
}
};
}
and then using make_move.setOnClickListener(getButtonOnClickListener());
This is best way to using click event for button. using onClick listener implementing. use below code.
public class MyFragment extends Fragment implements OnClickListener {
Button mButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main_layout, null);
mButton = (Button) view.findViewById(R.id.button1);
mButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
if (v == mButton) {
// Do something on click button
}
}
}
If using every click event separately it take more space. its better to use this code.
Add #Override above onClick method
Or you can use below method of button click Listener in OnActivityCreated() methos of Fragment.
make_move.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
makeMoveCallback.makeMoveMethod();
}
});