sourcecode

하단의 둥근 모서리SheetDialogFragment

copyscript 2023. 8. 7. 22:54
반응형

하단의 둥근 모서리SheetDialogFragment

나는 Bttom 사용자 지정이 있습니다.SheetDialogFragment와 하단 뷰 위에 둥근 모서리를 갖고 싶습니다.

아래에서 표시할 레이아웃을 부풀리는 사용자 정의 클래스입니다.

View mView;

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

또한 이 XML 리소스 파일을 배경으로 사용합니다.

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

문제는 이 리소스 파일을 레이아웃의 루트 요소의 배경으로 설정해도 모서리가 여전히 둥글지 않다는 것입니다.

아래 코드를 사용할 수 없습니다.

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

맨 아래의 기본 배경을 재정의하기 때문입니다.SheetDialog(시트 대화 상자)를 사용하면 아래쪽 보기 위에 반투명 회색이 표시되지 않습니다.

드로잉 한 만들기 기리가능만들기그지자정기만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>

다음 그런다재의정을 재정의합니다.bottomSheetDialogThemestyles.xml그리기 가능한 배경 사용:

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

이렇게 하면 모든 하단이 변경됩니다.앱의 SheetDialogs.

새로운 재료 구성요소 라이브러리를 사용하면 스타일의 속성을 사용하여 구성요소의 모양을 사용자 정의할 수 있습니다(참고: 버전 1.1.0 이상이 필요함).

우선순위를 사용하면 됩니다.onCreateView방법을 선택한 다음 하단 시트 대화 상자에 대한 사용자 정의 스타일을 정의합니다.

「 」를 합니다.bottomSheetDialogTheme을 입력합니다.styles.xml 테마 테마:

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

그런 다음 원하는 모양을 정의합니다.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>

enter image description here


은 당신의 이메를재동동사수있에서 이 과 같은 수 .BottomSheetDialogFragment)를 bottomSheetDialogTheme 테마 예:

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

에는 "라는 주제를 "Overlay"에서만합니다.단일에서만 오버레이BottomSheetDialogFragment그리고 모든 앱에서는 그렇지 않습니다.


확장 상태에 대한 중요한 참고 사항:

확장된 상태에서 하단시트 모서리가 평평합니다.공식 코멘트는 githubrepo에서 확인할 수 있습니다.

우리 디자인 팀은 둥근 모서리는 스크롤 가능한 콘텐츠를 나타내고 평평한 모서리는 추가 콘텐츠가 없음을 나타내는 것으로 강하게 생각합니다.따라서, 그들은 우리가 이 변경 사항을 fitToContents로 추가하는 것을 원하지 않습니다.

은 이동은통제다니됩에 의해 됩니다.BottomSheetBehavior그리고 그것을 무시하는 것은 불가능합니다.
그러나 해결 방법이 있습니다. -> 고지 사항: 다음 릴리스에서 작동을 중지할 수 있습니다!

추가할 수 있습니다.BottomSheetCallback에 시대에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;
  }

BottomSheetDialog는 기본 때문에 . 의 배경을 합니다. 그래서 모서리가 보이지 않습니다. 모서리를 표시하려면 대화 상자의 배경을 투명하게 만들어야 합니다.BottomSheetDialog.

의 서이스에서 이 하세요.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>

그리고 이 스타일을 아래로 설정합니다.시트 대화 상자

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

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

스타일을 정의합니다.

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

사용자 정의 맨 아래에 이 스타일 사용이렇게 SheetDialogFragment, 작업이 될 것입니다!

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

      ...
    }

이것은 저에게 효과가 있었습니다.

을 만듭니다(예: 예테만듭다니을블이그기리배경명됨명예▁((다▁create)니듭).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" />
</shape>

아래에 스타일을 추가합니다.

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

의 신의에서.DialogFragment 방을무니다합을 합니다.getTheme()당신의 스타일을 되돌리기 위해.

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

제게 가장 간단하고 깨끗한 솔루션은 fragment 클래스의 ViewCreated(View, Bundle savedInstanceState) 메서드에 다음 4줄을 넣는 것이었습니다.

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    View bottomSheet = (View) view.getParent();
    bottomSheet.setBackgroundTintMode(PorterDuff.Mode.CLEAR);
    bottomSheet.setBackgroundTintList(ColorStateList.valueOf(Color.TRANSPARENT));
    bottomSheet.setBackgroundColor(Color.TRANSPARENT);
}

