I have a Bottom Sheet and I want to add a button in which the bottom sheet dialog expands on click
enter image description here
Is it doable to put onclicklistener inside bottom sheet fragment onCreateView and change the state of the dialog?
heres my Bottom Sheet Fragment
public class RepliesToComment extends BottomSheetDialogFragment {
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
Window window = dialog.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dialog.getBehavior().setState(BottomSheetBehavior.STATE_COLLAPSED); <--change to STATE_EXPANDED on click-->
return dialog;
}
ImageButton expandBtn;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_replies_to_comment, container, false);
{...}
expandBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
----
}
});
}
I manage to make it work heres my solution
dialog to global then made a boolean identifier to switch the state of the dialog
boolean identifier = true;
BottomSheetDialog dialog;
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
Window window = dialog.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
return dialog;
}
public void expand(){
if (!identifier){
dialog.getBehavior().setState(BottomSheetBehavior.STATE_COLLAPSED);
}else {
dialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);
}
}
then made the button into toggle button to change the value of the identifier
//expand
expandBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
identifier = b;
expand();
}
});
Related
I have a UI requirement showing a blocking DialogFragment, which can not be dismissed by clicking on the background.
Also when the DialogFragment is showing, any view under it cannot be clicked.
Things are working well except on the Samsung S9 device.
On Samsung S9, which has an edge button, when clicking around the edge button's edge, the view under the DialogFragment got clicked and the event performed, which is not as expected.
Here is a sample code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyDialogFragment myDialogFragment = new MyDialogFragment();
myDialogFragment.show(getSupportFragmentManager(), MyDialogFragment.TAG);
}
});
findViewById(R.id.background).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("wrong", "clicked!!!!---------------");
Toast.makeText(MainActivity.this, "Click!", Toast.LENGTH_LONG).show();
}
});
}
}
The layout is quite simple, just a LinearLayout with a button inside it.
Clicking button will show the blocking dialog.
The LinearLayout id is background, which should not be clicked after the dialog has shown.
The dialog code:
public class MyDialogFragment extends DialogFragment {
public static final String TAG = "Dialog";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCancelable(false);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_dialog_layout, container, false);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
#Override
public void onResume() {
Window window = getDialog().getWindow();
Point size = new Point();
Display display = window.getWindowManager().getDefaultDisplay();
display.getSize(size);
window.setLayout((int) (size.x * 0.8), WindowManager.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
super.onResume();
}
}
But now when the dialog is showing, click the area on the edge button, the background click listener can be entered, I can get the log and toast.
How to prevent this?
In the event that is firing I'd do
Fragment currentFrag = getSupportFragmentManager().findFragmentByTag(MyDialogFragment_TAG);
if (!(currentFrag instanceof MyDialogFragment))
{
// your code for when you're dialog fragment is not visible
}
setcancelable(false); can be used to block clicking on background till task completes
Give the root node an id
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/constraintlayoutRoot"
Add an empty OnClickListener
public View onCreateView(...) {
View view = _inflater.inflate(R.layout.fragment_xyz, _container, false);
view.findViewById(R.id.constraintlayoutRoot).setOnClickListener(view1 -> {
});
I am calling dialog fragment from FragmentA and returning some values to fragmentA. Now issue is whenever i go to another fragmentB from same fragmentA and return to it my dialog fragment values get cleared.
when i click on consultant doctor textview, a dialog opens (Pic 2). On Selecting an item (Pic 2),returns a value back to FragmentA. Pic 3 is a Fragment B which opens on same activity. But when i click on cross button on pic 3 and popBackStack , my value for consult doctor clears shown in Pic 4.
Pic 4 is an ISSUE
DialogFragment
#Override
public void onStart() {
super.onStart();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
getDialog().getWindow().setGravity(Gravity.CENTER);
getDialog().setCancelable(false);
getDialog().setCanceledOnTouchOutside(false);
getDialog().closeOptionsMenu();
}
#Override public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Nullable #Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View rootView = inflater.inflate(R.layout.consultant_doc_dialog, container, false);
recyclerView = (RecyclerView)rootView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setHasFixedSize(true);
adapter = new ConsultantDoctAdapter(getContext(),this);
adapter.getDocList().addAll(new ArrayList<DoctorList>());
recyclerView.setAdapter(adapter);
adapter.getDocList().clear();
adapter.getDocList().addAll(list);
adapter.notifyDataSetChanged();
close = (ImageButton)rootView.findViewById(R.id.bt_close);
close.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) {
getDialog().dismiss();
}
});
//cityEditText.setOnQueryTextListener(onQueryTextListener);
return rootView;
}
Fragment
#Nullable #Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_create_leads, container, false);
ButterKnife.bind(this, view);
setRetainInstance(true);
init();
setPicker();
setSpinnerListener();
btCheckCalendar.setOnClickListener(this);
etCityId.setOnClickListener(this);
etConsultingDocId.setOnClickListener(this);
btSubmit.setOnClickListener(this);
tvClientReferral.setOnClickListener(this);
etSalesPerson.setText(sharedPref.getString(AppConstants.PREFERENCE_USER_NAME, ""));
etZone.setText(sharedPref.getString(AppConstants.USER_ZONE, ""));
etAreaCode.setText(sharedPref.getString(AppConstants.USER_AREA_CODE, ""));
setSpinner();
getConsultantDoctorList();
return view;
}
Fragment B callBack:
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_main, new MyCalendarFragment())
.addToBackStack("calendarFragment")
.commit();
DialogCallack:
ConsultantDocDialogFragment consultantDocDialog = new ConsultantDocDialogFragment();
consultantDocDialog.setParameter(getContext(), this, doclist);
consultantDocDialog.show(getActivity().getSupportFragmentManager(),
ConsultantDocDialogFragment.class.getSimpleName());
break;
Please help me so that i can able to save state of values got from dialog fragment.
Please find the following code it may help you-
This is Fragment Code where you can get CallBack from Dialog Fragment-
HomeFragment.java
public class HomeFragment extends Fragment implements AlertDFragment.Callback {
private static final int DIALOG_FRAGMENT = 100;
Button alertdfragbutton;
private View rootView;
public HomeFragment() {
}
public static HomeFragment newInstance() {
return new HomeFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_home, container, false);
initUI(rootView);
return rootView;
}
private void initUI(View rootView) {
alertdfragbutton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
AlertDFragment alertdFragment = new AlertDFragment();
alertdFragment.setTargetFragment(HomeFragment.this, DIALOG_FRAGMENT);
// Show Alert DialogFragment
alertdFragment.show(getChildFragmentManager(), "Alert Dialog Fragment");
}
});
}
#Override
public void accept() {
Log.e("Home ", "OK");
}
#Override
public void decline() {
}
#Override
public void cancel() {
Log.e("Home ", "CANCEL");
}
}
Here is Dialog Fragment where we declare CallBack with methods-
public class AlertDFragment extends DialogFragment {
Callback callback;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
callback = (Callback) getTargetFragment();
return new AlertDialog.Builder(getActivity())
// Set Dialog Icon
.setIcon(R.drawable.androidhappy)
// Set Dialog Title
.setTitle("Alert DialogFragment")
// Set Dialog Message
.setMessage("Alert DialogFragment Tutorial")
// Positive button
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
callback.accept();
// Do something else
//getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, getActivity().getIntent());
}
})
// Negative Button
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
callback.cancel();
// Do something else
// getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
}
}).create();
}
public static interface Callback {
public void accept();
public void decline();
public void cancel();
}
}
A simple way to return values from DialogFragment is using setTargetFragment for calling a fragmentB creation, then return data to getTargetFragment (if not null). In fragmentA you can receive data through onActivityResult.
Another way is using SharedPreferences. You can get a new value with onResume or onHiddenChanged.
Instead of using the "Fragment Transition" why don't you just POP-UP your custom view
Just Create a global reference of
Dialogue dialogue
View popupView
and on click of whatever textview button etc.
you can just call a method like
void popup(){
popupView = LayoutInflater.from(getActivity()).inflate(R.layout.your_calenderlayout, null);
//suppose you have TextView cal_textview in popUp view i.e, your_calenderlayout
cal_textview = (TextView ) popupView.findViewById(R.id.cal_textview);
dialog = new Dialog(getContext());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCanceledOnTouchOutside(true);
dialog.setContentView(popupView); //and just add your popUpview
// For setting backgroung
/*dialog.getWindow().setBackgroundDrawableResource(android.R.color.Transparent);
*/
//For setting the width or height of popup
/*WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.CENTER;
dialog.getWindow().setAttributes(lp);*/
dialog.show();
}
and on dismiss of popUp or on click of the view inside popupView you set the value of variables or member inside the fragment directly
Hope this will help
You can use Shared prefs or sqlite to get your values and if you think its use less to save your temporary data in share prefs or sqlite Then Singleton model is a good option .. i believe we should follow KISS
design principle :P
How can the background be dimmed just like it is shown here?
I've set it up normally using the CoordinatorLayout and the BottomSheetBehavior.
This will simply show a bottom sheet.
public class MyBottomSheet extends BottomSheetDialogFragment {
private static final String TAG = "MyBottomSheet";
#NonNull
#Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
final View view = View.inflate(getContext(), R.layout.my_custom_view, null);
dialog.setContentView(view);
behavior = BottomSheetBehavior.from((View) view.getParent());
return dialog;
}
public void show(final FragmentActivity fragmentActivity) {
show(fragmentActivity.getSupportFragmentManager(), TAG);
}
}
To close the dialog simply as normal call close().
bottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull View bottomSheet, int newState) {}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
(your_layout/view).setAlpha(1 - slideOffset);
}
});
use BottomSheetDialog
basically it's a dialog (i.e support dim) and support modal bottom sheets behaviour give it a try
I am trying to achieve a full-screen dialog like the below image. I am able to show a full screen dialog but when the dialog is shown the status bar color changes to black and does not keep the primary-dark color.
Heres my dialog fragment
public class IconsDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.fragment_icons_dialog, container, false);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final RelativeLayout root = new RelativeLayout(getActivity());
root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// creating the fullscreen dialog
final Dialog dialog = new Dialog(getActivity());
dialog.setContentView(root);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.YELLOW));
dialog.getWindow().setWindowAnimations(R.style.DialogAnimation);
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
return dialog;
}
}
To get DialogFragment on full screen
Override onStart of your DialogFragment like this:
#Override
public void onStart()
{
super.onStart();
Dialog dialog = getDialog();
if (dialog != null)
{
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
}
}
In order to setStatusBarColor you need to set the flag: FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
public void setStatusBarColorIfPossible(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(color);
}
}
One way is to change back your status bar color as theme programmatically whenever you open the dialog.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Your theme color);
}
I'm trying to create an AlertDialog where both a message (in a TextView, for instance) and a MultiChoice-list can be displayed at the same time, but I'm a bit lost as to how to do it.
Will I have to create my own subclass of AlertDialog, or is there an easier way to do it?
You could create a normal AlertDialog but, instead of using the setMessage() method, you could just use a custom layout (you can inflate it in a View or even create a custom view) and use then the setView() method of the AlertDialog class.
Use DialogFragment for customization
public class ResponseDialog extends DialogFragment implements View.OnClickListener{
#Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
getDialog().getWindow()
.getAttributes().windowAnimations = R.style.DialogAnimationFromDown;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Black_NoTitleBar);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return dialog;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.YOUR_CUSTOM_LAYOUT, null);
//implement in layout what you want
return v;
}
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
}
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
}
}
}
for more info https://developer.android.com/reference/android/app/DialogFragment.html