tengo un BttomSheetDialogFragment personalizado y quiero tener esquinas redondeadas en la parte superior de la vista inferior
esta es mi clase personalizada que inflando mi diseño que quiero que aparezca desde abajo
View mView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.charge_layout, container, false);
initChargeLayoutViews();
return mView;
}
y también tengo este archivo de recursos xml como fondo:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners android:topRightRadius="35dp"
android:topLeftRadius="35dp"
/>
<solid android:color="@color/white"/>
<padding android:top="10dp"
android:bottom="10dp"
android:right="16dp"
android:left="16dp"/>
pero el problema es que, cuando configuro este archivo de recursos como fondo del elemento raíz de mi diseño, las esquinas aún no están redondeadas
y no puedo usar el siguiente código:
this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);
porque anula el fondo predeterminado de BottomSheetDialog y no habrá ningún color gris semitransparente sobre mi Vista inferior
Respuestas:
Crea un dibujo personalizado
rounded_dialog.xml
:<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@android:color/white"/> <corners android:topLeftRadius="16dp" android:topRightRadius="16dp"/> </shape>
Luego anule
bottomSheetDialogTheme
elstyles.xml
uso del dibujable como fondo:<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item> </style> <style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog"> <item name="bottomSheetStyle">@style/AppModalStyle</item> </style> <style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal"> <item name="android:background">@drawable/rounded_dialog</item> </style>
Esto cambiará todos los BottomSheetDialogs de su aplicación.
fuente
rounded_dialog
&AppModalStyle
names con un fondo donde solo las esquinas superiores están redondeadas, ya que solo esperaría usar un fondo de este tipo con un estilo de hoja inferior. ¿Qué talbottomsheet_rounded_background
&AppBottomSheetStyle
Con la nueva biblioteca de componentes de material , puede personalizar la forma de su componente usando el
shapeAppearanceOverlay
atributo en su estilo ( Nota: requiere la versión 1.1.0 )Simplemente use el método de
BottomSheetDialogFragment
anulaciónonCreateView
y luego defina su estilo personalizado para los cuadros de diálogo de la hoja inferior.Defina el
bottomSheetDialogTheme
atributostyles.xml
en el tema de su aplicación:<!-- Base application theme. --> <style name="AppTheme" parent="Theme.MaterialComponents.Light"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> .... <item name="bottomSheetDialogTheme">@style/CustomBottomSheetDialog</item> </style>
Entonces simplemente defina su forma favorita con
shapeAppearanceOverlay
<style name="CustomBottomSheetDialog" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog"> <item name="bottomSheetStyle">@style/CustomBottomSheet</item> </style> <style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet"> <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item> </style> <style name="CustomShapeAppearanceBottomSheetDialog" parent=""> <item name="cornerFamily">rounded</item> <item name="cornerSizeTopRight">16dp</item> <item name="cornerSizeTopLeft">16dp</item> <item name="cornerSizeBottomRight">0dp</item> <item name="cornerSizeBottomLeft">0dp</item> </style>
Puede obtener el mismo comportamiento anulando este método en su
BottomSheetDialogFragment
(en lugar de agregar elbottomSheetDialogTheme
tema en su aplicación):@Override public int getTheme() { return R.style.CustomBottomSheetDialog; }
En este caso, está utilizando este themeOverlay solo en el single
BottomSheetDialogFragment
y no en toda la aplicación.Nota importante sobre el ESTADO EXPANDIDO :
En el estado expandido, BottomSheet tiene esquinas planas . Puede consultar el comentario oficial en el repositorio de github :
Este comportamiento lo proporciona el
BottomSheetBehavior
y es imposible anularlo.Sin embargo, hay una solución:> DESCARGO DE RESPONSABILIDAD: ¡ puede dejar de funcionar en las próximas versiones!
Puede agregar un
BottomSheetCallback
en elBottomSheetDialogFragment
:@NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { Dialog dialog = super.onCreateDialog(savedInstanceState); ((BottomSheetDialog)dialog).getBehavior().addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { if (newState == BottomSheetBehavior.STATE_EXPANDED) { //In the EXPANDED STATE apply a new MaterialShapeDrawable with rounded cornes MaterialShapeDrawable newMaterialShapeDrawable = createMaterialShapeDrawable(bottomSheet); ViewCompat.setBackground(bottomSheet, newMaterialShapeDrawable); } } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); return dialog; } @NotNull private MaterialShapeDrawable createMaterialShapeDrawable(@NonNull View bottomSheet) { ShapeAppearanceModel shapeAppearanceModel = //Create a ShapeAppearanceModel with the same shapeAppearanceOverlay used in the style ShapeAppearanceModel.builder(getContext(), 0, R.style.CustomShapeAppearanceBottomSheetDialog) .build(); //Create a new MaterialShapeDrawable (you can't use the original MaterialShapeDrawable in the BottoSheet) MaterialShapeDrawable currentMaterialShapeDrawable = (MaterialShapeDrawable) bottomSheet.getBackground(); MaterialShapeDrawable newMaterialShapeDrawable = new MaterialShapeDrawable((shapeAppearanceModel)); //Copy the attributes in the new MaterialShapeDrawable newMaterialShapeDrawable.initializeElevationOverlay(getContext()); newMaterialShapeDrawable.setFillColor(currentMaterialShapeDrawable.getFillColor()); newMaterialShapeDrawable.setTintList(currentMaterialShapeDrawable.getTintList()); newMaterialShapeDrawable.setElevation(currentMaterialShapeDrawable.getElevation()); newMaterialShapeDrawable.setStrokeWidth(currentMaterialShapeDrawable.getStrokeWidth()); newMaterialShapeDrawable.setStrokeColor(currentMaterialShapeDrawable.getStrokeColor()); return newMaterialShapeDrawable; }
fuente
Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior
El
BottomSheetDialog
está configurando un color de fondo blanco predeterminado, es por eso que las esquinas no son visibles. Para mostrarlas, debe hacer que el fondo del cuadro de diálogo sea transparente anulando el estilo delBottomSheetDialog
.Defina este estilo en su
res/values/styles/styles.xml
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog"> <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item> </style> <style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal"> <item name="android:background">@android:color/transparent</item> </style>
Y establezca este estilo en su BottomSheetDialog
View view = getLayoutInflater().inflate(R.layout.chooser_bottom_sheet, null); BottomSheetDialog dialog = new BottomSheetDialog(this,R.style.BottomSheetDialog); // Style here dialog.setContentView(view); dialog.show();
fuente
crear una forma llamada forma_esquinas_ redondeadas
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:topLeftRadius="8dp" android:topRightRadius="8dp"/> <solid android:color="@color/white"/> </shape>
definir un estilo
<style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog"> <item name="bottomSheetStyle">@style/AppModalStyle</item> </style> <style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal"> <item name="android:background">@drawable/rounded_corners_shape</item> </style>
use este estilo en su BottomSheetDialogFragment personalizado como este, ¡funcionará!
public class CustomDialogFragment extends BottomSheetDialogFragment { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(STYLE_NORMAL, R.style. AppBottomSheetDialogTheme); } ... }
fuente
Fragment
s.Si usa la última versión del componente de material, solo tiene que anular
ShapeAppearance.MaterialComponents.LargeComponent
(ya que la hoja inferior usa esta forma) y establecer el valor que desee, como:<style name="ShapeAppearance.YourApp.LargeComponent" parent="ShapeAppearance.MaterialComponents.LargeComponent"> <item name="cornerFamily">rounded</item> <item name="cornerSize">12dp</item> </style>
Y luego configure el estilo de su aplicación:
<item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.YourApp.LargeComponent</item>
La solución de Gabriele Mariotti es similar y también funciona, pero esta es más simple.
fuente
BottomSheetDialog
?ShapeAppearance.MaterialComponents.LargeComponent
tengan el mismo tamaño de esquina y familia, no solo la hoja inferior. Verifique su requisito de estilo y decida si desea cambiar la apariencia de todos los componentes o solo de un componente o widget individual.La respuesta de Koma Yip de otra pregunta funcionó para mí, deberías intentarlo.
poner esto en su nodo raíz xml de diseño:
y en
onCreateView()
poner esto:fuente
Estaba comprobando lo mismo hoy y sí, tenías razón sobre seguir el código
this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);
esto se aplica al fondo del fragmento, por lo que debe obtener la vista de la hoja inferior desde la ventana de diálogo y cambiar el fondo aquí está el código
@SuppressLint("RestrictedApi") @Override public void setupDialog(Dialog dialog, int style) { super.setupDialog(dialog, style); View rootView = getActivity().getLayoutInflater().inflate(R.layout.view_member_info,null,false); unbinder = ButterKnife.bind(this, rootView); adjustUIComponents(); dialog.setContentView(rootView); FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet); bottomSheet.setBackgroundResource(R.drawable.container_background); }
aquí la hoja inferior es la vista real que desea cambiar.
fuente
BottomSheetDialogFragment
para que la lógica esté en elonCreateDialog
métodoCrea una forma dibujable ... que usaremos como fondo para la hoja inferior. Proporcione el valor apropiado para el radio de la esquina superior izquierda y derecha.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:topLeftRadius="24dp" android:topRightRadius="24dp" /> <padding android:top="2dp" /> <solid android:color="@color/white" /> </shape>
Ahora cree un estilo para el "Fragmento de diálogo de la hoja inferior"
<style name="BottomSheet" parent="@style/Widget.Design.BottomSheet.Modal"> <item name="android:background">@drawable/drawable_bottomsheet_background</item> </style> <style name="BaseBottomSheetDialog" parent="@style/Theme.Design.Light.BottomSheetDialog"> <item name="android:windowIsFloating">false</item> <item name="bottomSheetStyle">@style/BottomSheet</item> </style> <style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />
Ahora crea una clase personalizada que ampliará BottomSheetDilogFragment, donde proporciones tu estilo.
open class CustomRoundBottomSheet : BottomSheetDialogFragment() { override fun getTheme(): Int = R.style.BottomSheetDialogTheme override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme) }
Ahora use esta clase donde quiera que tenga una hoja inferior de esquina redondeada. p.ej
class BottomSheetSuccess : CustomRoundBottomSheet() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.bottomsheet_shopcreate_success, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) } }
fuente
Funcionó para mi
crea una forma llamada shape_unded_dialog
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/color_white" /> <corners android:topLeftRadius="16dp" android:topRightRadius="16dp" />
agregar estilos a continuación
<style name="AppBottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog"> <item name="bottomSheetStyle">@style/CustomBottomSheetStyle</item> </style> <style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal"> <item name="android:background">@drawable/shape_rounded_dialog</item> </style>
En la clase DialogFragment, el método override getTheme también devuelve el estilo Yourself.
@Override public int getTheme() { return R.style.AppBottomSheetDialogTheme; }
fuente
Esta respuesta es solo para el problema de configurar el color de fondo
Color.TRANSPARENT
después de configurar un elemento de diseño con fondo redondeado para el diseño.Ninguna de las respuestas me funcionó para establecer el color de fondo,
Color.TRANSPARENT
excepto lasetupDialog()
solución principal :@Override public void setupDialog(Dialog dialog, int style) { super.setupDialog(dialog, style); View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sheet, null); dialog.setContentView(contentView); ... ((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent)); }
PERO el
contentView
que establece para el diálogo aquí no es elview
queonViewCreated()
ingresa al inflaronCreateView()
. Rompe el flujo estándar, por lo que puede generar problemas que no puede usarView Bindings
,Kotlin Android Extensions
enonViewCreated()
Así que modifico un poco para establecer el fondo en
onActivityCreated()
:override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) (view?.parent as View).setBackgroundColor(Color.TRANSPARENT) }
Espero que esto ayude a quien tuvo el mismo problema
fuente
Sé que esta pregunta ya tiene una respuesta aceptada. Me gustaría documentar los problemas por los que pasé y cómo finalmente lo hice funcionar para que sea útil para alguien en el futuro.
En primer lugar, estaba usando
Theme.AppCompat.Light.DarkActionBar
como padre para nuestroAppTheme
. Esto significaba que la solución de @Gabriele Mariotti seguía fallando con el errorCould not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior
. Arreglé esto simplemente cambiando el padre aTheme.MaterialComponents.Light.DarkActionBar
. Esto no afectó nuestro tema de ninguna manera, pero el RTE desapareció. También puede solucionar este problema simplemente incluyendo los elementos necesarios en su estilo. Pero no me molesté en averiguar qué estilos requería BottomSheetBehavior.En segundo lugar, lo intenté como pude, pero no pude obtener el diseño del marco real (que era el BottomSheetDialogFragment) que usa para tener esquinas redondeadas. Me di cuenta de que establecer esto en una imagen Drawable funcionaba pero no con una forma o un
@null
. Resulta que fue porque elLinearLayout
que estaba usando tenía un fondo definido. Esto estaba anulando cualquier trasfondo en el estilo. Eliminar eso finalmente resultó en esquinas redondeadas.Además, no necesité que se estableciera ninguna forma de fondo para redondear las esquinas. La solución de @Gabriele Mariotti funcionó tan pronto como hice los cambios anteriores. Sin embargo, para establecer el color de fondo como quería que fuera, tuve que anular el elemento "backgroundTint".
PD: Soy nuevo en el desarrollo de Android y estoy manteniendo una aplicación antigua que se creó para uso interno en nuestra universidad. No estoy tan familiarizado con el sistema de diseño de Android o con la biblioteca de materiales. Supongo que por eso me tomó 3 días darme cuenta de esto. Espero que esto sea útil para alguien en el futuro.
fuente
Agregue estos dos métodos en su clase BottomsheetDialogFragment.
public void setDialogBorder(Dialog dialog) { FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet); bottomSheet.setBackground(new ColorDrawable(Color.TRANSPARENT)); setMargins(bottomSheet, 10, 0, 10, 20); } private void setMargins(View view, int left, int top, int right, int bottom) { if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); p.setMargins(left, top, right, bottom); view.requestLayout(); } }
Ahora llame al
setDialogBorder(dialog)
método ensetupDialog()
método de su clase BottomsheetDialogFragment.Ahora cree un archivo de forma en su carpeta dibujable.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="20dp" /> <solid android:color="@color/white" /> <stroke android:width="1dp" android:color="@color/transparent" /> </shape>
Ahora configure el fondo para la vista del cuadro de diálogo del grupo de vistas principal en un archivo xml.
android:background="@drawable/round_border_white"
¡¡Hecho!!
fuente
agregue forma con la esquina redondeada, conviértalo en fondo para su diseño raíz
<?xml version="1.0" encoding="utf-8" ?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:topLeftRadius="@dimen/padding_margin_16_dp" android:topRightRadius="@dimen/padding_margin_16_dp" /> <solid android:color="@color/white" /> </shape>
hacer que el fondo sea transparente en su BottomSheetDialogFragment
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) (view?.parent as View).setBackgroundColor(Color.TRANSPARENT) }
su trabajo para Contraintlayout, Framelyaout, Linearlayout, Relativelayout.
fuente
Otra forma de solucionar este problema es ampliar BottomSheetDialog y crear una clase personalizada que se adapte a sus necesidades. Puede hacer lo mismo para el archivo xml de diseño y agregar fondo o cualquier otra personalización necesaria. Esto también tiene la ventaja de que no dependerá de los nombres de identificación utilizados por Android (android.support.design.R.id.design_bottom_sheet), mientras cambia el fondo (aunque el cambio de nombre de identificación rara vez ocurre AFAIK).
fuente
Cree un elemento de diseño personalizado con esquinas redondeadas y configúrelo como fondo de la raíz de diseño de su BottomSheetDialogFragment
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary" /> <corners android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" android:topLeftRadius="12dp" android:topRightRadius="12dp" /> </shape>
Y luego simplemente agregue el siguiente código a su clase BottomSheetDialogFragment
@Override public void setupDialog(Dialog dialog, int style) { super.setupDialog(dialog, style); View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sheet, null); dialog.setContentView(contentView); CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()) .getLayoutParams(); CoordinatorLayout.Behavior behavior = params.getBehavior(); ((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent)); }
Incluso puede jugar con los parámetros para establecer el margen como se muestra a continuación
params.setMargins(50, 0, 50, 0);
fuente
Tienes que cambiar
bottom sheet theme
para lograr el diseño redondo superiorCree un background_bottom_sheet_dialog_fragment.xml de diseño personalizado:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:topLeftRadius="8dp" android:topRightRadius="8dp" /> <padding android:top="0dp" /> <solid android:color="@color/white" /> </shape>
Luego anule bottomSheetDialogTheme en styles.xml usando el elemento de diseño como fondo:
<!--Bottom sheet--> <style name="BottomSheet" parent="@style/Widget.Design.BottomSheet.Modal"> <item name="android:background">@drawable/background_bottom_sheet_dialog_fragment </item> </style> <style name="BaseBottomSheetDialog" parent="@style/Theme.Design.Light.BottomSheetDialog"> <item name="android:windowIsFloating">false</item> <item name="bottomSheetStyle">@style/BottomSheet</item> </style> <style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />
Esto cambiará el diseño de fondo de su hoja inferior
BottomSheetDialog
class SheetFragment() : BottomSheetDialogFragment() { lateinit var binding: SheetFragmentBinding; override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog; val view = View.inflate(context, R.layout.fragment_bottom_sheet, null); binding = DataBindingUtil.bind(view)!!; binding.viewModel = SheetFragmentVM(); dialog.setContentView(view); var bottomSheetBehavior = BottomSheetBehavior.from(view.parent as View); bottomSheetBehavior.setPeekHeight(BottomSheetBehavior.PEEK_HEIGHT_AUTO); bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { if (BottomSheetBehavior.STATE_EXPANDED == newState) { // do on STATE_EXPANDED } if (BottomSheetBehavior.STATE_COLLAPSED == newState) { // do on STATE_COLLAPSED } if (BottomSheetBehavior.STATE_HIDDEN == newState) { dismiss() } } override fun onSlide(bottomSheet: View, slideOffset: Float) { // do on slide } }) return dialog }
fuente