Animacja widoku przesuwanie się z innego widoku, przesuwanie widoków poniżej

Mam listę przycisków. Po naciśnięciu przycisku Widok powinien przesuwać się ruchem w dół z przycisku, Tak:

Start:
Tutaj wpisz opis obrazka

Halfway:
Tutaj wpisz opis obrazka

End:
Tutaj wpisz opis obrazka

Jak mam to zrobić? Widok, który powinien się wysunąć jest większy niż przycisk, więc najpierw ukrycie widoku za przyciskiem, a następnie przesunięcie go w dół powoduje, że widok jest widoczny powyżej przycisku. To nie powinno się zdarzyć.

Wszelkie pomysły lub przykłady, jak podchodzisz do tego?

Author: nhaarman, 2012-12-14

7 answers

Uważam, że najprostszym podejściem jest rozszerzenie Animation klasy i nadpisanie applyTransformation(), aby zmienić wysokość widoku w następujący sposób:

import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;

public class MyCustomAnimation extends Animation {

    public final static int COLLAPSE = 1;
    public final static int EXPAND = 0;

    private View mView;
    private int mEndHeight;
    private int mType;
    private LinearLayout.LayoutParams mLayoutParams;

    public MyCustomAnimation(View view, int duration, int type) {

        setDuration(duration);
        mView = view;
        mEndHeight = mView.getHeight();
        mLayoutParams = ((LinearLayout.LayoutParams) view.getLayoutParams());
        mType = type;
        if(mType == EXPAND) {
            mLayoutParams.height = 0;
        } else {
            mLayoutParams.height = LayoutParams.WRAP_CONTENT;
        }
        view.setVisibility(View.VISIBLE);
    }

    public int getHeight(){
        return mView.getHeight();
    }

    public void setHeight(int height){
        mEndHeight = height;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        super.applyTransformation(interpolatedTime, t);
        if (interpolatedTime < 1.0f) {
            if(mType == EXPAND) {
                mLayoutParams.height =  (int)(mEndHeight * interpolatedTime);
            } else {
                mLayoutParams.height = (int) (mEndHeight * (1 - interpolatedTime));
            }
            mView.requestLayout();
        } else {
            if(mType == EXPAND) {
                mLayoutParams.height = LayoutParams.WRAP_CONTENT;
                mView.requestLayout();
            }else{
                mView.setVisibility(View.GONE);
            }
        }
    }
}

Aby go użyć, ustaw onclick() w następujący sposób:

int height;

@Override
public void onClick(View v) {
    if(view2.getVisibility() == View.VISIBLE){
        MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.COLLAPSE);
        height = a.getHeight();
        view2.startAnimation(a);
    }else{
        MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.EXPAND);
        a.setHeight(height);
        view2.startAnimation(a);
    }
}
Pozdrawiam.
 71
Author: Luis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-30 09:58:06

Użyj czegoś w stylu:

 Animation a = new ScaleAnimation(1, 1, 0, 1, Animation.RELATIVE_TO_SELF, (float) 0.5,    Animation.RELATIVE_TO_SELF, (float) 0);
 a.setFillAfter(true);
 view.setAnimation(a);
 a.setDuration(1000);
 view.startAnimation(a);
 3
Author: neteinstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-19 14:29:16

Oto prosty przykład ręcznie robionej animacji, która zapewnia to, co chcesz. Działa w aplikacji testowej, ale nie jestem pewien, czy nie ma błędów:

public class MainActivity extends Activity implements OnClickListener {
private Timer timer;
private TimerTask animationTask;
private View view1;
private View view2;
boolean animating;
boolean increasing = true;
int initHeight = -1;
private LayoutParams params;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    timer = new Timer();

    view1 = findViewById(R.id.view1);// clickable view
    view1.setOnClickListener(this); 

    view2 = findViewById(R.id.view2);// animated view
    params = view2.getLayoutParams();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    timer.cancel();
}

@Override
public void onClick(View v) {
    Toast.makeText(this, "start animating...", Toast.LENGTH_SHORT).show();

    animationTask = new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (animationFinished()) {
                        animating = false;
                        cancel();//canceling animating task
                        return;
                    }
                    params.height += increasing ? 1 : -1;
                    view2.setLayoutParams(params);
                }
            });
        }

        private boolean animationFinished() {
            int viewHeight = view2.getHeight();
            if (increasing && viewHeight >= initHeight) {
                return true;
            }
            if (!increasing && viewHeight <= 0) {
                return true;
            }
            return false;
        }
    };

    //if we already animating - we just change direction of animation
    increasing = !increasing;
    if (!animating) {
        animating = true;
        int height = view2.getHeight();

        params.height = height;
        view2.setLayoutParams(params);//change param "height" from "wrap_conent" to real height

        if (initHeight < 0) {//height of view - we setup it only once
            initHeight = height;
        }
        timer.schedule(animationTask, 0, 10);//changing repeat time here will fasten or slow down animation
    }
}
}
 3
Author: Jin35,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-20 14:10:04

Może możesz ustawić wysokość na 0 i stopniowo zwiększać wysokość. Ale wtedy będziesz miał problem, że musisz mieć pewność, że Twój tekst jest wyrównany u dołu widoku. A także wiedzieć, jaka powinna być maksymalna wysokość widoku.

 2
Author: ndsmyter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-14 22:22:25

Zrobiłbym to w ten sposób. Najpierw układ całego składanego panelu: (pseudo xml)

RelativeLayout (id=panel, clip)
    LinearLayout (id=content, alignParentBottom=true)
    LinearLayout (id=handle, above=content)

Powinno to zapewnić, że zawartość jest zawsze poniżej uchwytu.

Wtedy, gdy trzeba się zwinąć:

  • Animacja górnego marginesu zawartości od 0 do-content.wysokość
  • animuje wysokość panelu od bieżącej do bieżącej zawartości.wysokość
 1
Author: Vincent Mimoun-Prat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-19 14:43:17

Korzystanie z adaptera listy przesuwnej jest o wiele łatwiejsze niż wygłupianie się animacjami

Https://github.com/tjerkw/Android-SlideExpandableListView

 1
Author: Aiden Fry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-19 14:52:12

Po prostu prześlij android:animateLayoutChanges do LinearLayout, który zawiera wszystkie widoki, osiągniesz pożądany rezultat.

 -1
Author: Muhammad Hassaan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 11:19:46