Runde Ecke für BottomSheetDialogFragment

101

Ich habe ein benutzerdefiniertes BttomSheetDialogFragment und ich möchte runde Ecken oben in der Ansicht von unten haben

Dies ist meine benutzerdefinierte Klasse, die mein Layout aufbläst, das ich von unten anzeigen möchte

View mView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.charge_layout, container, false);
    initChargeLayoutViews();
    return mView;
}

und auch ich habe diese XML-Ressourcendatei als Hintergrund:

<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"/>

Das Problem ist jedoch, dass die Ecken immer noch nicht abgerundet sind, wenn ich diese Ressourcendatei als Hintergrund für das Stammelement meines Layouts festlege

und ich kann den folgenden Code nicht verwenden:

    this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);

Weil der Standardhintergrund von BottomSheetDialog überschrieben wird und über meiner Ansicht von unten keine halbtransparente graue Farbe angezeigt wird

Rasool Ghana
quelle
5
@RasoolGhana - Schauen Sie sich diesen Link an: medium.com/halcyon-mobile/…
Mohit Charadva

Antworten:

208

Erstellen Sie eine benutzerdefinierte Zeichnung 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>

Dann außer Kraft setzen bottomSheetDialogThemeauf styles.xmldie ziehbar als Hintergrund verwenden:

<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>

Dadurch werden alle BottomSheetDialogs Ihrer App geändert.

javiCabanas
quelle
1
Für mich geht das. Ich habe auch festgestellt, dass es vom Layout-Stammelement abhängt. Zuerst hatte ich Kartenansicht als Wurzel (weil ich einen anderen Weg versucht habe, Ecken abzurunden), dann habe ich es in lineares Layout geändert und jetzt funktioniert es perfekt
Ivan Shafran
1
Abstürze auf Android API 17
Morteza Rastgoo
1
Ich würde rounded_dialog& AppModalStyleNamen nicht mit einem Hintergrund verwenden, bei dem nur die oberen Ecken abgerundet sind, da Sie nur erwarten würden, einen solchen Hintergrund mit einem unteren Blattstil zu verwenden. Wie wäre es mit bottomsheet_rounded_background&AppBottomSheetStyle
hmac
2
Hinweis: Wenn Sie in der Stammansicht einen Hintergrund angeben, wird diese Einstellung überschrieben
hmac
1
Kann dies ohne Verwendung eines Themas erfolgen? Wenn ich es benutze Theme.AppCompat.Light.NoActionBar, ändern alle meine UI-Komponenten ihre Farben und ich kann sie nicht überschreiben
Code Wiget
63

Mit der neuen Materialkomponentenbibliothek können Sie die Form Ihrer Komponente mithilfe des shapeAppearanceOverlayAttributs in Ihrem Stil anpassen ( Hinweis: Es ist die Version 1.1.0 erforderlich ).

Verwenden Sie einfach das BottomSheetDialogFragmentÜberschreiben der onCreateViewMethode und definieren Sie dann Ihren benutzerdefinierten Stil für Bottom Sheet-Dialoge.

Definieren Sie das bottomSheetDialogThemeAttribut styles.xmlin Ihrem App-Thema:

  <!-- 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>

Dann definieren Sie einfach Ihre Lieblingsform mit 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>

Geben Sie hier die Bildbeschreibung ein


Sie können dasselbe Verhalten erzielen, das diese Methode in Ihrem überschreibt BottomSheetDialogFragment(anstatt das bottomSheetDialogThemein Ihrem App-Design hinzuzufügen ):

@Override public int getTheme() {
    return R.style.CustomBottomSheetDialog;
  }

In diesem Fall verwenden Sie dieses themeOverlay nur in der einzelnen BottomSheetDialogFragmentund nicht in der gesamten App.


Wichtiger Hinweis zum ERWEITERTEN STAAT :

Im erweiterten Zustand hat das BottomSheet flache Ecken . Sie können den offiziellen Kommentar in Github Repo überprüfen :

Unser Designteam ist der festen Überzeugung, dass abgerundete Ecken auf scrollbaren Inhalt hinweisen, während flache Ecken darauf hinweisen, dass kein zusätzlicher Inhalt vorhanden ist. Daher möchten sie nicht, dass wir diese Änderung mit fitToContents hinzufügen.

Dieses Verhalten wird von der bereitgestellt BottomSheetBehaviorund kann nicht überschrieben werden.
Es gibt jedoch eine Problemumgehung -> HAFTUNGSAUSSCHLUSS: Es kann in den nächsten Versionen nicht mehr funktionieren !!

Sie können ein hinzufügen BottomSheetCallbackin BottomSheetDialogFragment:

  @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;
  }