이렇게 하면 조각 레이아웃의 최상위 보기 배경으로 설정하면 둥근 모서리가 있는 사용자 지정 그리기 가능한 그림이 올바르게 표시됩니다.

기본적으로 이것은 기본적인 Bottom보다 우선합니다.색상, tintMode 및 tintList와 관련된 SheetFragment 특성.

이것을 사용하면 스타일 리소스를 조작할 필요가 없습니다.

재료 구성요소의 마지막 버전을 사용하는 경우에는 우선순위를 변경하면 됩니다.ShapeAppearance.MaterialComponents.LargeComponent모양을 처럼) 합니다.

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

그런 다음 앱 스타일을 설정합니다.

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

가브리엘레 마리오티의 솔루션은 비슷하고 작동하기도 하지만 이것은 더 간단합니다.

1단계:

성을 합니다.res/drawable로명된명라고 rounded_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners
    android:topLeftRadius="32dp"
    android:topRightRadius="32dp" />
  <solid android:color="#D81B60" />
</shape>

2단계:

이 스타일을 만들어 대화 상자 배경을 제거합니다.

<style name="NoBackgroundDialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:windowBackground">@null</item>
</style>

3단계:

사여 대자의 상루가뷰그능트를 사용하여 그리기 의 루트 합니다.setBackgroundResource()우선하여 스타일을 설정합니다.getTheme()방법

Java:

public class MyDialogFragment extends BottomSheetDialogFragment {

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

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null);
        view.setBackgroundResource(R.drawable.rounded_background);
        return view;

    }
}

코틀린:

class MyDialogFragment : BottomSheetDialogFragment() {

    override fun getTheme() = R.style.NoBackgroundDialogTheme

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val view: View = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null)
        view.setBackgroundResource(R.drawable.rounded_background)
        return view
    }

}

결과:

enter image description here

if(보기)setBackgroundResource(R.drawable.rounded_background) 이 줄은 작동하지 않으며 fragment의 Xml 형식 배경을 설정하려고 합니다.

나는 오늘 같은 것을 확인하고 있었고 네 당신이 코드를 따르는 것에 대해 옳았습니다.

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

이것은 조각 배경에 적용되므로 대신 대화창에서 하단 시트 보기를 가져와 배경을 변경해야 합니다. 여기 코드가 있습니다.

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

여기 아래쪽 시트가 변경하려는 실제 보기입니다.

다른 질문에 대한 코마 입의 대답은 저에게 효과가 있었습니다, 당신은 그것을 시도해 보세요.

그리기 가능한 xml(예: 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>

레이아웃 xml 루트 노드에 저장합니다.

레이아웃 xml의 배경으로 설정합니다.

android:background="@drawable/dialog_bg"

그고리로.onCreateView()다음과 같이 입력합니다.

대화 상자의 배경을 투명으로 설정

dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
  1. 도형 그리기 가능한 도형 만들기 ..아래쪽 시트의 배경으로 사용할 것입니다. 왼쪽 위와 오른쪽 모서리의 반지름에 적절한 값을 제공하십시오.

    <?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. 이제 "하단 시트 대화상자 조각"에 대한 스타일을 작성합니다.

    <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. 이제 아래쪽으로 확장할 사용자 지정 클래스를 만듭니다.스타일을 제공하는 SheetDilogFragment.

    open class CustomRoundBottomSheet : BottomSheetDialogFragment() {
    
        override fun getTheme(): Int = R.style.BottomSheetDialogTheme
    
        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme)
    
    }
    
  4. 이제 이 클래스를 둥근 모서리 하단 시트가 있는 곳 어디에서나 사용하십시오.

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

단순한 솔루션:

class TopRoundedCornersFragment : BottomSheetDialogFragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setStyle(STYLE_NORMAL, R.style.AppBottomSheetDialogTheme)
    }
}

