Recolher ou expandir programaticamente CollapsingToolbarLayout

158

Pergunta simples, mas não consigo encontrar uma resposta. Como posso recolher ou expandir CollapsingToolbarLayoutprogramaticamente?

barra de ferramentas recolhida

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

barra de ferramentas expandida

Tomas
fonte
1
Eu estava pensando a mesma coisa. Também pode ser interessante expandir a barra de ferramentas para a tela cheia quando o usuário clicar no layout incorporado (por exemplo, imagem).
Moritz

Respostas:

321

Usando a Biblioteca de suporte v23, você pode ligar appBarLayout.setExpanded(true/false).

Leitura adicional: AppBarLayout.setExpanded (boolean)

jaxvy
fonte
2
Ok, obrigado pela dica, mas libs apoio v23 são muito buggy, por isso não posso testá-lo agora, porque eu preciso ficar em 22.2.1 ....
Tomas
Agora você tem 23.0.1 com algumas correções
Mario Velasco
6
É possível definir uma animação personalizada com suporte libs 23.1.1? O setExpanded (booleano, verdadeiro) tem uma animação muito lenta ...
Nifhel
Eu tive um problema em que tenho um layout com uma barra de ferramentas dobrável e uma visão de reciclagem embaixo dela. Ao excluir itens da revisão de reciclagem, a barra de ferramentas não se comportava adequadamente, portanto, eu expandia o layout da barra de aplicativos e funcionava corretamente. Acabei usando o appBarLayout.setExpanded (true, true) para a animação.
Raio Hunter
49

Eu uso esse código para recolher a barra de ferramentas. Ainda não conseguiu encontrar uma maneira de expandi-lo.

public void collapseToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, 10000, true);
    }
}

Edit 1: A mesma função com velocidade negativaY, mas a barra de ferramentas não é expandida 100% e false para o último parâmetro deve funcionar

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, -10000, false);
    }
}

Edit 2: Este código faz o truque para mim

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.setTopAndBottomOffset(0);
        behavior.onNestedPreScroll(rootLayout, appbarLayout, null, 0, 1, new int[2]);
    }
}
  • setTopAndBottomOffset expande a barra de ferramentas
  • onNestedPreScroll mostra o conteúdo dentro da barra de ferramentas expandida

Tentarei implementar o comportamento sozinho.

Tuấn Trần Anh
fonte
2
A edição 1 também funcionará se você definir o último parâmetro de onNestedFlingcomo false.
Ricky Lee
2
params.getBehavior () está retornando nulo. No xml, a tag layout_behaviour é definida no irmão NestedScrollView, não no AppBarLayout. Pode me ajudar?
User31689
Obrigado. Editar 1 funcionará corretamente, se o último parâmetro for falso. :)
Sirelon
@GobletSky Eu enfrentei o mesmo problema. Eu tinha o NestedScrollView no meu fragmento e tentei ligar onNestedFling antes de definir o fragmento. Depois de definir o fragmento, eu poderia chamar o método com sucesso.
usp
@usp Na verdade, meu problema era totalmente diferente (erro um pouco noobish). Veja isto: stackoverflow.com/questions/31067082/…
User31689
27

Você pode definir o quanto ele se expande ou entra em colapso com seu animador personalizado. Basta usar o setTopAndBottomOffset(int).

Aqui está um exemplo:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt();
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
            appBar.requestLayout();
        }
    });
    valueAnimator.setIntValues(0, -900);
    valueAnimator.setDuration(400);
    valueAnimator.start();
}
Gerhard
fonte
2
Essa é a única resposta que permite animar para um deslocamento personalizado. Muito Obrigado!
Guilherme Torres Castro
2
appBar.setExpanded (false, true); (abrir / fechar, animado) Você não precisa escrever todas essas linhas
Puni
2
para @Puni, se você quiser expandir / recolher para um deslocamento "personalizado" (como fazer o recolhimento de vários estágios), será necessário.
曾其威
Esta é a melhor solução para animar o deslocamento da AppBar, caso você não queira escrever um comportamento personalizado. A única atualização no trecho de código é chamar valueAnimator.setIntValues ​​() com o valor inicial behavior.topAndBottomOffset em vez de 0 para iniciar a animação do deslocamento atual da barra de aplicativos.
Reel
Para usar uma variável personalizada ( -900 )para definir valueAnimator.setIntValuesA solução do - ( appBar.getTotalScrollRange() )
apostador
12

Eu escrevi uma pequena extensão para AppBarLayout. Permite a expansão e o colapso de CollapsibleToolbarLayoutambos com e sem animação. Parece estar fazendo tudo certo.

Sinta-se livre para experimentar.

Basta usá-lo em vez do seu AppBarLayout e poderá chamar métodos responsáveis ​​pela expansão ou recolhimento do CollapsingToolbarLayout.

Está funcionando exatamente como o esperado no meu projeto, mas você pode precisar ajustar os valores de arremesso / rolagem nos perform...métodos (especialmente em performExpandingWithAnimation()) para se ajustar perfeitamente ao seu CollapsibleToolbarLayout.

Bartek Lipinski
fonte
@ssdeno, leia o arquivo Leiame.md da essência do Github. Está obsoleto desde a v23 da biblioteca de Suporte. Desde a v23 do Suporte (passando para AndroidX), existe um setExpandedmétodo no AppBarLayout.
Bartek Lipinski
6

Use mAppBarLayout.setExpanded(true)para expandir a Barra de Ferramentas e use mAppBarLayout.setExpanded(false)para recolher a Barra de Ferramentas.

Se você deseja alterar a altura de CollapsingToolbarLayout programaticamente, basta usar mAppBarLayout.setLayoutParams(params);

Expandir:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*200; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(true);

Colapso:

CoordinatorLayout.LayoutParams params =(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*80; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(false);
Ferdous Ahamed
fonte
1
Isso me ajudou muito.
NoName
1
Isso é muito útil. Obrigado!
sunlover3
5

para aqueles que querem trabalhar com onNestedPreScroll e obter erros como eu. eu recebo NullPointerException no onCreate com esta linha

    CoordinatorLayout coordinator =(CoordinatorLayout)findViewById(R.id.tab_maincontent);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
    //below line
    params.setBehavior(new AppBarLayout.Behavior() {});

e não funciona corretamente com isso. mas eu trabalho em torno deste problema com

em onCreate:

        scrollToolbarOnDelay();

e...

    public void scrollToolbarOnDelay() {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.tab_appbar);
                    CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.tab_maincontent);
                    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
         if(behavior!=null)
                    behavior.onNestedPreScroll(coordinator, appBarLayout, null, 0, 100, new int[]{0, 0});
         else
            scrollToolbarOnDelay()
                }
            }, 100);


        }
Sepehr Nozaryian
fonte
1

Tente isso ...

Expandir

appBarLayout.setExpanded(true, true);

Recolher

appBarLayout.setExpanded(false, true);
Victor Sam VS
fonte
0

Isso pode ajudar a expandir ou contrair:

appBarLayout.setActivated(true);
appBarLayout.setExpanded(true, true);
ROHIT LIEN
fonte
0

eu tenho usando isso

 private fun collapseAppbar() {
        scrollView.postDelayed(Runnable {
            scrollView?.smoothScrollTo(50, 50)
        }, 400)
    }
denizs
fonte
0

Para expandir / recolher AppBarLayout programaticamente:

fun expandAppBarLayout(expand: Boolean, isAnimationEnabled: Boolean){
    appBarLayout.setExpanded(expand, isAnimationEnabled);
}
avisador
fonte