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の間の値exclusiveに設定する必要があるため、この値を、ピークの高さよりも確実に低い非常に低い数値に設定します、「0.0001f」と言います。この値では、_STATE_HALF_EXPANDED
_の状態も表示されません。状態は_STATE_EXPANDED
_と_STATE_COLLAPSED
_の間で変動します。
代替ソリューション
上記のソリューションは機能し、_STATE_HALF_EXPANDED
_状態を効果的に無効にしますが、ハック(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>
_
画像のように上記を試してみたい場合は、以下のコードに従ってください。
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>
レイアウトを高さの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)
お役に立てれば
addBottomSheetCallback
にBottomSheetBehavior
を設定してみてください。_STATE_HALF_EXPANDED
_状態を検出したら、setState(STATE_HIDDEN)
を呼び出して、下のシートが中間状態に到達しようとするたびに、閉じます。
BottomSheetBehavior
.setHalfExpandedRatio(0f)
を設定してみてください。 。setState() を使用して明示的に状態を設定しない限り、STATE_HALF_EXPANDED
に影響する他の多くのものはありません。 CoordinatorLayout.Behavior<View>
を拡張し、STATE_HALF_EXPANDED
を持たないカスタムBehavior
を作成することも可能です。例えば。 CoordinatorLayout Behaviorsですべてをインターセプト 。
いろいろな方法を試しましたが、完璧に機能するテクニックはありませんでした。カスタムロジックに基づいて_BottomSheetBehavior.BottomSheetCallback {}
_でイベントをインターセプトしてdismiss()
を呼び出しましたが、ジャークが発生しました。
それで、ついに、私のBottomSheetDialogFragment
に_bottomSheetBehavior.isDraggable = false
_を追加しました。これにより、タッチによって下のシートのドラッグが発生しました。そして、私は自分でダイアログの却下を処理しました。とにかく、空の領域のダイアログでは閉じられます。
一番下のシートはまだアニメーションで拡大していることに注意してください。それは本当に素晴らしいです!
fun onCreateDialog(savedInstanceState:Bundle?):Dialogをオーバーライドします{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
}
_