I have made a bottom sheet dialog with Frame layout. Everything is working fine but I am unable to make the background transparent.
I have given transparent color to both the Frame layout and the parent layout of the dialog UI.
Here is the code for the Frame layout:
<FrameLayout
android:id="#+id/nearby_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
Code for the bottomsheet dialog UI:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#android:color/transparent"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
app:cardCornerRadius="20dp"
app:cardElevation="10dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
....
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
This is how I am initializing the dialog:
FrameLayout bottom_sheet;
bottomSheetBehavior = BottomSheetBehavior.from(bottom_sheet);
View view = getLayoutInflater().inflate(R.layout.nearby_floating_sheet, null);
bottomSheetDialog = new BottomSheetDialog(getActivity());
bottomSheetDialog.setContentView(view);
bottomSheetDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
((View)view.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
bottomSheetDialog.show();
Here is my output:
Can someone please help me with this.
Maybe you should also set your Dialog Window to transparent.
add the following code to your BottomSheetDialog.
// BottomSheetDialog
public BottomSheetDialog(Context context) {
super(context, R.style.Bottom_Sheet_Style); //set your own dialog theme
// ...
Window window = getWindow();
window.setBackgroundDrawableResource(android.R.color.transparent);
WindowManager.LayoutParams lp = window.getAttributes();
lp.alpha = 1.0f;
lp.dimAmount = 0.0f;
window.setAttributes(lp);
// ...
}
Then add the following code to your res/values/styles.xml. If you don't have the file, then create one.
<style name="Bottom_Sheet_Style" parent="#android:style/Theme.Dialog">
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
for transparent background you must apply theme while creating the dialog
first create the below style
<item name="android:background">#android:color/transparent</item>
then apply it using BottomSheetDialog(this,R.style.yourStyle)
you can use bottomSheetDialog.getWindow().setDimAmount(0) for setting up dim amount
Related
I have this custom layout because I want a ListView with TextView below it and I want to handle click on list items so dialog doesn't close. (AlertDialog will show its own message view above its ListView.)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="14dp"
android:paddingEnd="10dp"
>
<ListView
android:id="#+id/optionList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:choiceMode="singleChoice"
android:divider="#null"
/>
<TextView
android:id="#+id/messageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:padding="5dp"
/>
</LinearLayout>
I made a fake setup where I put text in both the dialog's TextView and my layout's. Screenshot of the result.
I even tried putting style="?android:attr/textAppearanceMedium" in #id/messageView in my layout since alert_dialog.xml has it. It made the text larger than the dialog's message. And the color doesn't match, too light (as if it's the Activity's default color).
I even tried using the builder's LayoutInflater, which is what the documentation says to do.
val infl = builder.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = infl.inflate(R.layout.dialog_report_profile, null)
builder.setView(view)
You can always put both style="?android:attr/textAppearanceMedium" AND android:color="#000" at your TextView.
Or, you can just add this to your res/styles.xml:
<style name="DialogMessageText" parent="#android:style/TextAppearance.Medium">
<item name="android:textColor">#android:color/black</item>
</style>
and put this line to your TextView: style="#style/DialogMessageText"
I want to get something like this. Is it possible?
The answer to this question is not applicable without an actual header item, which I don't have here. Action bar is not an item I can anchor to, or at least I don't know a way to do that.
This can be done using a custom toolbar as supportActionBar.
And instead of using layout_anchor to place the FAB, we can constraint it to the tool bar using ConstraintLayout as a root view.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="64dp"
android:layout_marginRight="64dp"
android:src="#drawable/ic_baseline_play_arrow_24"
app:layout_constraintBottom_toBottomOf="#id/appbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/appbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
And make sure to use AppTheme with NoActionBar like Theme.MaterialComponents.DayNight.NoActionBar
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
Then set supportActionBar in activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
}
Preview:
I have tried a solution but it isn't direct one and hope it will help
in the root coordinate layout create a child empty layout at the top of it and change the background color to be the same color of action bar , then new empty layout will be after action bar directly and it will be shown as part of the action bar and give it proper height as you want .and your code will be like that
Empty layout:
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:id="#+id/tst"
android:background="#android:color/black"
android:layout_height="50dp"/>
you can increase the height as you want but it is the best height for my device
Floating Actio Button:
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="#id/tst"
app:layout_anchorGravity="top|center"
/>
I am trying to make a transparent bottom sheet layout, that would allow me to see the contents of the view below it. The bottom sheet is working as expected, however when I set the background to either #null or #android:color/transparent, the layout's view is white, as opposed to transparent. My layout is as follows:
app_bar_main.xml:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/coordinatorLayout"
android:background="#android:color/transparent"
android:fitsSystemWindows="true"
tools:context=".core.activities.MainActivity">
<!-- stuff here -->
<LinearLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#null"
android:orientation="vertical"
app:layout_behavior="#string/bottom_sheet_behavior">
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
The linear layout with id bottom_sheet holds, well, my bottom sheet. The sheet itself is defined as follows:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="#null"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#null"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottom_sheet_placeholder_layout"
android:layout_weight="0.6"
android:layout_width="match_parent"
android:background="#null"
android:layout_height="50dp"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottom_sheet_layout"
android:layout_margin="0dp"
android:layout_weight="0.4"
android:layout_width="match_parent"
android:background="#color/my_background"
android:layout_height="wrap_content"
android:orientation="vertical">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="#+id/my_progress_bar" />
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:textColor="#color/my_text"
android:id="#+id/txt_my_info"
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:textSize="48px" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/txt_my_address"
android:textColor="#color/my_secondary_text"
android:visibility="gone"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/btn_edit_tree_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:layout_marginTop="-62dp"
android:elevation="100dp"
android:src="#drawable/ic_create_black_24dp"
app:layout_anchor="#id/bottom_sheet_layout"
app:layout_anchorGravity="top|end|right"
app:useCompatPadding="true"/>
</android.support.design.widget.CoordinatorLayout>
The answer is much more easier: just add this line
myDialog
.getWindow()
.findViewById(R.id.design_bottom_sheet)
.setBackgroundResource(android.R.color.transparent);
And don't change standard ids (R.id.design_bottom_sheet and android.R.color.transparent). It makes background of Bottom Sheet Dialog transparent
private void setupDialogBackground() {
getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.design_bottom_sheet);
if (bottomSheet == null)
return;
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheet.setBackground(null);
}
});
}
add this in styles.xml
<style name="TransparentDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:colorBackground"> #android:color/transparent</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:backgroundDimAmount">0.3</item>
<item name="android:windowFrame">#null</item>
<item name="android:windowIsFloating">true</item>
</style>
BottomSheetDialog bsDialog = new BottomSheetDialog(this,R.style.TransparentDialog);
bsDialog.setContentView(R.layout.bottomsheet_dialog);
bsDialog.show();
and voila it works
I had to wait until after setContentView was called in onActivityCreated in order to access the container. Also while getDialog().getWindow().findViewById(R.id.design_bottom_sheet) did successfully find the FrameLayout, I decided to avoid explicitly calling out the internally defined id by using getView().getParent().
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); // setContentView called here
((View) getView().getParent()).setBackgroundColor(Color.TRANSPARENT);
}
Add this in your bottomSheet setupDialog(final Dialog dialog, int style)
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
and also add android:background="#android:color/transparent" to root view
Just need to use this style:
<style name="BaseBottomSheetDialogThem" parent="#style/Theme.Design.Light.BottomSheetDialog">
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
and set your style to BaseBottomSheetDialogThem.
Here is the kotlin version thanks to kolorszczak . Hope it save someones time converting .
val dialog = BottomSheetDialog(activity!!)
dialog.setOnShowListener {
var dialogTmp: BottomSheetDialog = it as BottomSheetDialog
var bottomSheet: FrameLayout? =
dialogTmp.findViewById(R.id.design_bottom_sheet) as FrameLayout?
?: return#setOnShowListener
bottomSheet?.background = null
}
Create in your color.xml : <color name="colorTransparent">#00000000</color>
and use android:background="#color/colorTransparent"
change color background
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottom_sheet_placeholder_layout"
android:layout_weight="0.6"
android:layout_width="match_parent"
android:background="#00FFFFFF"
android:layout_height="50dp"
android:orientation="horizontal">
</LinearLayout>
Try it!!
I already showed my bottom sheet layout with its peek height set to 100dp. But how can I limit my bottom sheet to expand to 500dp only? This is my sample layout:
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity" />
<android.support.v4.widget.NestedScrollView
android:id="#+id/design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
app:behavior_hideable="true"
app:behavior_peekHeight="100dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_margin="#dimen/activity_horizontal_margin"
app:layout_anchor="#+id/design_bottom_sheet"
app:layout_anchorGravity="top|right|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.design.widget.CoordinatorLayout>
In addition to my question, how can I disallow the user from dragging the bottom sheet up and down?
to stop the bottom sheet from moving up the full screen is simple, just set a layout_height for your NestedScrollView to 500dp, also you probably want to set it's layout_gravity="bottom"
<android.support.v4.widget.NestedScrollView
android:id="#+id/design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="500dp"
android:background="#000000"
android:layout_gravity="bottom"
app:behavior_hideable="true"
app:behavior_peekHeight="100dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="5dp"
android:background="#e444ff" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
if you don't want the view to be draggable up then you need to set behavior_peekHeight and layout_height to the same values.
And to stop the view from being draggable down is the behavior_hideable flag just set this to false
You can use setMaxHeight method from BottomSheetBehavior (this method should be called before show() method)
bottomSheetDialog.behavior.maxHeight = 1000 // set max height when expanded in PIXEL
bottomSheetDialog.behavior.peekHeight = 400 // set default height when collapsed in PIXEL
You can just set param "maxHeight" to the root viewgroup of your bottom sheet.
android:maxHeight=500dp
Works good with ConstraintLayout as root layout.
If using BottomSheetDialogFragment:
In my case I was using BottomSheetDialogFragment and modified the bottom sheet peek height by getting its reference by override OnCreateDialog method inside my BottomSheetFragment
#NonNull #Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog bottom_dialog = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) bottom_dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
assert bottomSheet != null;
//BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
DisplayMetrics displayMetrics = requireActivity().getResources().getDisplayMetrics();
int height = displayMetrics.heightPixels;
int maxHeight = (int) (height*0.80);
BottomSheetBehavior.from(bottomSheet).setPeekHeight(maxHeight);
}
});
return dialog;
}
Above solutions didn't work for me so I solved it by
1. added app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" in the root view of bottom sheet layout.
2. custom style for bottom sheet:
<style name="AppBottomSheetDialogTheme" parent="Theme.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">#style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Widget.MaterialComponents.BottomSheet">
<item name="behavior_peekHeight">600dp</item>
</style>
3. And using this in Activity or Fragment by
val mBottomSheetDialog = BottomSheetDialog(this, R.style.AppBottomSheetDialogTheme)
val inflater = this.layoutInflater
val sheetView = inflater.inflate(R.layout.bottom_sheet_layout, null)
mBottomSheetDialog.setContentView(sheetView)
mBottomSheetDialog.show()
For some reason, the accepted answer didn't work for me. Maybe because I'm not using a fragment and a NestedScrollView as the layout inside my BottomSheet. Anyway, in my case, the solution was to limit the size of the CoordinatorLayout:
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Your main content here -->
</ConstarintLayout>
<CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="MAX SIZE OF BOTTOM SHEET">
<YourBottomSheetLayout>
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</CoordinatorLayout>
</ConstarintLayout>
I've been playing around with CardViews inside a RecyclerView, but can't seem to get my cards centered.
My cardview.xml:
<android.support.v7.widget.CardView
android:id="#+id/cardview"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_width="300dp"
android:layout_height="100dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/text"
android:textAlignment="center"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</android.support.v7.widget.CardView>
My activity_main.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryDark"/>
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Image of what my app looks like when I run it:
Okok, I have the same question and I think I have "solved" it. It's really just another hack. The android team at Google really should fix this recycler view and add support for swipe to dismiss.
In onCreateView:
recyclerView.addItemDecoration(new ItemDecoration() {
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
int totalWidth = parent.getWidth();
int maxCardWidth = getResources().getDimensionPixelOffset(R.dimen.card_max_width);
int sidePadding = (totalWidth - maxCardWidth) / 2;
sidePadding = Math.max(0, sidePadding);
outRect.set(sidePadding, 0, sidePadding, padding);
}
});
You need to set LinearLayout's android:layout_width as match_parent in order for android:gravity="center" to take effect.
Had the same problem. My RecyclerView is inside a SwipeRefreshLayout, so I found out I could center it with the SwipeRefreshLayout.
<style name="swipe_refresh_cards_layout">
<item name="android:layout_width">#dimen/swipe_refresh_cards_width</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center_horizontal</item>
</style>
I'm using a dimens.xml file for various screen sizes here.
Not the best solution IMO, but it works. I also found it to work (not using the solution above) if I put a LinearLayout as the parent to the SwipeRefreshLayout with
<style name="inner_layout">
<item name="android:layout_width">#dimen/swipe_refresh_cards_width</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:orientation">vertical</item>
</style>
Try wrapping up your Cardview inside a LinearLayout with width set to match_parent and android:gravity = "center".
Just set your parent's(in your case LinearLayout) width to match_parent.