Android - Como desativar o estado STATE_HALF_EXPANDED de uma planilha inferior

14

Eu tenho uma folha inferior que deve ir entre 2 estados STATE_COLLAPSEDe , STATE_EXPANDED quando está fechada, a altura deve estar 200dpe, quando expandida, será exibida em tela cheia.

Então, eu estou definindo o BottomSheetBehaviorcom

isFitToContents = false
peekHeight = 200dp

e sou forçado a definir um valor halfExpandedRatiocaso contrário, quando na STATE_HALF_EXPANDEDfolha inferior ocupar metade da tela.

Estou trabalhando com com.google.android.material:material:1.1.0-rc01

Existe uma maneira de desativar o STATE_HALF_EXPANDEDestado?

Ou, na verdade skipCollapsed=true, devo definir , descobrir em termos de proporção o que 200dp significa e trabalhar com STATE_HALF_EXPANDEDe em STATE_EXPANDEDvez de STATE_COLLAPSEDeSTATE_EXPANDED

Noa Drach
fonte
forneça mais detalhes, como a aparência da folha de baixo.
UD ..
@ UD..Não acho que o conteúdo da folha de baixo seja relevante neste caso. Esta é uma questão mais geral, é possível desativar um dos estados folha de fundo
Noa Drach
11
Para o meu caso de uso, parece que definir halfExpandedRatio=0.25fe, em peekHeight = 200dpseguida, tratar STATE_COLLAPSEDe STATE_HALF_EXPANDEDcomo se eles fossem o mesmo estado resolve o problema. Manter a questão em aberto, caso haja outras idéias.
Noa Drach
você pode seguir este link, ele ajudará androidhive.info/2017/12/android-working-with-bottom-sheet
UD ..
Certifique-se de aceitar uma dessas respostas, se ela atender aos objetivos estabelecidos em sua pergunta!
CommonsWare

Respostas:

3

O valor da taxa de metade expandida deve ser definido como um valor entre 0 e 1 exclusivo ; portanto, defina esse valor para um número muito baixo, que certamente será menor que a sua altura de pico, diga "0,0001f". Com esse valor, você nem deve ver o STATE_HALF_EXPANDEDestado. Os estados variam entre STATE_EXPANDEDe STATE_COLLAPSED.


Solução alternativa

A solução acima funciona e desativa efetivamente o STATE_HALF_EXPANDEDestado, mas é imprecisa (IMO) e pode ser interrompida no futuro. Por exemplo, e se for aplicado um valor razoável para a taxa de meia expansão, que esteja entre a altura da espiada e a altura total? Isso seria problema.

Os requisitos declarados pelo OP são que a folha inferior deve fazer a transição entre a altura da espiada e a altura total. Não há nenhum problema com a altura da espiada, mas o OP especifica isFitToContents = falsepara atingir a altura total. (Presumo que a folha de baixo dele possa ser menor que o espaço disponível.)

Infelizmente, quando isFitToContents == falseé introduzido um comportamento adicional de "meia altura" que o OP deseja evitar e, portanto, a questão.

Além do comportamento de "meia altura", outro comportamento é introduzido, que é o "deslocamento expandido". O deslocamento expandido especifica a que distância da tela inteira a folha inferior será interrompida. Um valor de 100f, por exemplo, deixará uma 100pxborda na parte superior da folha inferior quando totalmente expandida. O padrão para o deslocamento expandido é zero.

Não conheço nenhum comportamento que seja isFitToContents == falseintroduzido além dos mencionados acima.

Portanto, considerando esses requisitos, podemos criar uma folha de fundo que se mova entre a altura da espiada e a altura total, especificando isFitToContents == trueassim evitando o problema da "meia altura"? Não há requisitos para um deslocamento expandido diferente de zero; portanto, não precisamos nos preocupar com isso.

Aqui está um pequeno aplicativo de demonstração demonstrando que podemos atender a esses requisitos com a estrutura da folha inferior direita:

