Создание анимации для изображений от малого до большого при прокрутке по вертикали

Я создаю изображения, в которых при прокрутке изображение должно увеличиваться, а оставшиеся изображения должны уменьшаться. Аналогично, когда второе изображение подталкивается вверх, оно должно увеличиваться и показываться. Я использовал тип аккордеона, но ничего не работает. Я искал, но не смог найти.

В IPhone у него есть функции, но я не мог найти, как создать для Android. Это для

enter image description here

тот же эффект, который будет реализован в android.

Я использовал ScaleAnimation со скрытием и отображением макетов, чтобы открыть, где изображение было размещено внутри макета. Но это также не сработало.

if(openLayout == panel1){
    panel1.startAnimation(new ScaleAnimToHide(1.0f, 1.0f, 1.0f, 0.0f, 200, panel1, true));
}

Может кто-нибудь помочь мне решить эту проблему?

Спасибо заранее!

Ответ 1

Я создал базовое настраиваемое представление, которое реплицирует это поведение, но не полностью одно и то же, но я думаю, что он достаточно близок на данный момент, если он должен быть точно таким же, что можно быстро достичь, изменив метод updateChildViews(). Я написал этот класс за 20 минут, так что он далек от совершенства, для готового к производству решения необходимо выполнить некоторую дополнительную работу. Как правило, это решение работает со всеми видами дочерних представлений, но для репликации точного поведения используйте ImageView в качестве фона для ваших дочерних представлений и установите это свойство в ImageViews:

android:scaleType="centerCrop"

Проблемы, которые я вижу с моим решением в этом текущем состоянии:

  • Работает только в вертикальной ориентации
  • Нет повторной переработки.
  • Должно быть получено из AdapterView, а не LinearLayout.

В любом случае, как это выглядит до сих пор:

enter image description here

Вот исходный код:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

public class Accordion extends LinearLayout {

    private static final String LOG_TAG = Accordion.class.getSimpleName();

    private double scrollProgress = 0.0;
    private double topViewScaleFactor = 2.0;
    private double collapsedViewHeight = 200.0;
    private double expandedViewHeight = 700.0;
    private double scrollProgressPerView = expandedViewHeight;

    private final ScrollTouchListener touchListener = new ScrollTouchListener() {
        @Override
        protected void onScroll(float x, float y) {
            scrollProgress += y;
            if(scrollProgress < 0.0) {
                scrollProgress = 0.0;
            }

            int viewCount = getChildCount();
            double maxScrollProgress = (viewCount - 1) * scrollProgressPerView + 1;
            if(scrollProgress > maxScrollProgress) {
                scrollProgress = maxScrollProgress;
            }

            Log.i(LOG_TAG, String.format("Scroll Progress: %f", scrollProgress));

            updateChildViews();
        }
    };

    public Accordion(Context context) {
        super(context);

        this.setOnTouchListener(this.touchListener);
    }

    public Accordion(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.setOnTouchListener(this.touchListener);
    }

    public Accordion(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        this.setOnTouchListener(this.touchListener);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        updateChildViews();
    }

    private void updateChildViews() {
        int viewCount = getChildCount();
        double progress = scrollProgress;
        double overflow = 0;
        for(int i = 0; i < viewCount; i++) {
            View child = getChildAt(i);
            if(child != null) {
                if(progress >= scrollProgressPerView) {
                    progress -= scrollProgressPerView;
                    child.setVisibility(View.GONE);
                    setChildHeight(child, 0);
                } else if (progress > 0) {
                    setChildHeight(child, expandedViewHeight - progress);
                    overflow = progress;
                    child.setVisibility(View.VISIBLE);
                    progress = 0;
                } else {
                    if(overflow > 0) {
                        double height = collapsedViewHeight + overflow;
                        if(height > expandedViewHeight) {
                            height = expandedViewHeight;
                        }
                        setChildHeight(child, height);
                        overflow = 0;
                    } else {
                        setChildHeight(child, i > 0 ? collapsedViewHeight : expandedViewHeight);
                    }
                    child.setVisibility(View.VISIBLE);
                }
            }
        }
    }

    private void setChildHeight(View child, double height) {
        child.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, (int)height));
    }

    private static abstract class ScrollTouchListener implements OnTouchListener {

        private static final String LOG_TAG = ScrollTouchListener.class.getSimpleName();

        private boolean scrolling = false;
        private float x = 0;
        private float y = 0;

        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = event.getX();
                    y = event.getY();
                    scrolling = true;
                    return true;

                case MotionEvent.ACTION_UP:
                    scrolling = false;
                    return true;

                case MotionEvent.ACTION_MOVE:
                    if (scrolling) {
                        float newX = event.getX();
                        float newY = event.getY();

                        float difX =  x - newX;
                        float difY =  y - newY;
                        onScroll(difX, difY);

                        x = newX;
                        y = newY;
                    }
                    return true;

                default:
                    return false;
            }
        }

        protected abstract void onScroll(float x, float y);
    }
}

Чтобы использовать его, просто поместите его в макет, подобный этому:

<at.test.app.Accordion xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">

    <ImageView android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:scaleType="centerCrop"
               android:src="@drawable/alpen"/>

    <ImageView android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:scaleType="centerCrop"
               android:src="@drawable/alpen"/>

    <ImageView android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:scaleType="centerCrop"
               android:src="@drawable/alpen"/>

    <ImageView android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:scaleType="centerCrop"
               android:src="@drawable/alpen"/>

</at.test.app.Accordion>

Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать!

Ответ 2

Я думаю, что если контейнер, который вы используете, является ListView, то следующее должно быть полезным. Просто нужно обнаружить центральный элемент в представлении списка и применить эффект масштабирования к изображению в этой строке. Далее следует код, который могут быть использованы для реализации этой стратегии:

int visibleChildCount = (listView1.getLastVisiblePosition() - listView1.getFirstVisiblePosition()) + 1;

In your getView() method:
if(position==visibleChildCount/2)
{
 //Center Element
 //Apply the Transition Effect From the XML files to the Image to Grow.
}