在点击向上滑动时创建动画,向下按下以向下滑动android

时间:2014-04-21 15:47:57

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

继续这种类似的效果,[创建动画](Creating animation for images from small to large when scrolling vertical)我需要点击打开图像,而不是将图像拖到上下。怎么做? 任何想法?

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

这只是从图像滚动到顶部。我需要点击打开图片。怎么做?

提前致谢。

1 个答案:

答案 0 :(得分:0)

好的,我在你要链接到的问题(Creating animation for images from small to large when scrolling vertical)中玩了自定义视图,添加动画非常简单。结果如下:

Scrolling Clicking

首先,我们必须将自定义视图捕捉到某个项目。为此,我们必须像这样修改ScrollTouchListener

public abstract class ScrollTouchListener implements View.OnTouchListener {

    private boolean touching = false;
    private boolean scrolling = false;
    private double x = 0;
    private double y = 0;

    private double scrollPositionX = 0;
    private double scrollPositionY = 0;

    @Override
    public boolean onTouch(View view, MotionEvent event) {


        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = event.getX();
                y = event.getY();
                touching = true;
                return true;

            case MotionEvent.ACTION_UP:
                touching = false;
                if(scrolling) {
                    scrolling = false;
                    onScrollEnded(scrollPositionX, scrollPositionY);
                } else {
                    onClick(x, y); 
                }
                return true;

            case MotionEvent.ACTION_MOVE:
                double newX = event.getX();
                double newY = event.getY();

                double difX =  x - newX;
                double difY =  y - newY;

                if (scrolling) {
                    performScroll(difX, difY);
                } else if(difX > 0 || difY > 0)  {
                    scrolling = true;
                    onScrollStarted(scrollPositionX, scrollPositionY);
                    performScroll(difX, difY);
                }

                x = newX;
                y = newY;
                return true;

            default:
                return false;
        }
    }

    protected abstract void onScrollStarted(double scrollPositionX, double scrollPositionY);
    protected abstract void onScroll(double scrollPositionX, double scrollPositionY, double deltaX, double deltaY);
    protected abstract void onScrollEnded(double scrollPositionX, double scrollPositionY);
    protected abstract void onClick(double x, double y);

    private void performScroll(double difX, double difY) {
        scrollPositionX += difX;
        scrollPositionY += difY;

        onScroll(scrollPositionX, scrollPositionY, difX, difY);
    }

    public double getScrollPositionX() {
        return scrollPositionX;
    }

    public void setScrollPositionX(double scrollPositionX) {
        this.scrollPositionX = scrollPositionX;
    }

    public double getScrollPositionY() {
        return scrollPositionY;
    }

    public void setScrollPositionY(double scrollPositionY) {
        this.scrollPositionY = scrollPositionY;
    }
}

基本上我刚添加了onScrollStarted()的回调,当用户开始滚动时调用该回调 - 在这种情况下我们不需要 - 以及当用户停止滚动时调用的onScrollEnded()。为了方便起见,我将跟踪滚动进度的责任移到了ScrollTouchListener,我还添加了getter和setter,以便我们可以根据需要修改滚动进度 - 在我们的例子中,视图可以捕捉到某些位置。我添加的另一件事是onClick回调形式的点击检测。我们需要这样,所以我们可以点击一个视图来扩展它。我们无法使用普通的OnClickListener,因为我们在OnTouchListener中添加ScrollTouchListener消耗所有触摸事件,因此点击侦听器停止工作。但点击检测并不完美,因为它在那里实现。主要问题是只有在您不移动手指时才会计算点击次数。如果你的手指只移动一个像素,它就算作滚动。这里应该有一些额外的逻辑,你可以将你的手指移动几个像素,它仍然算作点击,如果有必要,这可以在以后实施。

然后在自定义视图中,我们为onScroll()中的ScrollTouchListener方法的实现添加了一个计算,该方法计算当前展开的视图和顶部第一个可见视图的索引: / p>

double relativeScroll = scrollPositionY / scrollProgressPerView;
currentItemIndex = (int)Math.round(relativeScroll);

currentItemIndex是自定义视图的成员变量。之后添加onScrollEnded()onClick()方法的实现。我们所做的就是计算自定义视图应该滚动多远。要么捕捉到某个项目,要么滚动到所单击的项目:

@Override
protected void onScrollEnded(double scrollPositionX, double scrollPositionY) {
    scrollProgress = currentItemIndex * scrollProgressPerView + 1;
    setScrollPositionY(scrollProgress);
    updateChildViews();
}

@Override
protected void onClick(double x, double y) {
    int clickedIndex = (int) Math.round((getScrollPositionY() + y) / scrollProgressPerView) + 1;
    scrollProgress = clickedIndex * scrollProgressPerView + 1;
    setScrollPositionY(scrollProgress);
    updateChildViews();
}

就是这样。这就是启用捕捉和选择Views所需的全部内容。因此,自定义视图中ScrollTouchListener的整个实现应如下所示:

private final ScrollTouchListener touchListener = new ScrollTouchListener() {

    @Override
    protected void onScrollStarted(double scrollPositionX, double scrollPositionY) {
        // Nothing to do here
    }

    @Override
    protected void onScroll(double scrollPositionX, double scrollPositionY, double deltaX, double deltaY) {
        scrollProgress += deltaY;
        if(scrollProgress < 0.0) {
            scrollProgress = 0.0;
        }

        if(scrollProgress > maxScrollProgress) {
            scrollProgress = maxScrollProgress;
        }

        double relativeScroll = scrollPositionY / scrollProgressPerView;
        currentItemIndex = (int)Math.round(relativeScroll);

        updateChildViews();
    }

    @Override
    protected void onScrollEnded(double scrollPositionX, double scrollPositionY) {
        scrollProgress = currentItemIndex * scrollProgressPerView + 1;
        setScrollPositionY(scrollProgress);
        updateChildViews();
    }

    @Override
    protected void onClick(double x, double y) {
        int clickedIndex = (int) Math.round((getScrollPositionY() + y) / scrollProgressPerView) + 1;
        scrollProgress = clickedIndex * scrollProgressPerView + 1;
        setScrollPositionY(scrollProgress);
        updateChildViews();
    }
};

您可能想知道实际动画内容的来源,但我们实际上并不需要照顾它。有一个非常方便的功能可以为我们处理所有动画。您只需将此属性添加到xml布局中的自定义视图属性:

android:animateLayoutChanges="true"

例如,我用于测试目的的布局如下所示:

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

    <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.customviews.accordion.view.Accordion>

请注意我添加到自定义视图的android:animateLayoutChanges="true"。这就是让这个视图为任何布局更改设置动画所需的全部内容。

相关问题