Android: come disabilitare lo stato STATE_HALF_EXPANDED di un foglio inferiore


14

Ho un foglio inferiore che dovrebbe andare tra 2 stati, STATE_COLLAPSEDe STATE_EXPANDED quando è crollato l'altezza dovrebbe essere 200dpe quando espanso sarà a schermo intero.

Quindi sto impostando il BottomSheetBehaviorcon

isFitToContents = false
peekHeight = 200dp

e sono costretto a impostare un valore, halfExpandedRatioaltrimenti quando sul STATE_HALF_EXPANDEDfoglio inferiore occuperà metà dello schermo.

Sto lavorando con com.google.android.material:material:1.1.0-rc01

C'è un modo per disabilitare lo STATE_HALF_EXPANDEDstato?

O dovrei effettivamente impostare skipCollapsed=true, capire in termini di rapporto cosa significa 200dp e lavorare con STATE_HALF_EXPANDEDe STATE_EXPANDEDinvece di STATE_COLLAPSEDeSTATE_EXPANDED


si prega di fornire maggiori dettagli come l'aspetto del foglio inferiore.
UD ..

@ UD..non credo che il contenuto del foglio inferiore sia pertinente in questo caso. Questa è una domanda più generale, è possibile disabilitare uno degli stati del foglio inferiore
Noa Drach,

1
Per il mio caso d'uso, sembra che l'impostazione halfExpandedRatio=0.25fe peekHeight = 200dpquindi il trattamento STATE_COLLAPSEDe STATE_HALF_EXPANDEDcome se fossero lo stesso stato risolva il problema. Mantenere aperta la domanda nel caso ci siano altre idee.
Noa Drach,

puoi seguire questo link, ti ​​aiuterà androidhive.info/2017/12/android-working-with-bottom-sheet
UD ..

Assicurati di accettare una di queste risposte, se una soddisfa gli obiettivi indicati nella tua domanda!
CommonsWare

Risposte:


3

Il valore del rapporto semi-espanso deve essere impostato su un valore compreso tra 0 e 1 esclusivo , quindi impostare questo valore su un numero molto basso che sarà sicuramente inferiore all'altezza di sbircia, ad esempio "0.0001f". Con questo valore non dovresti nemmeno vedere lo STATE_HALF_EXPANDEDstato. Gli stati oscilleranno tra STATE_EXPANDEDe STATE_COLLAPSED.


Soluzione alternativa

La soluzione sopra funziona e disabilita efficacemente lo STATE_HALF_EXPANDEDstato, ma è un hacker (IMO) e potrebbe rompersi in futuro. Ad esempio, cosa succede se viene applicato un valore ragionevole per il rapporto semi-espanso che si trova tra l'altezza di sbirciata e l'altezza completa? Sarebbe un problema.

I requisiti stabiliti dall'OP sono che il foglio inferiore deve passare tra l'altezza di sbirciata e l'altezza completa. Non ci sono problemi con l'altezza di sbirciatina, ma l'OP specifica isFitToContents = falsedi arrivare alla massima altezza. (Suppongo che il suo foglio inferiore possa essere più corto dello spazio disponibile.)

Sfortunatamente, quando isFitToContents == falseviene introdotto un ulteriore comportamento a "mezza altezza" che l'OP vuole evitare e quindi la domanda.

Oltre al comportamento a "mezza altezza", viene introdotto un altro comportamento che è l '"offset esteso". L'offset espanso specifica fino a che punto si arresta il foglio inferiore rispetto allo schermo intero. Un valore 100f, ad esempio, lascerà un 100pxbordo nella parte superiore del foglio inferiore una volta espanso completamente. L'impostazione predefinita per l'offset espanso è zero.

Non sono a conoscenza di comportamenti che isFitToContents == falseintroducano diversi da quelli sopra menzionati.

Quindi, dati questi requisiti, possiamo modellare un foglio inferiore che si sposta tra l'altezza di sbirciata e l'altezza completa specificando isFitToContents == truecosì evitando il problema della "mezza altezza"? Non è richiesto un offset espanso diverso da zero, quindi non dobbiamo preoccuparci di questo.

