Android - Cara menonaktifkan status STATE_HALF_EXPANDED dari lembar bawah

14

Saya memiliki lembaran bawah yang harus berada di antara 2 negara, STATE_COLLAPSEDdan STATE_EXPANDED ketika itu runtuh, seharusnya tinggi 200dpdan ketika diperluas itu akan menjadi layar penuh.

Jadi saya mengatur BottomSheetBehaviordengan

isFitToContents = false
peekHeight = 200dp

dan saya dipaksa untuk menetapkan nilai halfExpandedRatiosebaliknya jika di STATE_HALF_EXPANDEDbagian bawah lembar akan mengambil setengah dari layar.

Saya bekerja dengan com.google.android.material:material:1.1.0-rc01

Apakah ada cara untuk menonaktifkan STATE_HALF_EXPANDEDnegara?

Atau saya harus benar-benar menetapkan skipCollapsed=true, mencari tahu dalam hal rasio apa arti 200dp dan bekerja dengan STATE_HALF_EXPANDEDdan STATE_EXPANDEDbukannya STATE_COLLAPSEDdanSTATE_EXPANDED

Noa Drach
sumber
tolong berikan rincian lebih lanjut seperti, bagaimana lembaran bawah terlihat.
UD ..
@ UD..Saya tidak berpikir bahwa konten lembaran bawah relevan dalam kasus ini. Ini adalah pertanyaan yang lebih umum, apakah mungkin untuk menonaktifkan salah satu status lembar bawah
Noa Drach
1
Untuk kasus penggunaan saya, itu tampaknya bahwa pengaturan halfExpandedRatio=0.25fdan peekHeight = 200dpkemudian mengobati STATE_COLLAPSEDdan STATE_HALF_EXPANDEDseolah-olah mereka adalah memecahkan keadaan yang sama masalah ini. Menjaga pertanyaan tetap terbuka jika ada ide lain.
Noa Drach
Anda dapat mengikuti tautan ini, ini akan membantu androidhive.info/2017/12/android-working-with-bottom-sheet
UD ..
Pastikan untuk menerima salah satu dari jawaban ini, jika seseorang memenuhi tujuan yang ditetapkan dalam pertanyaan Anda!
CommonsWare

Jawaban:

3

Nilai rasio setengah diperluas harus ditetapkan ke beberapa nilai antara 0 dan 1 eksklusif , jadi set nilai ini ke beberapa angka yang sangat rendah yang pasti kurang dari ketinggian mengintip Anda, katakan "0,0001f". Dengan nilai ini Anda bahkan tidak harus melihat STATE_HALF_EXPANDEDnegara. Negara akan berfluktuasi antara STATE_EXPANDEDdan STATE_COLLAPSED.


Solusi alternatif

Solusi di atas berfungsi dan secara efektif menonaktifkan STATE_HALF_EXPANDED negara, tetapi itu adalah peretasan (IMO) dan mungkin pecah di masa depan. Misalnya, bagaimana jika nilai wajar untuk rasio setengah diperluas yang berada di suatu tempat antara ketinggian mengintip dan ketinggian penuh diberlakukan? Itu akan menjadi masalah.

Persyaratan sebagaimana dinyatakan oleh OP adalah bahwa lembaran bawah harus bertransisi antara ketinggian mengintip dan ketinggian penuh. Tidak ada masalah dengan ketinggian mengintip, tetapi OP menentukanisFitToContents = false untuk mencapai ketinggian penuh. (Saya berasumsi bahwa lembaran bawahnya mungkin lebih pendek daripada ruang yang tersedia.)

Sayangnya kapan isFitToContents == false perilaku "setengah tinggi" tambahan diperkenalkan bahwa OP ingin menghindari dan karena itu pertanyaannya.

Selain perilaku "setengah tinggi" perilaku lain diperkenalkan yang merupakan "diperluas offset." Offset yang diperluas menentukan seberapa jauh dari layar penuh lembar bawah akan berhenti. Nilai 100f, misalnya, akan meninggalkan 100pxbatas di bagian atas lembar bawah saat diperluas penuh. Default untuk offset yang diperluas adalah nol.

Saya tidak mengetahui adanya perilaku itu isFitToContents == false memperkenalkan selain dari yang disebutkan di atas.

Jadi, mengingat persyaratan ini, dapatkah kita membuat lembaran bawah yang bergerak antara ketinggian mengintip dan ketinggian penuh saat menentukan isFitToContents == true sehingga menghindari masalah "setengah tinggi"? Tidak ada persyaratan untuk offset yang diperluas tanpa nol, jadi kami tidak perlu khawatir tentang itu.

Berikut ini adalah aplikasi demo singkat yang menunjukkan bahwa kami dapat memenuhi persyaratan ini dengan struktur lembar kanan bawah:

