ImageView - 拉伸或下拉缩放

4

如何使用ImageView实现此功能,PullToZoom (不需要在示例中使用ListView)?

类似的问题,但没有答案 :(

2个回答

3
使用手势检测器(Gesture Detector)如何呢?您可以在以下代码中找到需要的实现(我认为): Gesture Detector。请注意,保留HTML标记,但不要写解释。
public class MainActivity extends AppCompatActivity {

    private static final String DEBUG_TAG = "Gestures";

    private GestureDetectorCompat mDetector;
    private ImageView imageView;
    private MyGestureListener myGestureListener;

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

        imageView = (ImageView) findViewById(R.id.image);

        myGestureListener = new MyGestureListener();
        mDetector = new GestureDetectorCompat(this, myGestureListener);
        imageView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                int action = MotionEventCompat.getActionMasked(event);
                if (action == MotionEvent.ACTION_UP) {
                    myGestureListener.upDetected();
                }
                return mDetector.onTouchEvent(event);
            }
        });

        imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.test));

    }

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final float MAX_ZOOM = 0.5f;

        private static final float PCT = 300f;
        private float delta;

        private ValueAnimator valueAnimator;

        @Override
        public boolean onDown(MotionEvent event) {
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if (valueAnimator != null) {
                valueAnimator.cancel();
            }

            delta += distanceY;
            float pct = getPct(delta);
            imageView.setScaleX(1.0f + pct);
            imageView.setScaleY(1.0f + pct);
            return false;
        }

        void upDetected() {

            float pct = getPct(delta);

            valueAnimator = new ValueAnimator();
            valueAnimator.setFloatValues(pct, 0.0f);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    imageView.setScaleX(1.0f + (float) animation.getAnimatedValue());
                    imageView.setScaleY(1.0f + (float) animation.getAnimatedValue());
                }
            });
            valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    delta = 0f;
                    imageView.setScaleX(1.0f);
                    imageView.setScaleY(1.0f);
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            valueAnimator.start();
        }

        private float getPct(float delta) {
            float pct = delta / PCT;
            if (pct >= MAX_ZOOM) {
                pct = MAX_ZOOM;
            }
            else if (pct <= -MAX_ZOOM) {
                pct = -MAX_ZOOM;
            }
            return pct;
        }
    }
}

MainActivity有一个简单的ImageView。 当你在其中“滚动”时,会检测手势并缩放图像(向上或向下)。 当你从屏幕上放开手指时,图像会通过简单的动画缩放回到原始大小。 如果你想避免缩小,只需要在getPct()方法上进行修改。

编辑

例如,如果你只想实现缩放功能,可以像这样修改getPct:

private float getPct(float delta) {
    float pct = -delta / PCT;
    if (pct >= MAX_ZOOM) {
        pct = MAX_ZOOM;
    }
    else if (pct <= 0) {
        pct = 0;
    }
    return pct;
}

编辑 #2

似乎手势检测器的第一个滚动事件是宽广的。我已经添加了一些代码来忽略它。

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

    private static final float MAX_ZOOM = 0.8f;

    private static final float PCT = 300f;
    private float delta;

    private ValueAnimator valueAnimator;
    private boolean mFirstEvent = true;

    @Override
    public boolean onDown(MotionEvent event) {
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        if (valueAnimator != null) {
            valueAnimator.cancel();
        }

        if (mFirstEvent) {
            mFirstEvent = false;
            return false;
        }

        delta += distanceY;
        float pct = getPct(delta);
        imageView.setScaleX(1.0f + pct);
        imageView.setScaleY(1.0f + pct);
        textView.setScaleY(1.0f - pct);
        return false;
    }

    void upDetected() {

        mFirstEvent = true;
        float pct = getPct(delta);

        valueAnimator = new ValueAnimator();
        valueAnimator.setFloatValues(pct, 0.0f);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                imageView.setScaleX(1.0f + (Float) animation.getAnimatedValue());
                imageView.setScaleY(1.0f + (Float) animation.getAnimatedValue());
                textView.setScaleY(1.0f - (Float) animation.getAnimatedValue());
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                delta = 0f;
                imageView.setScaleX(1.0f);
                imageView.setScaleY(1.0f);
                textView.setScaleY(1.0f);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        valueAnimator.start();
    }

    private float getPct(float delta) {
        float pct = -delta / PCT;
        if (pct >= MAX_ZOOM) {
            pct = MAX_ZOOM;
        }
        else if (pct <= 0) {
            pct = 0;
        }
        return pct;
    }

    /*private float getPct(float delta) {
        float pct = delta / PCT;
        if (pct >= MAX_ZOOM) {
            pct = MAX_ZOOM;
        }
        else if (pct <= -MAX_ZOOM) {
            pct = -MAX_ZOOM;
        }
        return pct;
    }*/
}

实际上它并没有在拉动时缩放。它会检测 ACTION_UP 手势并自动缩放到指定值。我想要的是根据用户滚动或拉动的量来缩放。 - Atul O Holic
你想要改变什么?我不明白。 - Mimmo Grottoli
当你向下拉或向下滚动(仅限向下操作)时,图像应该放大,当你离开它时,它会恢复到正常状态。这是我正在尝试的两件事中的一件。 - Atul O Holic
https://drive.google.com/file/d/0ByhJIK8n7rQ4WFk0clN3M21PbTQ/view?usp=sharing - 你能看到这个图片在抖动吗? - Atul O Holic
这并不是第一个事件的问题,问题在于当我们从中心某处拖动时它能正常工作,但当我们从边缘拖动时会出现问题。感谢所有的帮助,我会解决这个问题并让你知道的。 - Atul O Holic
显示剩余5条评论

0

安卓上的Tinder应用程序通过覆盖onTouchEvent()方法来实现类似的功能。查看this帖子以了解更多信息。


是的,那是我看到的第一件事。但它是为一个列表视图标题实现的,并且与其关联的高度是固定的。我正在尝试仅使用ImageView获得相同效果,而不必固定高度。 - Atul O Holic
没错,但是重写 View 的 onTouchEvent() 方法可能会解决它。 - frgnvola
是的,但我从代码中也可以看出它还在使用Listview的ScrollListener。 - Atul O Holic
https://github.com/Gnod/ParallaxListView/blob/master/src/com/gnod/parallaxlistview/ParallaxScollListView.java - 这是你提到的示例中使用的类。 - Atul O Holic
我实际上是在谈论第二个答案,其中覆盖了onTouchEvent()方法。 - frgnvola
让我们在聊天室中继续此讨论 - Atul O Holic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接