styles.xml에서

<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@drawable/bottom_sheet_dialog_bg</item>
</style>

<style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/BottomSheetStyle</item>
</style>

마지막으로 둥근 모서리 그리기 가능 리소스(bottom_sheet_dialog_bg.xml)를 만듭니다.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@android:color/white" />
    <corners
        android:topLeftRadius="4dp"
        android:topRightRadius="4dp" />

</shape>

저는 이 질문이 이미 받아들여진 답을 가지고 있다는 것을 알고 있습니다.저는 제가 겪은 문제들과 제가 어떻게 그것을 최종적으로 작동시켰는지를 문서화해서 미래의 누군가에게 유용하게 쓰고 싶습니다.

첫 번째로, 저는 사용하고 있었습니다.Theme.AppCompat.Light.DarkActionBar 리우부서의 로서.AppTheme는 @것을 의미합니다. @Gabriele Mariotti @Gabriele Marioti 다함류와께계는솔충루이오것의미을이는니합속다돌한션▁this▁error▁kept의다▁@▁with▁meantg이미니합것▁crashing는▁theg을는다.Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior저는 단순히 부모님을 바꾸어서 이것을 고쳤습니다.Theme.MaterialComponents.Light.DarkActionBar이것은 우리의 주제에 어떠한 영향도 주지 않았지만 RTE는 사라졌습니다.스타일에 필요한 항목을 포함하여 이 문제를 해결할 수도 있습니다.을 요구하는지 시트 동작.

두 번째로, 최대한 노력했지만 실제 프레임 레이아웃(아래쪽)을 얻을 수 없었습니다.SheetDialogFragment)는 둥근 모서리를 갖는 데 사용합니다.하는 것은 효과가 이나 모양이 것으로 설정하는 것은 효과가 있었다는 것을 .@null 보니,은 알보니, 그은것 이었습니다.LinearLayout저는 배경이 정의되어 있었습니다.이것은 스타일의 어떤 배경보다도 우선했습니다.그것을 제거하는 것은 마침내 둥근 모서리를 만들었습니다.

또한 모서리를 둥글게 처리하도록 배경 모양을 설정할 필요가 없었습니다.@Gabriele Marotti의 해결책은 제가 위의 변경을 하자마자 효과가 있었습니다.하지만 배경색을 원하는 대로 설정하려면 "backgroundTint" 항목을 오버라이드해야 했습니다.

PS: 저는 안드로이드 개발에 처음이고, 우리 대학에서 내부용으로 만들어진 오래된 앱을 유지하고 있습니다.저는 안드로이드의 레이아웃 시스템이나 자료 라이브러리에 대해 잘 모릅니다.그래서 이걸 알아내는데 3일이나 걸렸나 봐요.나는 이것이 미래의 누군가에게 유용하기를 바랍니다.

이 답변은 배경색을 다음으로 설정하는 문제에 대한 것입니다.Color.TRANSPARENT레이아웃에 둥근 배경이 있는 그리기 가능한 설정 후.

배경색을 다음으로 설정할 수 있는 답이 없습니다.Color.TRANSPARENT우선하는 것을 제외하고.setupDialog() 솔션루:

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

하지만contentView은 여서설대다같음습니다가 .view은 요세에 .onViewCreated()에서 때onCreateView()은 표준 깨기 수 문제와 수 있습니다.View Bindings-Kotlin Android ExtensionsonViewCreated()

그래서 저는 배경을 설정하기 위해 약간 수정합니다.onActivityCreated():

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

같은 문제를 겪은 이 도움을 바랍니다.

곡선 모양 및 피크 높이가 있는 하단 시트 대화 상자

    <!-- BottomSheet Dialog -->
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/CustomBottomSheet</item>

</style>


<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
    <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item>
    <item name="behavior_peekHeight">420dp</item>
</style>

<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">20dp</item>
    <item name="cornerSizeTopLeft">20dp</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>

</style>

다른 답변에서 지적한 바와 같이 상태가BottomSheetBehavior.STATE_EXPANDED모서리가 평평해집니다.

