[android] Android-바텀 시트의 STATE_HALF_EXPANDED 상태를 비활성화하는 방법

나는 2 주 사이에 가야 바닥 시트를, STATE_COLLAPSED그리고 STATE_EXPANDED
이 접힌 때 높이가되어야합니다 200dp및 확장 할 때 전체 화면 일 것이다.

제가 설정을 해요 그래서 BottomSheetBehavior함께

isFitToContents = false
peekHeight = 200dp

halfExpandedRatio그렇지 않으면 STATE_HALF_EXPANDED맨 아래 시트가 화면의 절반을 차지할 때 값을 설정해야합니다 .

나는 일하고 있어요 com.google.android.material:material:1.1.0-rc01

STATE_HALF_EXPANDED상태 를 비활성화하는 방법이 있습니까?

아니면 실제로 설정해야 skipCollapsed=true와 비율 무엇 200dp 수단과 업무의 관점에서 파악, STATE_HALF_EXPANDED그리고 STATE_EXPANDED대신 STATE_COLLAPSED하고STATE_EXPANDED



답변

반 확장 비율의 값은 0과 1 독점 사이의 값으로 설정해야합니다 . 따라서이 값을 뾰족한 높이보다 작은 매우 낮은 숫자로 설정하십시오 (예 : “0.0001f”). 이 값을 사용하면 STATE_HALF_EXPANDED상태를 볼 수도 없습니다 . 주 STATE_EXPANDED와 사이에 변동이 STATE_COLLAPSED있습니다.


대체 솔루션

위의 솔루션은 작동하고 효과적으로 STATE_HALF_EXPANDED상태를 비활성화 하지만 해킹 (IMO)이며 향후 중단 될 수 있습니다. 예를 들어, 반 높이 비율과 전체 높이 사이에있는 절반 확장 비율에 대한 합리적인 값이 적용된다면 어떨까요? 문제가 될 것입니다.

OP에 명시된 바와 같이 요구 사항은 바닥 시트가 픽 높이와 전체 높이 사이에서 전환되어야한다는 것입니다. 엿보기 높이에는 문제가 없지만 OP isFitToContents = false는 전체 높이에 도달하도록 지정 합니다. (나는 그의 바닥 시트가 사용 가능한 공간보다 짧을 수 있다고 가정합니다.)

불행하게도 isFitToContents == falseOP가 회피하고 싶어하는 추가 “반 높이”동작이 도입되면 질문이 생깁니다.

“반 높이”동작 외에도 “확장 오프셋”인 다른 동작이 도입되었습니다. 확장 오프셋은 바텀 시트가 전체 화면에서 얼마나 멀리 내려갈지를 지정합니다. 100f예를 들어 값이 100px완전히 확장되면 바텀 시트 상단에 테두리 가 남습니다 . 확장 된 오프셋의 기본값은 0입니다.

isFitToContents == false위에서 언급 한 것 이외의 동작을 인식하지 못했습니다 .

따라서 이러한 요구 사항을 감안할 isFitToContents == true때 “반 높이”문제를 피 하면서 특정 높이와 전체 높이 사이를 이동하는 바닥 시트를 만들 수 있습니까? 0이 아닌 확장 오프셋에 대한 요구 사항이 없으므로 걱정할 필요가 없습니다.

오른쪽 하단 시트 구조로 이러한 요구 사항을 충족 할 수 있음을 보여주는 간단한 데모 앱이 있습니다.

여기에 이미지 설명을 입력하십시오

MainActivity5.kt

class MainActivity5 : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main5)

        val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet)
        val sheetBehavior: BottomSheetBehavior<LinearLayout> = BottomSheetBehavior.from(bottomSheet)
        sheetBehavior.isFitToContents = true // the default  
  sheetBehavior.peekHeight = 200

  // Log the states the bottom sheet passes through.  
  sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            override fun onStateChanged(bottomSheet: View, newState: Int) {
                Log.d("MainActivity", "<<<< $newState = ${translateSheetState(newState)}")
            }

            override fun onSlide(bottomSheet: View, slideOffset: Float) {}
        })
    }
}

BaseActivity.kt

open class BaseActivity : AppCompatActivity() {

    protected fun translateSheetState(state: Int): String {
        return when (state) {
            BottomSheetBehavior.STATE_COLLAPSED -> "STATE_COLLAPSED"
  BottomSheetBehavior.STATE_DRAGGING -> "STATE_DRAGGING"
  BottomSheetBehavior.STATE_EXPANDED -> "STATE_EXPANDED"
  BottomSheetBehavior.STATE_HALF_EXPANDED -> "STATE_HALF_EXPANDED"
  BottomSheetBehavior.STATE_HIDDEN -> "STATE_HIDDEN"
  BottomSheetBehavior.STATE_SETTLING -> "STATE_SETTLING"
  else -> "Unknown state: $state"
  }
    }
}

activity_main5.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/short_text"
            android:textSize="16sp" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

하단 시트가 길면 다음과 같은 구조로 스크롤됩니다.

activity_main6.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light"
        android:orientation="vertical"
        android:scrollbars="none"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:text="@string/long_text"
                android:textSize="16sp" />
        </androidx.core.widget.NestedScrollView>
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>


답변

여기에 이미지 설명을 입력하십시오

