我在scrollivew内的linearlayout中有一个imageViews数组。 图像视图具有onTouchEvent并在滚动时获得DOWN触摸事件。 我需要一个方法,所以我可以在没有拦截DOWN事件的视图的情况下滚动。
儿童触控听众
image.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Animation scale = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scale.setInterpolator(new DecelerateInterpolator());
scale.setFillEnabled(true);
scale.setFillBefore(true);
scale.setFillAfter(true);
scale.setDuration(300);
v.startAnimation(scale);
image.getParent().getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
image.getParent().getParent().requestDisallowInterceptTouchEvent(false);
scale = new ScaleAnimation(0.5f, 1.0f, 0.5f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scale.setInterpolator(new OvershootInterpolator());
scale.setFillEnabled(true);
scale.setFillBefore(true);
scale.setFillAfter(true);
scale.setDuration(200);
scale.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
toggle();
}
});
image.startAnimation(scale);
mPager.setCurrentItem(image.getId(), false);
v.performClick();
break;
case MotionEvent.ACTION_CANCEL:
scale = new ScaleAnimation(0.5f, 1.0f, 0.5f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scale.setInterpolator(new OvershootInterpolator());
scale.setFillEnabled(true);
scale.setFillBefore(true);
scale.setFillAfter(true);
scale.setDuration(200);
scale.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
toggle();
}
});
image.startAnimation(scale);
mPager.setCurrentItem(image.getId(), false);
v.performClick();
break;
}
return true;
}
});
答案 0 :(得分:1)
每一组"一系列行动"从ACTION_DOWN
开始,因此您的ImageView
将始终获得此操作,因为他们可以处理它(状态更改)。但ACTION_MOVE
只能由ScrollView
处理,因此这些TouchEvent
会通过论坛Button-child(已调度)传递给ScrollView-parent(通过LinearLayout)。
您可以使用调度和拦截TouchEvent
s(more here)并将您的操作类型传递给正确的View
但是......你怎么知道用户想要什么?在确切的触摸时刻(ACTION_DOWN
)用户可能想要滚动或单击按钮,因此您不知道如何/谁将调度以后的事件以及视图的行为方式。我在您的代码中看到您希望为按钮添加动画效果 - 最好尝试使用其状态并在state_pressed
更改为true
时开始动画,并在设置false
时将其反转。但它可能会给你同样的效果。另一种方法是在按钮被点击时保持整个ScrollView
(some examples),但其在UX方面的解决方案很差
查看Google Play中的某些应用,甚至是Google Play应用。在任何列表上按任何可点击的视图/应用程序 - 它会改变背景,在棒棒糖上有一些涟漪效果等....但是当您按下整个视图时,按下View / App会失去这些效果(state_pressed
为false)。你无法猜出用户在ACTION_DOWN
时想要做什么,所以上述效果(失败)是正常的
编辑:
正如我所说 - 在ACTION_DOWN
时刻猜测用户想要做什么(点击/滚动)是没有办法和正确的行为,所以你的代码和使用都很好。几乎...
这是我的一个(非常古老的)自定义视图的示例,名为Arrow(它包含箭头;))
@SuppressLint("NewApi") //Honeycomb ofc, use NineOldAndroid for older
public class Arrow extends ImageView implements ValueAnimator.AnimatorUpdateListener{
ValueAnimator va_scaleX=null, va_scaleY=null;
public Arrow(Context context) {
super(context);
createAnimation();
}
public Arrow(Context context, AttributeSet attrs) {
super(context, attrs);
createAnimation();
}
public Arrow(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
createAnimation();
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
private void createAnimation() {
if (va_scaleX == null || va_scaleY==null) {
va_scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.5f);
va_scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.5f);
/* useful, optional, similar methods from Animation
va_scaleX.setDuration(150);
va_scaleY.setDuration(150);
va_scaleX.setInterpolator(new LinearInterpolator());
va_scaleY.setInterpolator(new LinearInterpolator());*/
va_scaleY.addUpdateListener(this); //one is enough
}
}
public void startAnimation() {
va_scaleX.start();
va_scaleY.start();
}
public void reverseAnimation() {
va_scaleX.reverse();
va_scaleY.reverse();
}
}
它不是最好的方式(两个动画师),但是就像魅力一样..请注意,虽然动画此View可绘制状态不会刷新(例如,当您将selector
设置为背景时)。使用ValueAnimator
代替常规Animation
arrow.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
a.startAnimation();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
a.reverseAnimation();
break;
default:
break;
}
return false;
}
});
它会创建平滑的反向动画,因此当用户按下箭头(ACTION_DOWN
)时,动画将会启动,但是当此视图的下一个动作不适用时(在这种情况下为ACTION_MOVE
){将调用{1}}方法,将此视图返回到原始大小。整个操作将非常快,因此用户甚至不会注意到这个小的调整大小(和反转)