Gabriele Mariotti
quelle
2
@GabrieleMariotti mit dieser Technik, wenn ich irgendwo auf das Blatt tippe und es nicht entlassen wird, werden die Ecken weg animiert. Ich bin nicht sicher, ob Sie auf den Android-Materialkomponenten entwickeln, aber wenn ja, wussten Sie von diesem Problem? Ich habe 1.1.0-alpha10 verwendet, aber ich habe auch gerade beta2 überprüft. Ich bin mir nicht sicher, ob es von den genauen Ansichten abhängt, die ich in das Blatt eingefügt habe oder nicht.
AndroidGy
1
Ich habe dieses Problem gemeldet: issuetracker.google.com/issues/144859239 Wenn jemand weitere Erkenntnisse oder Lösungen für das Problem hat, antworten Sie bitte. Vielen Dank!
AndroidGy
2
Ich erhalte diesen Fehler und stürze auf v1.1.0-beta02Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior
hkchakladar
3
Es funktioniert nicht, wenn das Dialogfeld für das untere Blatt erweitert wird. Irgendeine Idee?
José Carlos
2
Dies war die perfekte und neueste Antwort. Ich muss dies als Antwort markieren
Vikas Acharya
33

Das BottomSheetDialogist eine Standard - weiße Hintergrundfarbe einstellen, deshalb die Ecken nicht sichtbar sind, Um ihnen zu zeigen , was Sie brauchen durch Überschreiben der Stil der den Hintergrund des Dialogs transparent zu machen BottomSheetDialog.

Definieren Sie diesen Stil in Ihrem 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>

Und setzen Sie diesen Stil auf Ihren 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();
Badr
quelle
1
Besser als die akzeptierte Antwort, da Sie auf diese Weise unterschiedliche Hintergründe in verschiedenen BottomSheetDialogs haben können
Luke
Jetzt Kurve sichtbar, aber eine transparente Farbe auf dem gesamten Bildschirm bei Berührung nur die weiße Farbe im unteren Dialogfeld ist sichtbar @Badr irgendeine Korrektur?
Arnold Brown
26

Erstellen Sie eine Form mit dem Namen round_corners_shape

<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>

Definieren Sie einen Stil

  <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>

Verwenden Sie diesen Stil auf Ihrem benutzerdefinierten BottomSheetDialogFragment wie folgt, es wird funktionieren!

 public class CustomDialogFragment extends BottomSheetDialogFragment {
      @Override
      public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style. AppBottomSheetDialogTheme);
      }

      ...
    }
zhimin
quelle
Es wäre hilfreich, wenn Sie dem Code einige Erläuterungen hinzufügen würden.
UditS
Dies ist der richtige Ort, um ein Thema für Fragments festzulegen.
DYS
9

Wenn Sie die letzte Version der Materialkomponente verwenden, müssen Sie nur überschreiben ShapeAppearance.MaterialComponents.LargeComponent(da das untere Blatt diese Form verwendet) und den gewünschten Wert festlegen:

 <style name="ShapeAppearance.YourApp.LargeComponent" parent="ShapeAppearance.MaterialComponents.LargeComponent">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">12dp</item>
 </style>

Und dann in Ihrem App-Stil einstellen:

<item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.YourApp.LargeComponent</item>

Die Lösung von Gabriele Mariotti ist ähnlich und funktioniert auch, aber diese ist einfacher.

Benjamin Ledet
quelle
Im Vergleich zu anderen ist es eine viel bessere Lösung, da der größte Teil der Lösung auf dem Set basiert und benutzerdefiniert gezeichnet werden kann
D-Feverx
Sieht gut aus. Gilt das auch für BottomSheetDialog?
Jaden Gu
8

Ich habe heute dasselbe überprüft und ja, Sie hatten Recht, wenn Sie dem Code folgen

this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);

Dies gilt für Fragmenthintergründe. Stattdessen sollten Sie die Bottomsheet-Ansicht aus dem Dialogfenster abrufen und den Hintergrund ändern. Hier ist der Code

 @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);
    }

Hier ist das untere Blatt die tatsächliche Ansicht, die Sie ändern möchten.

Aashish Bhatnagar
quelle
Nur so habe ich das zum Laufen gebracht. Übrigens benutze ich BottomSheetDialogFragmentso, dass Logik in der onCreateDialogMethode ist
Kirill Starostin
8

Antwort von Koma Yip von einer anderen Frage, die für mich funktioniert hat, sollten Sie versuchen.

Erstellen Sie eine XML-Datei in drawable, z. B. dialog_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white"/>
    <corners android:radius="30dp" />
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp" />
</shape>