는 설을통이문를수해있다습니결할제정해▁setting▁by다있▁you▁issue▁this를 설정하면 해결할 수 있습니다.peekHeightBottomSheetBehavior사용자 지정 스타일을 사용할 수 있습니다.

abstract class BaseBottomSheetFragment : BottomSheetDialogFragment(){

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
        if (state == BottomSheetBehavior.STATE_EXPANDED) {
            val displayMetrics = DisplayMetrics()
            requireActivity().windowManager!!.defaultDisplay!!.getMetrics(displayMetrics)
            (dialog as BottomSheetDialog).behavior.peekHeight = displayMetrics.heightPixels
        } else {
            (dialog as BottomSheetDialog).behavior.state = state
        }
    }

    override fun getTheme(): Int {
        return R.style.CustomBottomSheetDialog
    }
}

사용자 지정 하단시트 대화상자 스타일

<style name="CustomBottomSheetDialog" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/CustomBottomSheet</item>
    <item name="materialButtonStyle">@style/CustomMaterialButtonStyle</item>
</style>

<style name="CustomMaterialButtonStyle" parent="@style/Widget.MaterialComponents.Button">
    <item name="cornerRadius">@dimen/dialog_bottom_radius</item>
</style>

<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
    <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item>
</style>

<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
    <item name="android:background">@android:color/transparent</item>
    <item name="backgroundTint">@android:color/transparent</item>
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">@dimen/dialog_bottom_radius</item>
    <item name="cornerSizeTopLeft">@dimen/dialog_bottom_radius</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>
</style>

STATE_EXPENDED에서 둥근 모서리의 플랫화를 비활성화하는 짧은 솔루션:

@SuppressLint("RestrictedApi")
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState)
    
    //Disable animator that flats the rounded corners
    (dialog as BottomSheetDialog).behavior.disableShapeAnimations()

    return dialog
}

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

지금 전화하기setDialogBorder(dialog).setupDialog()BottomsheetDialogFragment는 다음과 같습니다.

이제 그리기 가능한 폴더에 모양 파일을 만듭니다.

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

이제 xml 파일에서 상위 뷰 그룹 대화 상자 뷰의 배경을 설정합니다.

android:background="@drawable/round_border_white"

됐습니다.

변경해야 합니다.bottom sheet theme최상단 배치를 달성하기 위해

그리기 가능한 사용자 지정 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>

그런 다음 아래쪽을 오버라이드합니다.시트 대화 상자그리기 가능한 배경을 사용하여 styles.xml에 대한 테마:

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

하단 시트의 배경 레이아웃이 변경됩니다.

맨 아래 시트 대화 상자

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
}

둥근 모서리가 있는 모양을 추가하여 루트 레이아웃의 배경으로 만듭니다.

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

당신의 엉덩이의 배경을 투명하게 하라.SheetDialogFragment

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

제약 조건 레이아웃, 프레임 레이아웃, 선형 레이아웃, 상대 레이아웃에 대한 작업입니다.

전체 솔루션:

style.xml에 아래 스타일 특성을 추가합니다.

<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/bottom_sheet_background</item>
</style>

그런 다음 AppBottom을 사용시트 대화 상자코드에서 맨 아래 시트 대화 상자를 만드는 테마입니다.

private fun openBottomSheetTermsCondition() {
    val mBottomSheetDialog = BottomSheetDialog(requireContext(),R.style.AppBottomSheetDialogTheme)
    val sheetView = layoutInflater.inflate(R.layout.bottom_sheet_travel_advice_terms, null)
    mBottomSheetDialog.setContentView(sheetView)
    sheetView.tv_head.setOnClickListener {
        mBottomSheetDialog.dismiss()
    }

    sheetView.webView.loadDataWithBaseURL(null,getString(R.string.privacy_policy_body_html),"text/html", "utf-8", null)
    mBottomSheetDialog.show()
}

저는 아래의 드로잉 테이블을 사용하여 하단 시트 배경을 반올림합니다.

    <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:topLeftRadius="@dimen/bottom_sheet_corner_radius"
        android:topRightRadius="@dimen/bottom_sheet_corner_radius" />
    <solid android:color="@color/white" />
