Android Support Design Library(v23.2.1)を使用して、BottomSheetBehavior#setState(STATE_EXPANDED)
を使用してBottomSheetDialogFragment
を拡張するフラグメントの状態をどのように設定しますか?
https://code.google.com/p/Android/issues/detail?id=202396 言う:
一番下のシートは、最初はSTATE_COLLAPSEDに設定されています。展開する場合は、BottomSheetBehavior#setState(STATE_EXPANDED)を呼び出します。ビューレイアウトの前にメソッドを呼び出すことはできません。
推奨プラクティス では、最初にビューを拡大する必要がありますが、BottomSheetBehaviourをフラグメント(BottomSheetDialogFragment
)に設定する方法がわかりません。
View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
「ビューレイアウトの前にメソッドを呼び出すことはできません。」
上記のテキストが手掛かりです。
ダイアログには、ダイアログが表示になったときに起動されるリスナーがあります。ダイアログは、レイアウトされていない場合は表示できません。
したがって、モーダルボトムシート(BottomSheetFragment
)のonCreateDialog()
で、ダイアログを返す直前(またはダイアログへの参照を取得したらどこでも)を呼び出します。
// This listener's onShow is fired when the dialog is shown
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
// In a previous life I used this method to get handles to the positive and negative buttons
// of a dialog in order to change their Typeface. Good ol' days.
BottomSheetDialog d = (BottomSheetDialog) dialog;
// This is gotten directly from the source of BottomSheetDialog
// in the wrapInBottomSheet() method
FrameLayout bottomSheet = (FrameLayout) d.findViewById(Android.support.design.R.id.design_bottom_sheet);
// Right here!
BottomSheetBehavior.from(bottomSheet)
.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
私の場合、カスタムBottomSheet
は次のようになりました。
@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;
}
}
これが役立つかどうか教えてください。
UPDATE
次のように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);
}
});
// Do something with your dialog like setContentView() or whatever
return dialog;
}
}
しかし、ベースBottomSheetFragment
はBottomSheetDialog
を返すこと以外は何もしないので、なぜ誰もがそれをしたいのか、本当にわかりません。
ANDROIDXの更新
AndroidXを使用する場合、以前はAndroid.support.design.R.id.design_bottom_sheet
で見つかったリソースがcom.google.Android.material.R.id.design_bottom_sheet
で見つかるようになりました。
efeturiの答えは素晴らしいですが、-onCreateDialog()ではなく、onCreateView()を使用してBottomSheetを作成したい場合は、 onCreateView()メソッドの下に追加する必要があるコードは次のとおりです。
@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);
}
これを処理するBottomSheetDialogFragment
のサブクラスを作成しました。
public 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;
}
}
したがって、BottomSheetDialogFragment
の代わりにこのクラスを拡張して、独自のボトムシートを作成します。
プロジェクトで古いAndroidサポートライブラリを使用している場合は、com.google.Android.material.R.id.design_bottom_sheet
をAndroid.support.design.R.id.design_bottom_sheet
に変更します。
OnResumeでBottomsheetDialogFragment状態を適用すると、この問題が解決します
@Override
public void onResume() {
super.onResume();
if(mBehavior!=null)
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
onShow(DialogInterface dialog)およびpostDelayedがアニメーションの不具合を引き起こす可能性があります
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);
}
});
BottomSheetBehavior.from(bottomSheet)
がnullを返すため、d.findViewById(Android.support.design.R.id.design_bottom_sheet)
でNullPointExceptionに遭遇しました。
変わっている。 DEBUGモードのAndroid MonitorのWatchesにこのコード行を追加すると、Framelayoutが正常に返されることがわかりました。
BottomSheetDialogのwrapInBottomSheet
のコードは次のとおりです。
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;
}
時折、R.id.design_bottom_sheet
がAndroid.support.design.R.id.design_bottom_sheet
と等しくないことがわかりました。それらは異なるR.Javaで異なる値を持ちます。
そこで、Android.support.design.R.id.design_bottom_sheet
をR.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);
}
});
NullPointExceptionはもうありません。
上記の方が良いと思います。悲しいことに、解決する前にそれらの解決策を見つけられませんでした。しかし、私の解決策を書いてください。すべてに非常に似ています。
================================================== ================================
私は同じ問題に直面しています。これが私が解決したことです。動作はBottomSheetDialogで非表示になります。これは動作を取得するために使用できます。親レイアウトをCooridateLayoutに変更したくない場合は、これを試すことができます。
ステップ1:BottomSheetDialogFragmentをカスタマイズする
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
}
}
ステップ2:フラグメントにこのカスタマイズされたフラグメントを拡張させる
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()
}
}
私が実装した最も簡単な方法は次のとおりです。ここでは、Android.support.design.R.id.design_bottom_sheetを見つけて、ボトムシートの状態をEXPANDEDに設定しています。
これがないと、ボトムシート常にCOLLAPSED状態でスタックしていましたビューの高さが画面の高さの0.5を超えており、ボトムシート全体を表示するには手動でスクロールする必要があります。
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
}
}
OnShow()を使用した結果はすべて、ソフトキーボードが表示されたときにランダムレンダリングのバグを引き起こします。以下のスクリーンショットを参照してください-BottomSheetダイアログは画面の下部にありませんが、キーボードが表示されたように配置されます。この問題は常に発生するわけではありませんが、頻繁に発生します。
UPDATE
プライベートメンバーを反映したソリューションは不要です。ソフトキーボードを非表示にした後にダイアログを作成して表示するためにpostDelayed(約100ミリ秒)を使用するのがより良い解決策です。次に、onShow()を使用した上記のソリューションは問題ありません。
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);
したがって、他のソリューションを実装しますが、BottomSheetDialogにはすべてのメンバーがプライベートであるため、リフレクションを使用する必要があります。しかし、それはレンダリングのバグを解決します。 BottomSheetDialogFragmentクラスは、BottomSheetDialogを作成するonCreateDialogメソッドを持つAppCompatDialogFragmentのみです。私は、AppCompatDialogFragmentの独自の子を作成します。これは、クラスを作成し、BottomSheetDialogを拡張し、プライベート動作メンバーへのアクセスを解決し、onStartメソッドで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());
}
....
}
uregentx回答と同様に、kotlinで、BottomSheetDialogFragment
から拡張するフラグメントクラスを宣言できます。ビューが作成されると、ダイアログが表示された後、ダイアログリスナーのデフォルト状態を設定できます。
STATE_COLLAPSED:下のシートは表示されますが、ピークの高さのみが表示されます。
STATE_EXPANDED:下部のシートが表示され、その最大の高さがあります。
STATE_HALF_EXPANDED:下のシートは表示されますが、半分の高さしか表示されません。
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
}
}
Gradleで材料設計の実装を使用することを忘れないでください。
implementation "com.google.Android.material:material:$version"
材料設計のリファレンスもご覧ください ボトムシート