Fügen Sie dies in Ihren Layout-XML-Stammknoten ein:

Legen Sie es als Hintergrund in Ihrer Layout-XML fest

android:background="@drawable/dialog_bg"

und onCreateView()setzen Sie dies ein:

Setzen Sie den Hintergrund Ihres Dialogs auf transparent

dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Variag
quelle
Dies sollte die richtige Lösung sein, da es für alle DialogFragments funktioniert, ohne durch Reifen zu springen.
Jssingh
2
Für mich gibt es immer noch weiße Ecken hinter meinen abgerundeten Ecken. Wenn ich also die Farbe meines Zeichens in Rot ändere, funktioniert Ihr Code korrekt und erstellt ein abgerundetes rotes Rechteck. Dahinter befindet sich jedoch immer noch ein weißes Standardrechteck. Der von Ihnen geschriebene Code "dialog.getWindow (). SetBackgroundDrawable ..." ändert die Farbe des gesamten "abgedunkelten" Bereichs über meinem Dialog, aber auch hier fehlen diese beiden kleinen Ecken. Wissen Sie, was dieses Problem verursachen könnte?
Nick Dev
Als Ergänzung zu meinem obigen Kommentar sollte ich beachten, dass ich den Code in onCreateView () in " getDialog () .getWindow () ..." ändern musste , damit mein Code ausgeführt werden konnte. Vielleicht funktioniert es deshalb bei mir nicht.
Nick Dev
1
@NickDev Stellen Sie eine neue Frage, wenn Sie der Meinung sind, dass diese Lösung nicht für Ihren Code gilt, und wir möglicherweise eine Lösung finden.
Variag
@Variag Danke, dass du dich gemeldet hast; Ich habe mir tatsächlich eine billige Problemumgehung ausgedacht, bei der ich den modalen Standarddialog für das untere Blatt mit einem Rechteck abdeckte, das dieselbe Farbe wie der abgedunkelte Bereich dahinter hat. Dann fügte ich ein zweites Rechteck mit abgerundeten Ecken hinzu. Es ist nicht ideal, aber es sieht gut aus! Ich schätze die Hilfe trotzdem.
Nick Dev
4

Diese Antwort gilt nur für das Problem, dass die Hintergrundfarbe Color.TRANSPARENTnach dem Einrichten eines Zeichnungszeichens mit abgerundetem Hintergrund für das Layout festgelegt wird.

Keine der Antworten funktionierte für mich, um die Hintergrundfarbe einzustellen, Color.TRANSPARENTaußer der überschreibenden setupDialog()Lösung:

@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));
}

ABER das, was contentViewSie hier für den Dialog eingestellt haben, ist nicht das view, in das Sie onViewCreated()beim Aufblasen gelangen onCreateView(). Es bricht den Standardablauf, so Störungen ausgeben kann , wie Sie nicht verwenden können View Bindings- Kotlin Android ExtensionsinonViewCreated()

Also habe ich ein bisschen gezwickt, um den Hintergrund einzustellen onActivityCreated():

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    (view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
  }

Hoffe diese Hilfe, die die gleichen Probleme bekam

DuDu
quelle
4
  1. Erstellen Sie eine Form zum Zeichnen. Diese wird als Hintergrund für das untere Blatt verwendet. Geben Sie den entsprechenden Wert für den Radius der oberen linken und rechten Ecke an.

    <?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>
  2. Erstellen Sie nun einen Stil für "Dialogfragment des unteren Blattes".

    <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" />
  3. Erstellen Sie nun eine benutzerdefinierte Klasse, die BottomSheetDilogFragment erweitert, in der Sie Ihren Stil angeben.

    open class CustomRoundBottomSheet : BottomSheetDialogFragment() {
    
        override fun getTheme(): Int = R.style.BottomSheetDialogTheme
    
        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme)
    
    }
  4. Verwenden Sie diese Klasse jetzt überall dort, wo Sie ein unteres Blatt mit runden Ecken haben möchten. z.B

    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)
        }
    
    } 
Mini-Chip
quelle
1

Fügen Sie diese beiden Methoden in Ihre BottomsheetDialogFragment-Klasse ein.

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();
        }
    }

Rufen Sie nun die setDialogBorder(dialog)Methode in der setupDialog()Methode Ihrer BottomsheetDialogFragment-Klasse auf.

Erstellen Sie nun eine Formdatei in Ihrem Zeichenordner.

<?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>

Legen Sie nun den Hintergrund für die übergeordnete Ansichtsgruppendialogansicht in der XML-Datei fest.

android:background="@drawable/round_border_white"

Getan!!

