[android] BottomSheetDialogFragment의 상태를 확장 됨으로 설정
Android 지원 디자인 라이브러리 (v23.2.1)를 BottomSheetDialogFragment
사용 BottomSheetBehavior#setState(STATE_EXPANDED)
하여 확장 으로 확장 되는 조각의 상태를 어떻게 설정 합니까?
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);
답변
“뷰 레이아웃 전에는 메소드를 호출 할 수 없습니다.”
위의 텍스트가 단서입니다.
대화 상자에는 대화 상자가 표시 되면 시작되는 리스너가 있습니다. 배치되어 있지 않으면 대화 상자를 표시 할 수 없습니다.
따라서 onCreateDialog()
모달 하단 시트 ( BottomSheetFragment
)에서 대화 상자를 반환하기 직전에 (또는 대화 상자에 대한 참조가 있으면 어디에서나) 다음을 호출하십시오.
// 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;
}
}
이것이 도움이되는지 알려주세요.
최신 정보
다음 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의 대답은, 그러나, 중대하다 onCreateView을 () 로가는 반대로, 당신의 BottomSheet을 만들 이 onCreateDialog () , 여기 당신이 아래에 추가해야합니다 코드입니다 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
이를 해결하기 위해 하위 분류 될 수 있습니다.
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
경우로 변경 합니다 .
답변
위의 것이 더 좋다고 생각합니다. 슬프게도 나는 해결하기 전에 그러한 해결책을 찾지 못했습니다. 하지만 내 솔루션을 작성하십시오. 모두 비슷합니다.
================================================ ===============================
나는 같은 문제에 직면 해있다. 이것이 제가 해결 한 것입니다. 동작은 동작을 얻을 수있는 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()
}
}
답변
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);
}
});
null을 반환 BottomSheetBehavior.from(bottomSheet)
하기 때문에 NullPointException을 만났습니다 d.findViewById(android.support.design.R.id.design_bottom_sheet)
.
이상 해요. 이 코드 줄을 DEBUG 모드에서 Android Monitor의 Watches에 추가하고 정상적으로 Framelayout을 반환합니다.
wrapInBottomSheet
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;
}
때때로, 나는 발견 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이 없습니다.
답변
BottomsheetDialogFragment
상태를 적용 onResume
하면이 문제가 해결됩니다.
@Override
public void onResume() {
super.onResume();
if(mBehavior!=null)
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
onShow(DialogInterface dialog)
및 postDelayed
애니메이션 결함이 발생할 수 있습니다
답변
onShow ()를 사용한 모든 결과는 소프트 키보드가 표시 될 때 임의의 렌더링 버그를 유발합니다. 아래 스크린 샷 참조-BottomSheet 대화 상자는 화면 하단에 있지 않지만 키보드가 표시된 것처럼 배치됩니다. 이 문제는 항상 발생하는 것은 아니지만 자주 발생합니다.
최신 정보
개인 회원을 반영한 나의 솔루션은 불필요합니다. 소프트 키보드 숨기기 후 대화 상자를 만들고 표시하기 위해 postDelayed (약 100ms)를 사용하는 것이 더 나은 솔루션입니다. 그런 다음 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());
}
....
}