"Beachten Sie, dass Sie die Methode nicht vor dem Anzeigen von Layouts aufrufen können."
Der obige Text ist der Hinweis.
Dialoge haben einen Listener, der ausgelöst wird, sobald der Dialog angezeigt wird . Der Dialog kann nicht angezeigt werden, wenn er nicht angelegt ist.
Rufen Sie also in onCreateDialog()
Ihrem modalen unteren Blatt ( BottomSheetFragment
) kurz vor dem Zurücksenden des Dialogfelds (oder irgendwo, sobald Sie einen Verweis auf das Dialogfeld haben) Folgendes auf:
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet)
.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
In meinem Fall stellte BottomSheet
sich heraus, dass mein Brauch :
@SuppressWarnings("ConstantConditions")
public class ShareBottomSheetFragment extends AppCompatDialogFragment {
@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog =
new BottomSheetDialog(getActivity(), R.style.Haute_Dialog_ShareImage);
dialog.setContentView(R.layout.dialog_share_image);
dialog.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
SwitchCompat switchview = (SwitchCompat) dialog.findViewById(R.id.switchview);
switchview.setTypeface(FontCache.get(dialog.getContext(), lookup(muli, NORMAL)));
return dialog;
}
}
Lassen Sie mich wissen, ob das hilft.
AKTUALISIEREN
Beachten Sie, dass Sie Folgendes überschreiben können BottomSheetDialogFragment
:
public class SimpleInitiallyExpandedBottomSheetFragment extends BottomSheetDialogFragment {
@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
return dialog;
}
}
Aber ich verstehe wirklich nicht, warum irgendjemand das tun möchte, da die Basis BottomSheetFragment
nichts anderes tut, als a zurückzugeben BottomSheetDialog
.
UPDATE FÜR ANDROIDX
Bei Verwendung von AndroidX kann die zuvor gefundene Ressource android.support.design.R.id.design_bottom_sheet
jetzt unter gefunden werden com.google.android.material.R.id.design_bottom_sheet
.
BottomSheetDialogFragment
Bild ruckelig erscheinen (scheint Frames in der Eröffnungsanimation zu überspringen), wenn es vom reduzierten zum erweiterten Verhalten übergeht. Bearbeiten: Getestet auf Android Marshmallow und KitKat Gerätenandroid.support.design.R
nach dem Aktualisieren der Support-Bibliotheken nur kein Paket finden ?android.support.design.R
, genau wie @natario. Ich benutzeimplementation "com.google.android.material:material:1.0.0"
. Ich benutze auch AndroidX im Projekt.com.google.android.material.R.id.design_bottom_sheet
Die Antwort von efeturi ist großartig. Wenn Sie jedoch onCreateView () zum Erstellen Ihres BottomSheet verwenden möchten, anstatt mit onCreateDialog () zu arbeiten , müssen Sie den folgenden Code unter Ihrer onCreateView () -Methode hinzufügen :
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { getDialog().setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; View bottomSheetInternal = d.findViewById(android.support.design.R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheetInternal).setState(BottomSheetBehavior.STATE_EXPANDED); } }); return inflater.inflate(R.layout.your_bottomsheet_content_layout, container, false); }
quelle
Eine einfache und elegante Lösung:
BottomSheetDialogFragment
könnte in Unterklassen unterteilt werden, um dies zu beheben:class NonCollapsableBottomSheetDialogFragment extends BottomSheetDialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState); bottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet); BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); behavior.setSkipCollapsed(true); behavior.setState(BottomSheetBehavior.STATE_EXPANDED); } }); return bottomSheetDialog; } }
Erweitern Sie also diese Klasse, anstatt
BottomSheetDialogFragment
Ihr eigenes unteres Blatt zu erstellen.Hinweis
Wechseln Sie
com.google.android.material.R.id.design_bottom_sheet
zu,android.support.design.R.id.design_bottom_sheet
wenn Ihr Projekt alte Android-Unterstützungsbibliotheken verwendet.quelle
com.google.android.material.R
jetzt statt zu seinandroid.support.design.R
.Ich denke, die oben genannten sind besser. Leider habe ich diese Lösung nicht gefunden, bevor ich sie gelöst hatte. Aber schreibe meine Lösung. ganz ähnlich zu allen.
================================================== ===============================
Ich stehe vor dem gleichen Problem. Das habe ich gelöst. Das Verhalten ist in BottomSheetDialog ausgeblendet, das zum Abrufen des Verhaltens verfügbar ist. Wenn Sie Ihr übergeordnetes Layout nicht in CooridateLayout ändern möchten, können Sie dies versuchen.
SCHRITT 1: Passen Sie das BottomSheetDialogFragment an
open class CBottomSheetDialogFragment : BottomSheetDialogFragment() { //wanna get the bottomSheetDialog protected lateinit var dialog : BottomSheetDialog override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog return dialog } //set the behavior here fun setFullScreen(){ dialog.behavior.state = STATE_EXPANDED } }
SCHRITT 2: Lassen Sie Ihr Fragment dieses angepasste Fragment erweitern
class YourBottomSheetFragment : CBottomSheetDialogFragment(){ //make sure invoke this method after view is built //such as after OnActivityCreated(savedInstanceState: Bundle?) override fun onStart() { super.onStart() setFullScreen()//initiated at onActivityCreated(), onStart() } }
quelle
dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED); } });
Ich habe NullPointException in getroffen,
BottomSheetBehavior.from(bottomSheet)
weild.findViewById(android.support.design.R.id.design_bottom_sheet)
null zurückgegeben wird.Es ist komisch. Ich habe diese Codezeile im DEBUG-Modus zu Watches in Android Monitor hinzugefügt und festgestellt, dass sie Framelayout normal zurückgibt.
Hier ist der Code von
wrapInBottomSheet
in BottomSheetDialog:private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) { final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(), R.layout.design_bottom_sheet_dialog, null); if (layoutResId != 0 && view == null) { view = getLayoutInflater().inflate(layoutResId, coordinator, false); } FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet); BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback); if (params == null) { bottomSheet.addView(view); } else { bottomSheet.addView(view, params); } // We treat the CoordinatorLayout as outside the dialog though it is technically inside if (shouldWindowCloseOnTouchOutside()) { coordinator.findViewById(R.id.touch_outside).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (isShowing()) { cancel(); } } }); } return coordinator; }
Gelegentlich stellte ich fest, dass
R.id.design_bottom_sheet
das nicht gleich istandroid.support.design.R.id.design_bottom_sheet
. Sie haben unterschiedliche Werte in unterschiedlichen R.java.Also wechsle ich
android.support.design.R.id.design_bottom_sheet
zuR.id.design_bottom_sheet
.dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.design_bottom_sheet); // use R.java of current project BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED); } });
Keine NullPointException mehr.
quelle
BottomsheetDialogFragment
Status anwenden inonResume
wird dieses Problem lösen@Override public void onResume() { super.onResume(); if(mBehavior!=null) mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); }
onShow(DialogInterface dialog)
undpostDelayed
kann Animationsfehler verursachenquelle
Alle Ergebnisse bei Verwendung von onShow () verursachen einen zufälligen Renderfehler, wenn eine weiche Tastatur angezeigt wird. Siehe Screenshot unten - Das Dialogfeld "BottomSheet" befindet sich nicht am unteren Bildschirmrand, sondern wird so platziert, als ob die Tastatur angezeigt wurde. Dieses Problem tritt nicht immer, sondern häufig auf.
AKTUALISIEREN
Meine Lösung mit Reflexion eines privaten Mitglieds ist unnötig. Die Verwendung von postDelayed (mit ca. 100 ms) zum Erstellen und Anzeigen von Dialogen nach dem Ausblenden der Softtastatur ist die bessere Lösung. Dann sind die obigen Lösungen mit onShow () in Ordnung.
Utils.hideSoftKeyboard(this); mView.postDelayed(new Runnable() { @Override public void run() { MyBottomSheetDialog dialog = new MyBottomSheetDialog(); dialog.setListener(MyActivity.this); dialog.show(getSupportFragmentManager(), TAG_BOTTOM_SHEET_DLG); } }, 100);
Also implementiere ich eine andere Lösung, aber es erfordert die Verwendung von Reflection, da BottomSheetDialog alle Mitglieder als privat hat. Aber es löst Renderfehler. Die BottomSheetDialogFragment-Klasse ist nur AppCompatDialogFragment mit der onCreateDialog-Methode, die BottomSheetDialog erstellt. Ich erstelle ein eigenes Kind von AppCompatDialogFragment, das meine Klasse erstellt, erweitert BottomSheetDialog und löst den Zugriff auf private Verhaltensmitglieder und setzt es in der onStart-Methode auf den Status STATE_EXPANDED.
public class ExpandedBottomSheetDialog extends BottomSheetDialog { protected BottomSheetBehavior<FrameLayout> mBehavior; public ExpandedBottomSheetDialog(@NonNull Context context, @StyleRes int theme) { super(context, theme); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { Field privateField = BottomSheetDialog.class.getDeclaredField("mBehavior"); privateField.setAccessible(true); mBehavior = (BottomSheetBehavior<FrameLayout>) privateField.get(this); } catch (NoSuchFieldException e) { // do nothing } catch (IllegalAccessException e) { // do nothing } } @Override protected void onStart() { super.onStart(); if (mBehavior != null) { mBehavior.setSkipCollapsed(true); mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); } } } public class AddAttachmentBottomSheetDialog extends AppCompatDialogFragment { .... @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new ExpandedBottomSheetDialog(getContext(), getTheme()); } .... }
quelle
Der einfachste Weg, den ich implementiert habe, ist wie folgt: Hier finden wir android.support.design.R.id.design_bottom_sheet und setzen den Status des unteren Blattes auf EXPANDED .
Ohne dies blieb mein unteres Blatt immer im Status COLLAPSED hängen, wenn die Ansichtshöhe mehr als 0,5 der Bildschirmhöhe beträgt und ich manuell scrollen muss, um das vollständige untere Blatt anzuzeigen.
class BottomSheetDialogExpanded(context: Context) : BottomSheetDialog(context) { private lateinit var mBehavior: BottomSheetBehavior<FrameLayout> override fun setContentView(view: View) { super.setContentView(view) val bottomSheet = window.decorView.findViewById<View>(android.support.design.R.id.design_bottom_sheet) as FrameLayout mBehavior = BottomSheetBehavior.from(bottomSheet) mBehavior.state = BottomSheetBehavior.STATE_EXPANDED } override fun onStart() { super.onStart() mBehavior.state = BottomSheetBehavior.STATE_EXPANDED } }
quelle
Ähnlich wie bei uregentx answer können Sie in kotlin Ihre Fragmentklasse deklarieren, die sich von erstreckt
BottomSheetDialogFragment
, und beim Erstellen der Ansicht können Sie den Standardstatus des Dialoglisteners festlegen , nachdem der Dialog angezeigt wurde.class FragmentCreateGroup : BottomSheetDialogFragment() { ... override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? { // Set dialog initial state when shown dialog?.setOnShowListener { val bottomSheetDialog = it as BottomSheetDialog val sheetInternal: View = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet)!! BottomSheetBehavior.from(sheetInternal).state = BottomSheetBehavior.STATE_COLLAPSED } val view = inflater.inflate(R.layout.fragment_create_group, container, false) ... return view } }
Denken Sie daran, die Implementierung des Materialdesigns in Gradle zu verwenden.
Beachten Sie auch die Materialdesign-Referenz Bottom Sheets
quelle
dialog?
Variable in onCreateView?dialog
ist eine Eigenschaft der KlasseDialogFragment
, ist eigentlich ein Getter. In diesem Beispiel habe ich diesen Getter verwendet, um die aktuelle DialogFragment-Instanz undsetOnShowListener
darauf abzurufen . Möglicherweise haben Sie diese Art von Anweisungen bereits in Ihrem Projekt verwendet, z. B. in einer Aktivität, um auf den Aktionsbalken-actionBar
Getter zuzugreifen , sodass Sie diese Komponente beispielsweise ändern könnenactionBar?.subtitle = "abcd"
Meine Antwort ist mehr oder weniger dieselbe wie die meisten der oben genannten Antworten mit einer geringfügigen Änderung. Anstatt findViewById zu verwenden, um zuerst die untere Blattansicht zu finden, habe ich es vorgezogen, keine Ressourcen-IDs der Framework-Ansicht fest zu codieren, da sie sich in Zukunft möglicherweise ändern.
setOnShowListener(dialog -> { BottomSheetBehavior bottomSheetBehavior = ((BottomSheetDialog)dialog).getBehavior(); bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); });
quelle
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return super.onCreateDialog(savedInstanceState).apply { setOnShowListener { (this@TipsBottomDialogFragment.dialog as BottomSheetDialog).behavior.setState( BottomSheetBehavior.STATE_EXPANDED ) } } }
quelle
Wenn Sie dies hier an zukünftige Leser senden, wissen wir, dass wir eine andere Lösung verwenden können.
Ich habe versucht, das gleiche Problem zu lösen, das Sie mit a beschrieben haben
BottomSheetDialog
.Ich mag es nicht, interne Android-IDs zu verwenden, und ich habe gerade festgestellt, dass es eine Methode gibt
BottomSheetDialog
getBehavior
, die Sie verwenden können:Sie können dies in Ihrem verwenden
BottomSheetDialog
:behavior.state = BottomSheetBehavior.STATE_EXPANDED
Mit
BottomSheetDialogFragment
können Sie das gleiche Casting des Dialogs von diesem DialogFragment in ausführenBottomSheetDialog
.quelle
BottomSheetDialogFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) (dialog as? BottomSheetDialog)?.behavior?.state = STATE_EXPANDED }
oder wenn Sie bereit sind zu zeigen:
private fun onContentLoaded(items: List<Any>) { adapter.submitList(items) (dialog as? BottomSheetDialog)?.behavior?.state = STATE_EXPANDED }
quelle
Überschreiben Sie in Ihrer Kotlin BottomSheetDialogFragment-Klasse onCreateDialog wie folgt
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val bottomSheetDialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog bottomSheetDialog.setOnShowListener { val bottomSheet = bottomSheetDialog.findViewById<FrameLayout>( com.google.android.material.R.id.design_bottom_sheet ) val behavior = BottomSheetBehavior.from(bottomSheet!!) behavior.skipCollapsed = true behavior.state = BottomSheetBehavior.STATE_EXPANDED } return bottomSheetDialog }
quelle