Gestire le animazioni su elementi dentro un ConstraintLayout

Il problema, quando si utilizza un ConstraintLayout, è che il sistema dà la priorità ai "constraint" più che alle specifiche altezze (che non vengono prese in considerazione).

Per gestire delle animazioni (o anche solo per gestire cambi di dimensioni), è necessario utilizzare di ConstraintSet e reimpostarli al bisogno.

Ecco un codice di esempio che gestisce la procedura:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
// button che avvia l'animazione
Button btn = (Button) findViewById(R.id.btnRileva);

// listener per l'attività
btn.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(final View v)
    {
        // contenitore RelativeLayout
        final RelativeLayout rlContainer = (RelativeLayout) findViewById(R.id.rlContainer);

        // parametri di un ConstraintLayout
        final ConstraintLayout clMain = (ConstraintLayout) findViewById(R.id.ccMainLayout);

        // set di "constraint" (da cambiare o da ripristinare)
        final ConstraintSet set = new ConstraintSet();
        final ConstraintSet original = new ConstraintSet();

        // per avere una copia degli originali, bisogna clonarli
        set.clone(clMain);
        original.clone(clMain);

        // altezza iniziale dell'elemento
        final int initialHeight = rlContainer.getMeasuredHeight();

        // durata dell'effetto
        final int duration = (int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density);

        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t)
            {
                // inizio dell'attività di animazione
                if (interpolatedTime == 0)
                {
                    // rottura della connessione del vincolo del contenitore da "animare"
                    set.clear(R.id.rlContainer, ConstraintSet.BOTTOM);

                    // applicazione del set al contenitore "padre" (la root del layout)
                    set.applyTo(clMain);

                    // impostazione dell'altezza iniziale, in modo da non presentare "strane variazioni"
                    rlContainer.getLayoutParams().height = initialHeight;

                    // avverto il sistema che il layout è cambiato, così viene ridisegnato
                    rlContainer.requestLayout();
                }
                // conclusione dell'attività di animazione
                else if(interpolatedTime == 1)
                {
                    // faccio sparire il contenitore
                    rlContainer.setVisibility(View.GONE);
                }
                else
                {
                    // calcolo dell'altezza in base al tempo di interpolazione
                    int height = initialHeight - ((int)(initialHeight * interpolatedTime));

                    // imposto l'altezza
                    rlContainer.getLayoutParams().height = height;

                    // avverto il sistema che il layout è cambiato, così viene ridisegnato
                    rlContainer.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds()
            {
                return true;
            }
        };

        // imposta la durata dell'animazione
        a.setDuration(duration);

        // imposto un listener per gestire avvio e fine dell'animazione
        a.setAnimationListener(new Animation.AnimationListener()
        {
            @Override
            public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation)
            {
                Toast.makeText(getApplicationContext(), "fine dell'animazione", Toast.LENGTH_LONG).show();

                // reimposto il ConstraintSet originale
                original.applyTo(clMain);
                rlContainer.getLayoutParams().height = initialHeight;
                rlContainer.requestLayout();
            }

            @Override
            public void onAnimationRepeat(Animation animation) { }
        });

        // avvio l'animazione
        rlContainer.startAnimation(a);
    }
});

Nessun commento:

Generare un colore randomico di tonalità "pastello"

Questo script restituisce il codice di un colore generato a caso nelle tonalità pastello. La generazione viene definita attraverso le 3 ca...