继续这种类似的效果,[创建动画](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;
}
这只是从图像滚动到顶部。我需要点击打开图片。怎么做?
提前致谢。
答案 0 :(得分:0)
好的,我在你要链接到的问题(Creating animation for images from small to large when scrolling vertical)中玩了自定义视图,添加动画非常简单。结果如下:
首先,我们必须将自定义视图捕捉到某个项目。为此,我们必须像这样修改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"
。这就是让这个视图为任何布局更改设置动画所需的全部内容。