This question already has answers here:
Set state of BottomSheetDialogFragment to expanded
(20 answers)
Closed 4 years ago.
My BottomSheetDialogFragment opens half (mean not fully) when I open it.
fragment.show(supportFragmentManager, "my_frag")
I tried NestedScrollView with behavior_peekHeight but did not work.
Tried without NestedScrollView. with only LinearLayout.
Tried switching height between match_parent & wrap_content
I have simple RecyclerView in BottomSheetDialogFragment layout.
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
...
>
<android.support.v7.widget.RecyclerView
...
/>
By BottomSheetFragment you mean BottomSheetDialogFragment . To open expended sheet you need to make some changes in onCreateDialog().
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog bottomSheetDialog=(BottomSheetDialog)super.onCreateDialog(savedInstanceState);
bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog dialog = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = dialog .findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(true);
BottomSheetBehavior.from(bottomSheet).setHideable(true);
}
});
return bottomSheetDialog;
}
Just keep the layout match_parent no need to use NestedScrollView. It worked for me . Let me know if you still face problem .
In case someone is using New Material library . Which is
implementation 'com.google.android.material:material:1.0.0'.
Then you need change the id of Parent FrameLayout. So it will be .
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog bottomSheetDialog=(BottomSheetDialog)super.onCreateDialog(savedInstanceState);
bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dia) {
BottomSheetDialog dialog = (BottomSheetDialog) dia;
FrameLayout bottomSheet = dialog .findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(true);
BottomSheetBehavior.from(bottomSheet).setHideable(true);
}
});
return bottomSheetDialog;
}
Make sure all your imports from import com.google.android.materialin this case.
You are accessing your parent view so use below code to expand it into Full screen.
View parent = (View) inflatedView.getParent();
parent.setFitsSystemWindows(true);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(parent);
inflatedView.measure(0, 0);
DisplayMetrics displaymetrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenHeight = displaymetrics.heightPixels;
bottomSheetBehavior.setPeekHeight(screenHeight);
if (params.getBehavior() instanceof BottomSheetBehavior) {
((BottomSheetBehavior)params.getBehavior()).setBottomSheetCallback(mBottomSheetBehaviorCallback);
}
params.height = screenHeight;
parent.setLayoutParams(params);
Hope it helps you.
Related
Currently, we are figuring how to implement such a bottom sheet, with the following requirements.
Round corner bottom sheet.
Fixed height bottom sheet.
Non-draggable bottom sheet.
Content in the bottom sheet is scrollable.
Hide bottom sheet when we tap on non-bottom sheet item.
Hide sheet when we press on back button.
A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
We are considering, whether to use BottomSheetBehavior or BottomSheetDialogFragment.
So far, we manage to implement all the requirements, by using BottomSheetBehavior.
Implementation using BottomSheetBehavior
However, we do not really like the solution as
It increases the complexity of our Activity's layout, where additional CoordinatorLayout is required.
Manual touch event code handling is required at Activity, to achieve requirement 5, 6 & 7 (Hide bottom sheet).
Here's the code snippet by using BottomSheetBehavior.
public class MainActivity extends AppCompatActivity {
private BottomSheetBehavior bottomSheetBehavior;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.image_button_0).setOnClickListener(view -> demo0());
findViewById(R.id.image_button_1).setOnClickListener(view -> demo1());
// 7) A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item
// will get focus and bottom sheet will hide.
findViewById(R.id.edit_text_0).setOnFocusChangeListener((view, b) -> {
if (b) {
hideBottomSheet();
}
});
// 7) A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item
// will get focus and bottom sheet will hide.
findViewById(R.id.edit_text_1).setOnFocusChangeListener((view, b) -> {
if (b) {
hideBottomSheet();
}
});
}
public void demo0() {
DemoBottomDialogFragment demoBottomDialogFragment = DemoBottomDialogFragment.newInstance();
demoBottomDialogFragment.show(getSupportFragmentManager(), "demoBottomDialogFragment");
}
public void demo1() {
// 1) Round corner bottom sheet.
View view = findViewById(R.id.bottom_sheet_layout_2);
/*
2) Fixed height bottom sheet.
3) Non-draggable bottom sheet.
4) Content in the bottom sheet is scrollable.
*/
this.bottomSheetBehavior = BottomSheetBehavior.from(view);
bottomSheetBehavior.setPeekHeight(900, true);
bottomSheetBehavior.setDraggable(false);
}
private boolean hideBottomSheet() {
if (this.bottomSheetBehavior != null) {
this.bottomSheetBehavior.setPeekHeight(0, true);
this.bottomSheetBehavior = null;
return true;
}
return false;
}
#Override
public void onBackPressed() {
// 5) Hide bottom sheet when we tap on non-bottom sheet item.
if (hideBottomSheet()) {
return;
}
super.onBackPressed();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// 6) Hide sheet when we press on back button.
hideBottomSheet();
return super.onTouchEvent(event);
}
}
If we were using BottomSheetDialogFragment, the code will be way more simpler. We can achieve all requirements, except number 7
A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
Here's the outcome of BottomSheetDialogFragment.
Implementation using BottomSheetDialogFragment
The good thing of using BottomSheetDialogFragment is that,
Will not increase the complexity of Activity's layout.
No code required at Activity, to hide the bottom sheet (Requirement 5, 6. Requirement 7 still not achievable)
Here's the code snippet.
public class DemoBottomDialogFragment extends BottomSheetDialogFragment {
public static DemoBottomDialogFragment newInstance() {
return new DemoBottomDialogFragment();
}
#NonNull
#Override public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// https://stackoverflow.com/questions/58651661/how-to-set-max-height-in-bottomsheetdialogfragment
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override public void onShow(DialogInterface dialogInterface) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
// !!!
layoutParams.height = 900;
bottomSheet.setLayoutParams(layoutParams);
}
});
return dialog;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make the bottom sheet non drag-able.
setStyle(DialogFragment.STYLE_NORMAL, R.style.BottomSheetDialogStyle);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_layout, container,
false);
// get the views and attach the listener
return view;
}
}
I was wondering, if we were using BottomSheetDialogFragment, is there a way to achieve
A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
As you can see, when I tap on EditText region, the bottom sheet is hidden. But, the EditText is not getting focus.
Here's the complete workable demo for testing purpose - https://github.com/yccheok/wediary-sandbox/tree/master/bottom-sheet
Thank you.
There are two window flags that allow passing touch events to the background windows:
FLAG_NOT_TOUCH_MODAL
FLAG_WATCH_OUTSIDE_TOUCH
But those flags can work only for touches outside the dialog window; so setting them alone won't work if the dialog window expands to obscure the EditText's.
So, we need to limit the dialog window to the bottom sheet desired layout height which it's hard coded as 900px. Doing this can prevent the window from obscuring the EditText's; and hence the flags do their job.
Now, we'll hard code the window height to that value; and set the bottom sheet to the expanded state to expand to the entire window:
So, instead of layoutParams.height = 900; We'd use:
WindowManager.LayoutParams params = window.getAttributes();
params.height = 900;
params.gravity = Gravity.BOTTOM; // bias the dialog to the bottom
getDialog().getWindow().setAttributes(params);
This will achieve the desired behavior but now the rounded corners are gone as the expanded state is designed to expand to the entire available space. To solve this we'd set the rounded corner in the BottomSheet style instead of the layout.
Here is the modified version:
<resources>
<style name="BottomSheetDialogStyle" parent="Theme.Material3.Light.BottomSheetDialog">
<item name="behavior_draggable">false</item>
<item name="bottomSheetStyle">#style/BottomSheetStyle</item>
</style>
<style name="BottomSheetStyle">
<item name="android:background">#drawable/bottom_sheet_background</item>
</style>
</resources>
Now we can safely remove android:background="#drawable/bottom_sheet_background" from the layout.
BottomSheetDialogFragment:
public class DemoBottomDialogFragment extends BottomSheetDialogFragment {
public static DemoBottomDialogFragment newInstance() {
return new DemoBottomDialogFragment();
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// https://stackoverflow.com/questions/58651661/how-to-set-max-height-in-bottomsheetdialogfragment
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
return dialog;
}
#Override
public void onStart() {
super.onStart();
Window window = getDialog().getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
window.setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
WindowManager.LayoutParams params = window.getAttributes();
params.height = 900;
params.gravity = Gravity.BOTTOM;
window.setAttributes(params);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make the bottom sheet non drag-able.
setStyle(DialogFragment.STYLE_NORMAL, R.style.BottomSheetDialogStyle);
}
#Nullable
#Override
#SuppressLint("RestrictedApi")
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_layout, container,
false);
return view;
}
}
It seems BottomSheetDialogFragment is coded with an anchor, where if your fragment layout exceeds 360dp in height onShow() will cause the dialog to peek to 360dp and you have to manually drag the sheet up to show all of your layout.
any way to bypass this behavior or any other recommendations for a modal bottom dialog where I can use a fragment?
you may check the behavior as follows
Activity.java
MyDialog myDialog = new MyDialog();
mtDialog.show(getChildFragmentManager(),"my_dialog_fragment");
MyDialog.java
public class MyDialog extends BottomSheetDialogFragment{
public View onCreate(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState){
return inflater.inflate(R.layout.dialog, container, false);
}
}
dialog.xml
<FrameLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="432dp"
android:backgroud="#color/blue"/>
that's pretty much the code. I've tried using setStyle and creating a BottomSheetDialog style and all those permutations and nope. but setting the height to 360dp is where it expands fully, but I need some more area.
OP here answering the Q.
public class MyDialogFragment extends BottomSheetDialogFragment {
#Override
public void setupDialog(Dialog dialog, int style) {
View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog, null);
dialog.setContentView(v);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) v.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
((BottomSheetBehavior) behavior).setState(BottomSheetBehavior.STATE_EXPANDED);
}
The above fixed the issue of not expanding to the full height declared in the layout. Might want to add a check on the behavior to make sure its not null. Now just need to add my arithmetic, not sure if it needs to be on oncreateview or here in setup dialog... we shall see.
Happy coding :)
I'm using the BottomSheetBehavior from Google recently released AppCompat v23.2. The height of my bottom sheet depends on the content displayed inside of the bottom sheet (similar to the what Google does themselves in their Maps app).
It works fine with the data loaded initially, but my application changes the content displayed during runtime and when this happens the bottom sheet retains at it's old height, which either leads to unused space at the bottom or a cut of view.
Is there any way to inform the bottom sheet layout to recalculate the height used for expanded state (when height of the ViewGroup is set to MATCH_HEIGHT) or any way to manually set the required height?
EDIT: I also tried to manually call invalidate() on the ViewGroup and the parent of it but without any success.
I had the same problem with RelativeLayout as my bottom sheet. The height won't be recalculated. I had to resort to setting the height by the new recalculated value and call BottomSheetBehavior.onLayoutChild.
This is my temporary solution:
coordinatorLayout = (CoordinatorLayout)findViewById(R.id.coordinator_layout);
bottomSheet = findViewById(R.id.bottom_sheet);
int accountHeight = accountTextView.getHeight();
accountTextView.setVisibility(View.GONE);
bottomSheet.getLayoutParams().height = bottomSheet.getHeight() - accountHeight;
bottomSheet.requestLayout();
behavior.onLayoutChild(coordinatorLayout, bottomSheet, ViewCompat.LAYOUT_DIRECTION_LTR);
You can use BottomSheetBehavior#setPeekHeight for that.
FrameLayout bottomSheet = (FrameLayout) findViewById(R.id.bottom_sheet);
BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(newHeight);
This does not automatically move the bottom sheet to the peek height. You can call BottomSheetBehavior#setState to adjust your bottom sheet to the new peek height.
behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
Though the issue has been resolved in >=24.0.0 support library, if for some reason you still have to use the older version, here is a workaround.
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(#NonNull final View bottomSheet, int newState) {
bottomSheet.post(new Runnable() {
#Override
public void run() {
//workaround for the bottomsheet bug
bottomSheet.requestLayout();
bottomSheet.invalidate();
}
});
}
#Override
public void onSlide(#NonNull View bottomSheet, float slideOffset) {
}
});
For bottom sheet dialog fragment, read this: Bottom Sheet Dialog Fragment Expand Full Height
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
FrameLayout bottomSheet = dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setPeekHeight(0);
}
I faced the same issue, when trying to update the peek height based on its contents, the height from a previous layout was found. This makes sense as the new layout had not taken place yet. By posting on the UI thread the layout height is calculated after the new layout, and another layout request is made to update the bottom sheet to the right height.
void show() {
setVisibility(View.VISIBLE);
post(new Runnable() {
#Override
public void run() {
mBottomSheetBehavior.setPeekHeight(findViewById(R.id.sheetPeek).getHeight());
requestLayout();
}
})
}
I was facing the same issue when I used a recyclerview inside a BottomSheet and the items changed dynamically. As #sosite has mentioned in his comment, the issue is logged and they have fixed it in the latest release.
Issue log here
Just update your design support library to version 24.0.0 and check.
I've followed #HaraldUnander advice, and it gave me an idea which has actually worked. If you run a thread (couldn't make it work with the post method as him) after the BottomSheetBehavior.state is set up programmatically to STATE_COLLAPSED, then you can already obtain the height of your views and set the peekHeight depending on it's content.
So first you set the BottomSheetBehavior:
BottomSheetBehavior.from(routeCaptionBottomSheet).state = BottomSheetBehavior.STATE_COLLAPSED
And then you set the peekHeight dynamically:
thread {
activity?.runOnUiThread {
val dynamicHeight = yourContainerView.height
BottomSheetBehavior.from(bottomSheetView).peekHeight = dynamicHeight
}
}
If using Java (I'm using Kotlin with Anko for threads), this could do:
new Thread(new Runnable() {
public void run() {
int dynamicHeight = yourContainerView.getHeight();
BottomSheetBehavior.from(bottomSheetView).setPeekHeight(dynamicHeight);
}
}).start();
Below code snippet helped me solve this issue where i am toggling between visibility of different views in layout and height is automatically changing for my bottom sheet.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.your_bottom_sheet_layout, container, false)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.setContentView(R.layout.your_bottom_sheet_layout)
dialog.setOnShowListener {
val castDialog = it as BottomSheetDialog
val bottomSheet = castDialog.findViewById<View?>(R.id.design_bottom_sheet)
val behavior = BottomSheetBehavior.from(bottomSheet)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
return dialog
}
I've been struggling with a problem similar to yours.
Manually setting the height of the bottomSheet was the solution for me.
Having a view viewA that has the BottomSheetBehaviour and a custom method modifyHeight() that modifies the height of the view:
viewA?.modifyHeight()
viewA?.measure(
MeasureSpec.makeMeasureSpec(
width,
MeasureSpec.EXACTLY
),
MeasureSpec.makeMeasureSpec(
0,
MeasureSpec.UNSPECIFIED
)
)
val layoutParams = LayoutParams(viewA.measuredWidth, viewA.measuredHeight)
val bottomSheet = BottomSheetBehavior.from(viewA)
layoutParams.behavior = bottomSheet
viewA.layoutParams = layoutParams
My layout would be something like:
<com.yourpackage.ViewA
android:id="#+id/viewA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_peekHeight="50dp"
app:layout_behavior="#string/bottom_sheet_behavior" />
It is important to reuse the bottomSheetBehaviour of the old layoutParams because it contains the peekHeight and listeners you may have attached.
Here is the toggle button click listener I have implement to set pick height of bottom sheet with animation
FrameLayout standardBottomSheet = findViewById(R.id.standardBottomSheet);
BottomSheetBehavior<FrameLayout> bottomSheetBehavior = BottomSheetBehavior.from(standardBottomSheet);
btnToggleBottomSheet.setOnClickListener(new HPFM_OnSingleClickListener() {
#Override
public void onSingleClick(View v) {
if (bottomSheetBehavior.getPeekHeight() == 0) {
ObjectAnimator.ofInt(bottomSheetBehavior, "peekHeight", 200).setDuration(300).start();
}
else {
ObjectAnimator.ofInt(bottomSheetBehavior, "peekHeight", 0).setDuration(300).start();
}
}
});
On my OnListItemClick , i am displaying a Dialog which is working fine i.e. displaying on fullscreen in Portrait Orientation using custom layout for dialog. To support LandScape Orientation, i have added that custom layout in layouts-land folder and the device is picking that layout. But the dialog is not being shown on full screen horizontally. its only filling vertical screen.
final Dialog prfDialog = new Dialog(getActivity());
prfDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
prfDialog.setContentView(R.layout.view_student_dailog_layout);
prfDialog.getWindow().setBackgroundDrawableResource(R.drawable.dialoge_back);
Here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/editStudentMainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
// Other View
</RelativeLayout>
Make another class which extends Dialog, and add 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);
}
}
This will force the dialog to be fullscreen.
Maybe if you want want to do this, just use that method after creating your dialog.
I have been trying many commands to setup the size of my DialogFragment. It only contains a color-picker, so I have removed the background and title of the dialog:
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawable(
new ColorDrawable(android.graphics.Color.TRANSPARENT));
However I also want to position the dialog where I want and it is problematic. I use:
WindowManager.LayoutParams params = getDialog().getWindow().getAttributes();
params.width = LayoutParams.WRAP_CONTENT;
params.height = LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.LEFT;
getDialog().getWindow().setAttributes(params);
But one (big) obstacle remains: even though my dialog pane is invisible, it still has a certain size, and it limits the positions of my dialog. The LayoutParams.WRAP_CONTENT are here to limit the size of this pane to my color-picker, but for some reason it does not work.
Has anyone been able to do something similar?
i met a similar question that is you can't set the dialogFragment's width an height in code,after several try ,i found a solution;
here is steps to custom DialogFragment:
1.inflate custom view from xml on method
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().setCanceledOnTouchOutside(true);
View view = inflater.inflate(R.layout.XXX,
container, false);
//TODO:findViewById, etc
return view;
}
2.set your dialog's width an height in onResume(),remrember in onResume()/onStart(),seems didn't work in other method
public void onResume()
{
super.onResume();
Window window = getDialog().getWindow();
window.setLayout(width, height);
window.setGravity(Gravity.CENTER);
//TODO:
}
After some trial and error, I have found the solution.
here is the implementation of my DialogFragment class :
public class ColorDialogFragment extends SherlockDialogFragment {
public ColorDialogFragment() {
//You need to provide a default constructor
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_color_picker, container);
// R.layout.dialog_color_picker is the custom layout of my dialog
WindowManager.LayoutParams wmlp = getDialog().getWindow().getAttributes();
wmlp.gravity = Gravity.LEFT;
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, R.style.colorPickerStyle);
// this setStyle is VERY important.
// STYLE_NO_FRAME means that I will provide my own layout and style for the whole dialog
// so for example the size of the default dialog will not get in my way
// the style extends the default one. see bellow.
}
}
R.style.colorPickerStyle corresponds to :
<style name="colorPickerStyle" parent="Theme.Sherlock.Light.Dialog">
<item name="android:backgroundDimEnabled">false</item>
<item name="android:cacheColorHint">#android:color/transparent</item>
<item name="android:windowBackground">#android:color/transparent</item>
</style>
I simply extend a default Dialog style with my needs.
Finally, you can invoke this dialog with :
private void showDialog() {
ColorDialogFragment newFragment = new ColorDialogFragment();
newFragment.show(getSupportFragmentManager(), "colorPicker");
}
For my use case, I wanted the DialogFragment to match the size of a list of items. The fragment view is a RecyclerView in a layout called fragment_sound_picker. I added a wrapper RelativeLayout around the RecyclerView.
I had already set the individual list item view's height with R.attr.listItemPreferredHeight, in a layout called item_sound_choice.
The DialogFragment obtains a LayoutParams instance from the inflated View's RecyclerView, tweaks the LayoutParams height to a multiple of the list length, and applies the modified LayoutParams to the inflated parent View.
The result is that the DialogFragment perfectly wraps the short list of choices. It includes the window title and Cancel/OK buttons.
Here's the setup in the DialogFragment:
// SoundPicker.java
// extends DialogFragment
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(getActivity().getString(R.string.txt_sound_picker_dialog_title));
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(R.layout.fragment_sound_picker, null);
RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv_sound_list);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
SoundPickerAdapter soundPickerAdapter = new SoundPickerAdapter(getActivity().getApplicationContext(), this, selectedSound);
List<SoundItem> items = getArguments().getParcelableArrayList(SOUND_ITEMS);
soundPickerAdapter.setSoundItems(items);
soundPickerAdapter.setRecyclerView(rv);
rv.setAdapter(soundPickerAdapter);
// Here's the LayoutParams setup
ViewGroup.LayoutParams layoutParams = rv.getLayoutParams();
layoutParams.width = RelativeLayout.LayoutParams.MATCH_PARENT;
layoutParams.height = getListItemHeight() * (items.size() + 1);
view.setLayoutParams(layoutParams);
builder.setView(view);
builder.setCancelable(true);
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
// ...
});
builder.setPositiveButton(R.string.txt_ok, new DialogInterface.OnClickListener() {
// ...
});
return builder.create();
}
#Override
public void onResume() {
Window window = getDialog().getWindow();
window.setLayout(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
super.onResume();
}
private int getListItemHeight() {
TypedValue typedValue = new TypedValue();
getActivity().getTheme().resolveAttribute(R.attr.listPreferredItemHeight, typedValue, true);
DisplayMetrics metrics = new android.util.DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
return (int) typedValue.getDimension(metrics);
}
Here is fragment_sound_picker:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_sound_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
use this code for resize of Dialog Fragment android
public void onResume() {
super.onResume();
Window window = getDialog().getWindow();
window.setLayout(250, 100);
window.setGravity(Gravity.RIGHT);
}