이미지와 같이 위를 시도하려면 아래 코드를 따르면 도움이 될 것입니다 !!!

public class CollectionsBottomSheet extends BottomSheetDialogFragment {
    private BottomSheetBehavior mBehavior;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
        View view = View.inflate(getContext(), R.layout.collections_layout, null);
        LinearLayout linearLayout = view.findViewById(R.id.root);
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();
        params.height = getScreenHeight();
        linearLayout.setLayoutParams(params);
        dialog.setContentView(view);
        mBehavior = BottomSheetBehavior.from((View) view.getParent());
        return dialog;

    }

    @Override
    public void onStart() {
        super.onStart();
        mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }

    public static int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }
}



xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true">


    <LinearLayout
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/filter_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableStart="@drawable/ic_cancel"
                android:drawableLeft="@drawable/ic_cancel"
                android:drawablePadding="30dp"
                android:gravity="center_vertical"
                android:padding="12dp"
                android:text="Filters"
                android:textColor="@color/black"
                android:textSize="18sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="10dp"
                android:layout_marginRight="10dp"
                android:padding="5dp"
                android:text="Reset ALL"
                android:textColor="#6f6f6f"
                android:textSize="12sp" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#d8dbdb" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_star"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="GUEST RATINGS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_money"
            android:drawableLeft="@drawable/ic_money"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PRICE RANGE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_loan"
            android:drawableLeft="@drawable/ic_star"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="PAY AT HOTEL"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_folder"
            android:drawableLeft="@drawable/ic_folder"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="COLLECTIONS"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_perm_identity_black_24dp"
            android:drawableLeft="@drawable/ic_perm_identity_black_24dp"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="FACILITIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_apartment"
            android:drawableLeft="@drawable/ic_apartment"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="CATEGORIES"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/sort_background"
            android:drawableStart="@drawable/ic_hotel_building"
            android:drawableLeft="@drawable/ic_hotel_building"
            android:drawablePadding="15dp"
            android:padding="15dp"
            android:text="ACCOMMODATION TYPE"
            android:textColor="#6f6f6f"
            android:textSize="16sp" />

    </LinearLayout>


</LinearLayout>


답변

설정 a하려고 addBottomSheetCallback당신에 BottomSheetBehavior, 그리고 당신이 감지 될 때 STATE_HALF_EXPANDED상태를 호출 setState(STATE_HIDDEN)바닥 시트 시도가 중간 상태에 도달 할 때마다 그냥 가까운거야, 그래서.


답변

레이아웃이 높이의 3 분의 1이어야하는 비슷한 유스 케이스가있었습니다. 나는 다음을 시도했고 훌륭하게 작동했다.

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottom_sheet_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grey"
    android:clickable="true">

    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/rounded_bottom_sheet_background"
        android:orientation="vertical"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

하단 시트에 다음을 설정하여 동적으로 변경해야했지만 XML 에서도이 작업을 수행 할 수 있습니다.

bottomSheet.setPeekHeight(200);// 200px
bottomSheet.setHideable(false);

해제하기 위해 다음 함수를 사용하여 조각에 애니메이션을 추가했습니다.

fragmentTransaction.setCustomAnimations(
                    R.anim.fade_in,
                    R.anim.fade_out,
                    R.anim.fade_in,
                    R.anim.fade_out)

도움이 되었기를 바랍니다


답변

설정을 시도하십시오 BottomSheetBehavior.setHalfExpandedRatio(0f). .setState ()로STATE_HALF_EXPANDED 명시 적으로 상태를 설정하지 않는 한 영향을 미칠 다른 것은 많지 않습니다 . 또한 확장 되고없는 사용자 정의를 작성할 수도 있습니다 . 예. CoordinatorLayout 동작으로 모든 것을 가로 채기 .BehaviorCoordinatorLayout.Behavior<View>STATE_HALF_EXPANDED


답변

다른 방법으로 시도했지만 완벽하게 작동하는 기술은 없습니다. 이벤트를 가로 채려고 시도 하고 사용자 지정 논리를 기반으로 BottomSheetBehavior.BottomSheetCallback {}호출 dismiss()했지만 문제가 발생했습니다.

그래서 마침내, BottomSheetDialogFragment나는 추가 bottomSheetBehavior.isDraggable = false했고 이것은 터치로 바닥 시트를 끌었습니다. 그리고 나는 대화의 해제를 스스로 처리했습니다. 빈 영역 대화 상자에서 어쨌든 해제됩니다.

하단 시트는 여전히 애니메이션과 함께 확장됩니다. 정말 좋습니다!

재미 재정의 onCreateDialog (savedInstanceState : Bundle?) : 대화 상자 {val dialog = super.onCreateDialog (savedInstanceState)

    dialog.setOnShowListener {
        val bottomSheetDialog = it as BottomSheetDialog
        val bottomSheet =
            bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
                ?: return@setOnShowListener

        //Making background to transparent to avoid white background to given space margin.
        bottomSheet.setBackgroundColor(ContextCompat.getColor(context!!, R.color.transparent))

        val inflatedView = fragmentProfileDialogBinding.root
        val parent = inflatedView.parent as View

        val bottomSheetBehavior = BottomSheetBehavior.from(parent)
        bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
        bottomSheetBehavior.isDraggable = false
    }

    return dialog
}


답변