【问题标题】:Creating animation for images from small to large when scrolling vertical垂直滚动时为从小到大的图像创建动画
【发布时间】:2014-03-18 06:41:00
【问题描述】:

我正在创建图像,当向上滚动时,图像会放大,而剩余的图像会变小。同样,当第二张图片向上推时,它应该放大并显示。我使用手风琴类型,但没有任何效果。我搜索了但找不到。

在 iPhone 中,它具有功能,但我找不到如何为 android 创建。这是为了

在android中实现相同的效果。

我使用 ScaleAnimation 和隐藏和显示布局来打开图像放置在布局内的位置。但这也没有用。

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

有人可以帮我解决这个问题吗?

提前致谢!!

【问题讨论】:

标签: android android-layout android-intent android-animation


【解决方案1】:

我已经创建了一个基本的自定义视图来复制这种行为,它并不完全相同,但我认为它现在已经足够接近了,如果它需要完全相同,这可以通过修改 updateChildViews() 方法来快速实现。我在 20 分钟内写完这门课,所以它远非完美,对于生产就绪的解决方案,还需要做一些额外的工作。通常,此解决方案适用于所有类型的子视图,但要复制确切的行为,请使用 ImageView 作为子视图的背景,并在 ImageViews 上设置此属性:

android:scaleType="centerCrop"

我在当前状态下的解决方案中看到的问题:

  • 仅适用于垂直方向
  • 没有视图回收。
  • 应该派生自 AdapterView 而不是 LinearLayout。

不管怎样,到目前为止是这样的:

这里是源代码:

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,那么following一定是有用的。只需要检测list view的中心元素,并对该行的图像应用缩放效果。下面是代码可用于实施此策略:

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

    【讨论】:

    • 我认为尝试让 ListView 以这种方式运行比编写自定义视图要困难得多。这种效果并不像看起来那么简单,只需将动画应用于某些视图即可。
    • 那么祝你好运......请发布您在这方面的任何线索或想法,以便我也可以与您在同一页面上。
    • 我不太明白你的意思,但你可以看看我的回答。这是一个完整的工作示例。
    • @XaverKapeller 非常棒。我有一个疑问。这意味着应该从AdapterView派生什么?直接扩展为线性布局并在构造函数中,我可以通过添加xml来使用吗? LayoutInflater inflater = (LayoutInflater) 上下文 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); mView = inflater.inflate(R.layout.main, this, false)
    • 我的示例目前正在扩展 LinearLayout,但这不是最佳选择,尤其是在应该显示大量子视图的情况下。对于一个完美的解决方案,自定义视图应该扩展 AdapterView 并实现正确的视图回收。但在大多数情况下,我的自定义视图应该已经是一个很好的解决方案了。
    猜你喜欢
    • 2017-06-23
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多