</shape>

맨 아래 시트 xml bottom_sheet_travel_advise_terms.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:behavior_hideable="false"
    app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
    app:cardCornerRadius="@dimen/spacing_normal"
    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/spacing_small">

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/begin_horizontal_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="@dimen/activity_vertical_margin" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/begin_vertical_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="@dimen/activity_horizontal_margin" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/end_vertical_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="@dimen/activity_horizontal_margin" />

        <View
            android:id="@+id/sheet_header_shadow"
            android:layout_width="match_parent"
            android:layout_height="@dimen/spacing_tiny"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:background="@drawable/bottom_sheet_header_shadow"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/tv_head"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:drawablePadding="@dimen/spacing_normal"
            android:fontFamily="sans-serif-medium"
            android:gravity="start"
            android:padding="@dimen/spacing_small"
            android:text="@string/term_and_condition"
            android:textColor="@color/greyish_brown"
            android:textSize="20sp"
            app:drawableLeftCompat="@drawable/ic_close_black_24dp"
            app:layout_constraintEnd_toEndOf="@id/end_vertical_guideline"
            app:layout_constraintStart_toStartOf="@id/begin_vertical_guideline"
            app:layout_constraintTop_toBottomOf="@+id/begin_horizontal_guideline" />

        <View
            android:id="@+id/line_separation"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="@dimen/spacing_small"
            android:background="@color/blue_gray"
            app:layout_constraintTop_toBottomOf="@+id/tv_head" />

        <WebView
            android:id="@+id/webView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="@id/end_vertical_guideline"
            app:layout_constraintStart_toStartOf="@id/begin_vertical_guideline"
            app:layout_constraintTop_toBottomOf="@id/line_separation" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

setupDialog()제한된 API입니다.현재 작동하는 가장 간단한 솔루션material:1.3.0-beta01테마를 터치하지 않고:

res/drawable/bs_background:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners
    android:topLeftRadius="16dp"
    android:topRightRadius="16dp" />
  <solid android:color="@color/dayNightBackground" />
</shape>
public class MyBsDialogFrag extends BottomSheetDialogFragment {

@Override
  public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((View) view.getParent()).setBackgroundResource(R.drawable.bs_background);
  }

}

먼저 상단 모서리가 둥근 모양을 포함하는 그리기 가능한 xml 파일을 만들어야 합니다. 원하는 이름을 지정하십시오.나는 그것을 bottom rounded_top_shape.xml로 명명했습니다.

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

그런 다음 당신의 style.xml에 이것을 추가합니다.

<style name="AppBottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>

<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@drawable/rounded_top_shape</item>
</style>

그런 다음 아래와 같이 앱 테마에 이 행을 추가합니다.

 <style name="MyAppTheme" parent="Theme.MaterialComponents.Light.Bridge">
    <!-- this line -->
    <item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
</style>

간단한 해결책을 찾았습니다.com.google.dll.material:material:1.6.1과 함께 작동합니다.

class MyBottomSheet: BottomSheetDialogFragment() {
    
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            disableShapeAnimation()
        }
    
      @SuppressLint("RestrictedApi", "VisibleForTests")
      private fun disableShapeAnimation() {
            try {
                val dlg = dialog as BottomSheetDialog
                dlg.behavior.disableShapeAnimations()
            } catch (ex: Exception) {
                Log.e("BaseBottomSheet", "disableShapeAnimation Exception:", ex)
            }
        }
}

이 문제를 해결하는 또 다른 방법은 아래쪽을 확장하는 것입니다.SheetDialog를 사용하여 필요에 맞는 사용자 정의 클래스를 만듭니다.레이아웃 xml 파일에 대해서도 동일한 작업을 수행하고 배경 또는 필요한 다른 사용자 지정을 추가할 수 있습니다.Android(안드로이드)에서 사용하는 ID 이름에 의존하지 않는다는 이점도 있습니다.서포트.디자인.R.id .design_bottom_sheet)을 사용하여 배경을 변경합니다(ID 이름을 변경하는 경우는 드물지만 AFAIK).