masukkan deskripsi gambar di sini

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>

Jika kami memiliki lembar bawah yang panjang maka struktur berikut berfungsi untuk menggulirnya:

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>
Cheticamp
sumber
mengenai tanggapan awal Anda - saya melihat bahwa bahkan jika saya menetapkan rasio setengah diperluas, petunjuk yang sangat tipis dari lembar bawah masih terlihat. Lagi pula, ini bukan perilaku yang saya cari. seperti yang Anda sebutkan dalam "Solusi alternatif" - "lembaran bawah harus bertransisi antara ketinggian mengintip dan ketinggian penuh"
Noa Drach
"Solusi alternatif" Anda tampaknya berfungsi dan itu solusi yang saya butuhkan, pengujian awal saya menunjukkan bahwa saya perlu menggunakan isFitToContents = false, tetapi pengujian sekarang dg isFitToContents = truebekerja dengan baik
Noa Drach
@NoaDrach Jika lembar bawah dapat disembunyikan maka akan ada setidaknya 1px ditampilkan di bagian bawah karena bagaimana offset lembar bawah dihitung. Saya tidak berpikir bahwa lembaran itu akan disembunyikan tetapi, dengan 1px yang ditampilkan, lembaran itu hanya bisa dipaksa untuk disembunyikan sheetBehavior.state = BottomSheetBehavior.STATE_HIDDENketika setengah diperluas negara tercapai, tetapi itu menjadi sedikit rumit. Solusi alternatif lebih baik.
Cheticamp
2

masukkan deskripsi gambar di sini

Jika Anda ingin mencoba di atas seperti pada gambar, Anda dapat mengikuti kode di bawah ini, semoga membantu Anda !!!

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>
UD ..
sumber
jawaban yang sangat bagus ... menyelamatkan hari saya
unownsp
1

coba atur addBottomSheetCallbackpada Anda BottomSheetBehavior, dan ketika Anda mendeteksi STATE_HALF_EXPANDEDkeadaan, panggil setState(STATE_HIDDEN)jadi kapan pun lembar bawah mencoba mencapai keadaan setengah, itu hanya akan menutup.

marmor
sumber
ide yang bagus, dalam kasus saya, saya akan mengatur negara STATE_COLLAPSEDdan tidak STATE_HIDDEN. Tapi saya mencoba untuk menerapkannya dan transisi dari STATE_HALF_EXPANDEDke STATE_COLLAPSEDterasa kikuk. Transisi antar negara dianimasikan, sehingga Anda melihat lembaran bawah berhenti STATE_HALF_EXPANDEDdan kemudian pindah keSTATE_COLLAPSED
Noa Drach
Bisakah Anda menggabungkan ini dengan halfExpandedRatio dari 0?
Ridcully
@Reccully - 2 masalah di sini - 1. halfExpandedRatio harus di atas 0 2. pengaturan ke nilai yang sangat rendah akan membuat saya diminimalkan hampir sepenuhnya (setengah diperluas), sebelum diambil ke keadaan runtuh. Saya berpikir untuk menggabungkan saran ini dengan solusi kerja saya halfExpandedState=0.25f, b / c maka transisi antar negara tidak akan semudah ini. Tapi, saya tidak yakin itu akan menjadi perubahan besar dibandingkan dengan apa yang sudah saya miliki
Noa Drach
1

Saya memiliki kasus penggunaan serupa di mana tata letak harus sepertiga dari ketinggian. Saya mencoba yang berikut dan itu berhasil.

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

Saya harus mengubah ini secara dinamis jadi saya mengatur yang berikut di lembar bawah tetapi Anda dapat melakukannya dalam xml juga:

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

Untuk mengabaikan, saya menambahkan animasi ke fragmen saya menggunakan fungsi berikut:

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

Semoga ini membantu

Saurabh
sumber
0

Saya mencoba berbagai cara, tetapi tidak ada teknik yang bekerja sempurna. Saya mencoba mencegat peristiwa BottomSheetBehavior.BottomSheetCallback {}dan menelepondismiss() berdasarkan logika kustom tetapi menyebabkan brengsek.

Jadi, akhirnya, In my BottomSheetDialogFragmentmenambahkanbottomSheetBehavior.isDraggable = false dan ini menyebabkan menyeret lembar bawah dengan sentuhan Dan, saya menangani pemberhentian dialog saya sendiri. pada dialog area kosong, bagaimanapun juga dapat diberhentikan.

Perhatikan bahwa, Lembar bawah masih mengembang dengan animasi. Benar-benar hebat!

menimpa kesenangan onCreateDialog (disimpanInstanceState: Bundel?): Dialog {val dialog = super.onCreateDialog (disimpanInstanceState)

    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
}
Rahul Rastogi
sumber