DalveerSinghDaiya
quelle
Welche Ansicht verwenden Sie mit setMargins?
tmm1
FrameLayout bottomSheet; Dieser wird in der Methode setDialogBorder () definiert. Dies ist eigentlich die Standardansicht für das untere Blatt Dialogfeld in Android. Es wird gut funktionieren.
DalveerSinghDaiya
0

Eine andere Möglichkeit, dieses Problem zu beheben, besteht darin, BottomSheetDialog zu erweitern und eine benutzerdefinierte Klasse zu erstellen, die Ihren Anforderungen entspricht. Sie können dasselbe für die Layout-XML-Datei tun und Hintergrundinformationen oder andere erforderliche Anpassungen hinzufügen. Dies hat auch den Vorteil, dass Sie nicht von den von Android verwendeten ID-Namen (android.support.design.R.id.design_bottom_sheet) abhängig sind, während Sie den Hintergrund ändern (obwohl die Änderung des ID-Namens selten AFAIK erfolgt).

Gaurav Jain
quelle
0

Erstellen Sie eine benutzerdefinierte Zeichnung mit abgerundeten Ecken und legen Sie sie als Hintergrund für das Layout-Stammverzeichnis Ihres BottomSheetDialogFragment fest

<?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>

Fügen Sie dann einfach den folgenden Code zu Ihrer BottomSheetDialogFragment-Klasse hinzu

@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));
}

Sie können sogar mit den Parametern spielen, um den Rand wie unten festzulegen

params.setMargins(50, 0, 50, 0);
Darshna Desai
quelle
0

Sie müssen das ändern bottom sheet theme, um das Top-Round-Layout zu erreichen

Erstellen Sie eine benutzerdefinierte zeichnbare Datei background_bottom_sheet_dialog_fragment.xml:

<?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>

Überschreiben Sie dann bottomSheetDialogTheme in styles.xml mit dem Zeichen als Hintergrund:

<!--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" />

Dadurch wird das Hintergrundlayout Ihres unteren Blattes geändert

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
}
Atul
quelle
0

Ich weiß, dass diese Frage bereits eine akzeptierte Antwort hat. Ich möchte die Probleme dokumentieren, die ich durchgemacht habe, und wie ich es endlich zum Laufen gebracht habe, damit es für jemanden in der Zukunft nützlich ist.

Erstens habe ich Theme.AppCompat.Light.DarkActionBarals Elternteil für unsere verwendet AppTheme. Dies bedeutete, dass die @ Gabriele Mariotti-Lösung immer wieder mit dem Fehler abstürzte Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior. Ich habe dies behoben, indem ich einfach das übergeordnete Element in geändert habe Theme.MaterialComponents.Light.DarkActionBar. Dies hatte keinerlei Auswirkungen auf unser Thema, aber die RTE war weg. Sie können dieses Problem auch beheben, indem Sie einfach die erforderlichen Elemente in Ihren Stil aufnehmen. Aber ich habe mich nicht darum gekümmert, herauszufinden, welche Stile von BottomSheetBehavior benötigt werden.

Zweitens versuchen Sie es wie ich könnte, aber ich konnte nicht das tatsächliche Frame-Layout (das BottomSheetDialogFragment war) verwenden, um runde Ecken zu haben. Ich erkannte, dass das Setzen eines Bildes Drawable funktionierte, aber nicht mit einer Form oder einem @null. Es stellte sich heraus, dass der von LinearLayoutmir verwendete Hintergrund definiert war. Dies überschrieb jeden Hintergrund im Stil. Das Entfernen führte schließlich zu abgerundeten Ecken.

Außerdem musste keine Hintergrundform eingestellt werden, um die Ecken abzurunden. Die Lösung von @Gabriele Mariotti funktionierte, sobald ich die obigen Änderungen vorgenommen hatte. Um die Hintergrundfarbe so einzustellen, wie ich sie haben wollte, musste ich das Element "backgroundTint" überschreiben.

PS: Ich bin neu in der Android-Entwicklung und pflege eine alte App, die für den internen Gebrauch in unserem College entwickelt wurde. Ich bin mit dem Layoutsystem von Android oder der Materialbibliothek nicht allzu vertraut. Ich denke, deshalb habe ich 3 Tage gebraucht, um das herauszufinden. Ich hoffe, dass dies in Zukunft für jemanden nützlich ist.

abhijeetviswa
quelle
0

Es hat bei mir funktioniert

Erstellen Sie eine Form mit dem Namen shape_rounded_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" />

füge unten Stile hinzu

<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>

In der Klasse DialogFragment gibt die Methodenüberschreibung getTheme auch den Yourself-Stil zurück.

@Override
public int getTheme() {
    return R.style.AppBottomSheetDialogTheme;
}
Mohamad
quelle