둥근 모서리가 있는 사용자 지정 그리기 가능한 그림을 만들고 이 그림을 하단의 배경으로 설정합니다.SheetDialogFragment의 레이아웃 루트

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

그런 다음 아래 코드를 하단에 추가합니다.SheetDialogFragment 클래스

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

아래와 같이 마진을 설정하기 위해 매개 변수를 가지고 놀 수도 있습니다.

params.setMargins(50, 0, 50, 0);

이 필한경우가 필요하다면.setFitContents=true저는 훅으로 해결책을 시도했습니다.onStateChanged하지만 대화 상자가 도달하면 직선에서 둥근 모서리로 깜박입니다.EXPANDED주(州)입니다. 꽤 짜증납니다.

깜박임이 발생하지 않고 개인 API를 사용할 필요가 없으며 더 읽기 쉬운 대안(imho)이 있습니다.

를 보있다니습고드의 를 보고 .BottomSheetBehavior검색 결과:

  /** True if Behavior has a non-null value for the @shapeAppearance attribute */
  private boolean shapeThemingEnabled;

됩니다.MaterialShapeDrawable사용되지 않습니다.다음에서 확인할 수 있습니다.BottomSheetBehavior.onLayout():

// Only set MaterialShapeDrawable as background if shapeTheming is enabled, otherwise will
// default to android:background declared in styles or layout.
if (shapeThemingEnabled && materialShapeDrawable != null) {
  ViewCompat.setBackground(child, materialShapeDrawable);
}

을 으로기값으로 설정android:background배경이 렌더링되는 방식에 대한 완벽한 제어를 의미하기 때문에 정확히 우리가 필요로 하는 것입니다.

별도의 스타일과 설정을 만들어 재료 테마를 비활성화할 수 있습니다.shapeAppearance그리고.shapeAppearanceOverlay null 로지정:

<style name="Theme.YourApp.NoShapeBottomSheetDialog" parent="Theme.MaterialComponents.BottomSheetDialog">
  <item name="bottomSheetStyle">@style/Theme.YourApp.NoShapeButtonSheet</item>
</style>

<style name="Theme.YourApp.NoShapeButtonSheet" parent="Widget.MaterialComponents.BottomSheet.Modal">
  <item name="shapeAppearance">@null</item>
  <item name="shapeAppearanceOverlay">@null</item>
</style>

확다하BottomSheetDialogFragment 및오라드이버드를 재정의합니다.onCreateDialog:

public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
  return new BottomSheetDialog(requireContext(),
                R.style.Theme_Grupin_NoShapeBottomSheetDialog);
}

아래쪽 시트는 이제 아무런 배경도 없이 벌거벗었습니다.원하는 배경을 추가할 수 있습니다. 애니메이션은 더 이상 작동하지 않습니다.

재료 구성요소 테마를 사용하는 경우 맨 아래의 기본 동작을 재정의할 수 있습니다.SheetDialog는 배경색을 투명으로 설정한 다음 레이아웃의 배경을 반올림하도록 설정합니다.

    <style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="bottomSheetDialogTheme">@style/BottomSheetDialog</item>
    </style>

    <style name="BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
    </style>

    <style name="bottomSheetStyleWrapper" parent="Widget.MaterialComponents.BottomSheet.Modal">
        <item name="android:backgroundTint">@android:color/transparent</item>
    </style>

rounded_message.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/white"/>
    <corners android:topLeftRadius="26dp"
        android:topRightRadius="26dp"/>

</shape>

그런 다음 모양을 맨 아래 시트 루트 레이아웃의 배경에 적용합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/rounded_corner">

    <!-- 
       other layout components
     -->

</LinearLayout>

하단 시트 레이아웃에 Webview와 같은 구성요소가 있는 경우 Webview의 기본 배경이 흰색이기 때문에 예상대로 둥근 모서리를 만들지 못할 수 있습니다.이 경우 다음과 같이 배경을 간단히 제거할 수 있습니다.

webView.setBackgroundColor(0);

언급URL : https://stackoverflow.com/questions/43852562/round-corner-for-bottomsheetdialogfragment

반응형