insira a descrição da imagem aqui

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 tivermos uma folha inferior longa, a seguinte estrutura funcionará para rolá-la:

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
fonte
em relação à sua resposta inicial - vi que, mesmo que eu defina a proporção expandida pela metade, uma dica muito fina da folha de baixo ainda é visível. De qualquer forma, esse não é o comportamento que estou procurando. como você mencionou em "Solução alternativa" - "a folha inferior deve fazer a transição entre a altura da espiada e a altura total"
Noa Drach
sua "solução alternativa" parece estar funcionando e é a solução que eu precisava, meus testes iniciais mostraram que eu precisava usar isFitToContents = false, mas os testes agora com isFitToContents = trueok funcionam
Noa Drach
@NoaDrach Se a folha inferior estiver oculta, haverá pelo menos 1 px sendo exibido na parte inferior devido à forma como o deslocamento da folha inferior é calculado. Eu não estava pensando que a planilha estaria oculta, mas, com 1px sendo exibido, ela poderia ser forçada a ficar oculta sheetBehavior.state = BottomSheetBehavior.STATE_HIDDENquando o estado de meia expansão for alcançado, mas isso está ficando um pouco complicado. A solução alternativa é melhor.
Cheticamp
2

insira a descrição da imagem aqui

se você quiser tentar acima como na imagem, você pode seguir o código abaixo, pode ajudá-lo !!!

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 ..
fonte
resposta muito boa ... salvou o meu dia
unownsp 7/01
1

tente definir um addBottomSheetCallbackno seu BottomSheetBehaviore, quando detectar um STATE_HALF_EXPANDEDestado, ligue setState(STATE_HIDDEN)para que, sempre que a folha de baixo tentar atingir o estado intermediário, ela será fechada.

marmor
fonte
boa ideia, no meu caso, eu definiria o estado como STATE_COLLAPSEDe não STATE_HIDDEN. Mas tentei implementá-lo e a transição de STATE_HALF_EXPANDEDpara STATE_COLLAPSEDparece desajeitada. A transição entre estados é animada, então você vê a folha de baixo parar STATE_HALF_EXPANDEDe depois se move paraSTATE_COLLAPSED
Noa Drach
Você poderia combinar isso com um halfExpandedRatio de 0?
Ridcully
@Ridcully - 2 questões aqui - 1. halfExpandedRatio deve estar acima de 0 2. defini-lo com um valor muito baixo fará com que eu seja minimizado quase completamente (estado meio expandido), antes de ser ajustado ao estado recolhido. Pensei em combinar essa sugestão com minha solução de trabalho de halfExpandedState=0.25f, b / c, então a transição entre estados não será tão óbvia. Mas não tenho certeza se haverá uma grande mudança em relação ao que eu já tenho
Noa Drach
1

Eu tinha um caso de uso semelhante, em que o layout precisava ter um terço da altura. Eu tentei o seguinte e funcionou muito bem.

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

Eu tive que alterá-las dinamicamente para definir o seguinte na folha inferior, mas você também pode fazer isso em xml:

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

Para descartar, adicionei animação ao meu fragmento usando a seguinte função:

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

Espero que isto ajude

Saurabh
fonte
0

Tentei de maneiras diferentes, mas nenhuma técnica funcionou perfeitamente. Tentei interceptar eventos BottomSheetBehavior.BottomSheetCallback {}e liguei com dismiss()base na lógica personalizada, mas isso causou um empurrão.

Então, finalmente, no meu BottomSheetDialogFragmenteu adicionei bottomSheetBehavior.isDraggable = falsee isso causou o arrastamento da folha de baixo pelo toque. de qualquer maneira, na caixa de diálogo de área vazia, é dispensado.

Observe que, a folha inferior ainda se expande com animação. Isso é realmente ótimo!

substituir diversão onCreateDialog (savedInstanceState: Bundle?): Caixa de diálogo {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
}
Rahul Rastogi
fonte