Ecco una breve app demo che dimostra che possiamo soddisfare questi requisiti con la giusta struttura in basso:

inserisci qui la descrizione dell'immagine

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>

Se abbiamo un foglio inferiore lungo, la seguente struttura funziona per farlo scorrere:

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>

per quanto riguarda la tua risposta iniziale - ho visto che anche se ho impostato un rapporto semi-espanso, è ancora visibile un suggerimento molto sottile del foglio inferiore. E comunque, questo non è il comportamento che sto cercando. come menzionato in "Soluzione alternativa" - "il foglio inferiore deve passare tra l'altezza di sbirciata e l'altezza completa"
Noa Drach,

la tua "soluzione alternativa" sembra funzionare ed è la soluzione di cui avevo bisogno, i miei test iniziali hanno dimostrato che devo usare isFitToContents = false, ma i test ora isFitToContents = truefunzionano correttamente
Noa Drach

@NoaDrach Se il foglio inferiore è nascosto, allora ci sarebbe almeno 1px mostrato in basso a causa del modo in cui viene calcolato l'offset del foglio inferiore. Non pensavo che il foglio sarebbe stato nascosto ma, con 1px mostrato, il foglio potrebbe essere costretto ad essere nascosto sheetBehavior.state = BottomSheetBehavior.STATE_HIDDENquando viene raggiunto lo stato di semi-espansione, ma questo sta diventando un po 'complicato. La soluzione alternativa è migliore.
Cheticamp,

2

inserisci qui la descrizione dell'immagine

se vuoi provare sopra come nell'immagine, puoi seguire il codice qui sotto, possa aiutarti !!!

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>

risposta molto buona ... mi ha salvato la giornata
unspsp

1

prova a impostare a addBottomSheetCallbacksul tuo BottomSheetBehavior, e quando rilevi uno STATE_HALF_EXPANDEDstato, chiama setState(STATE_HIDDEN)così ogni volta che il foglio in basso cerca di raggiungere lo stato a metà strada, si chiuderà.


bella idea, nel mio caso avrei impostato lo stato su STATE_COLLAPSEDe non STATE_HIDDEN. Ma ho cercato di implementarlo e il passaggio da STATE_HALF_EXPANDEDa STATE_COLLAPSEDsembra goffo. La transizione tra gli stati è animata, quindi vedi il foglio inferiore fermarsi STATE_HALF_EXPANDEDe poi si sposta suSTATE_COLLAPSED
Noa Drach,

Potresti combinare questo con un rapporto metà espanso di 0?
Ridcully,

@Ridcully - 2 problemi qui - 1. halfExpandedRatio deve essere superiore a 0 2. L'impostazione su un valore molto basso lo farà minimizzare quasi completamente (stato semi-espanso), prima di essere portato allo stato compresso. Ho pensato di combinare questo suggerimento con la mia soluzione di lavoro di halfExpandedState=0.25f, b / c, quindi la transizione tra stati non sarà così ovvia. Ma non sono sicuro che sarà un grande cambiamento rispetto a quello che ho già
Noa Drach il

1

Ho avuto un caso d'uso simile in cui il layout doveva essere un terzo dell'altezza. Ho provato quanto segue e ha funzionato alla grande.

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

Ho dovuto cambiarli in modo dinamico, quindi ho impostato quanto segue sul foglio inferiore ma puoi farlo anche in xml:

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

Per eliminare, ho aggiunto l'animazione al mio frammento usando la seguente funzione:

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

Spero che sia di aiuto



0

Ho provato diversi modi, ma nessuna tecnica ha funzionato perfettamente. Ho provato a intercettare gli eventi BottomSheetBehavior.BottomSheetCallback {}e ho chiamatodismiss() base alla logica personalizzata, ma ha causato un cretino.

Quindi, alla fine, nel mio BottomSheetDialogFragmentho aggiunto bottomSheetBehavior.isDraggable = falsee questo ha causato il trascinamento del foglio inferiore al tocco E, ho gestito il licenziamento del dialogo da solo. nella finestra di dialogo area vuota vengono comunque ignorati.

Si noti che, il foglio inferiore si espande ancora con l'animazione. E 'davvero fantastico!

override 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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.