Android-如何禁用底部工作表的STATE_HALF_EXPANDED状态


14

我有一个底层应该2个状态之间去,STATE_COLLAPSED并且STATE_EXPANDED 当它崩溃了HIGHT应该是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_EXPANDEDSTATE_EXPANDED代替STATE_COLLAPSEDSTATE_EXPANDED


请提供更多详细信息,例如底页的外观。
UD..19 /

@UD ..在这种情况下,我认为底页内容不重要。这是一个更一般的问题,是可以将底部片材状态的禁用一个
诺亚德劳奇

1
对于我的使用情况下,它似乎是设置halfExpandedRatio=0.25fpeekHeight = 200dp再处理STATE_COLLAPSED,并STATE_HALF_EXPANDED就好像它们是相同的状态,解决了问题。如果还有其他想法,请不要犹豫。
Noa Drach,


如果一个答案满足您提出的目标,请务必接受其中一个答案!
CommonsWare

Answers:


3

半扩展比率的值必须设置为介于0和1之间的互斥值,因此,请将此值设置为一个非常小的数字,该数字肯定小于您的窥视高度,例如“ 0.0001f”。使用此值,您甚至都不会看到STATE_HALF_EXPANDED状态。状态将在STATE_EXPANDED和之间波动STATE_COLLAPSED


替代解决方案

上面的解决方案有效并且可以有效地禁用STATE_HALF_EXPANDED状态,但是它是hackish(IMO)的,将来可能会破坏。例如,如果对半张开的比例(在窥视高度和全高之间)的合理值被强制执行怎么办?那会很麻烦。

OP规定的要求是,底板应在窥视高度和全高度之间过渡。窥视高度没有问题,但是OP指定isFitToContents = false要达到全高。(我假设他的底页可能短于可用空间。)

不幸的是,当isFitToContents == false引入额外的“半高”行为时,OP希望避免这种行为,因此是个问题。

除了“半高”行为外,还引入了另一个行为,即“扩展偏移”。扩展的偏移量指定底片将从全屏停止多远。100f例如,如果值为,则100px在完全展开时会在底部表格的顶部留下边框。扩展偏移量的默认值为零。

isFitToContents == false除了上述提到的行为外,我没有发现其他行为。

因此,在满足这些要求的情况下,我们是否可以设计一个在窥视高度和全高度之间移动的底板,同时指定底板尺寸,isFitToContents == true从而避免出现“半高”问题?不需要非零的扩展偏移量,因此我们不必为此担心。

这是一个简短的演示应用程序,展示了我们可以使用正确的底部工作表结构满足这些要求:

在此处输入图片说明

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>

关于您的初始响应-我发现即使将扩展比例设置为一半,也仍然可以看到非常薄的底部提示。无论如何,这不是我要寻找的行为。正如您在“替代解决方案”中提到的那样-“底层应该在窥视高度和全高度之间过渡”
Noa Drach

您的“替代解决方案”似乎正在起作用,这是我需要的解决方案,我的初始测试表明我需要使用isFitToContents = false,但是现在isFitToContents = true可以正常工作进行测试
Noa Drach

@NoaDrach如果底部工作表是可隐藏的,则由于底部工作表偏移的计算方式,底部至少会显示1px。我不认为工作表会被隐藏,但是显示1px时,可能会在sheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN达到一半展开状态时强制将工作表隐藏起来,但这变得有些复杂。替代解决方案更好。
Cheticamp

2

在此处输入图片说明

如果您想像图片一样尝试上面的代码,可以按照下面的代码进行操作,可能会对您有所帮助!!!

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>

很好的答案...保存了我的一天
unownsp

1

尝试在addBottomSheetCallback上设置一个BottomSheetBehavior,并在检测到STATE_HALF_EXPANDED状态时调用,setState(STATE_HIDDEN)这样,只要底页试图达到中间状态,它就会关闭。


好主意,就我而言,我会将状态设置为STATE_COLLAPSED而不是STATE_HIDDEN。但是我尝试实现它,从过渡STATE_HALF_EXPANDEDSTATE_COLLAPSED笨拙。状态之间的过渡是动态的,因此您会看到最下面的页面停下来STATE_HALF_EXPANDED,然后移至STATE_COLLAPSED
Noa Drach,

您可以将其与HalfExpandedRatio为0相结合吗?
Ridcully

@Ridcully-这里有2个问题-1. halfExpandedRatio必须大于0 2.将其设置为非常低的值会使我几乎完全最小化(半展开状态),然后才捕捉到折叠状态。我想到将这个建议与我的工作解决方案halfExpandedState=0.25fb / c 结合起来,那么状态之间的过渡就不会那么明显了。但是,我不确定与我已经拥有的相比,这将是一个很大的变化
Noa Drach

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)

希望这可以帮助



0

我尝试了不同的方法,但是没有一种技术能完美地完成工作。我尝试拦截事件BottomSheetBehavior.BottomSheetCallback {}dismiss()根据自定义逻辑进行调用,但是这导致了故障。

因此,最后,在我BottomSheetDialogFragment添加的内容中bottomSheetBehavior.isDraggable = false,这导致通过触摸拖动底部工作表。而且,我自己处理了对话框的关闭。在空白区域对话框上反正被驳回。

请注意,底部工作表仍随动画扩展。太好了!

重写fun 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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.