Android的:如何检测时滚动已经结束
-
21-09-2019 - |
题
我使用GestureDetector.SimpleOnGestureListener的onScroll方法来滚动画布上的大的位图。当滚动结束我要重绘的情况下,用户想要进一步滚动...离位图的边缘位图,但我不能看到如何从滚动结束检测(用户抬起手指从屏幕)。
e2.getAction()似乎总是返回值2,使得没有帮助。 e2.getPressure似乎当压力似乎下降到大约0.13%至返回相当恒定值(约0.25),直到最后onScroll通话。我想我可以检测压力这种减少,但是这将是远离万无一失。
必须有一个更好的办法?谁能帮助,请
解决方案
下面是我如何解决了这个问题。希望这有助于。
// declare class member variables
private GestureDetector mGestureDetector;
private OnTouchListener mGestureListener;
private boolean mIsScrolling = false;
public void initGestureDetection() {
// Gesture detection
mGestureDetector = new GestureDetector(new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
handleDoubleTap(e);
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
handleSingleTap(e);
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// i'm only scrolling along the X axis
mIsScrolling = true;
handleScroll(Math.round((e2.getX() - e1.getX())));
return true;
}
@Override
/**
* Don't know why but we need to intercept this guy and return true so that the other gestures are handled.
* https://code.google.com/p/android/issues/detail?id=8233
*/
public boolean onDown(MotionEvent e) {
Log.d("GestureDetector --> onDown");
return true;
}
});
mGestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) {
return true;
}
if(event.getAction() == MotionEvent.ACTION_UP) {
if(mIsScrolling ) {
Log.d("OnTouchListener --> onTouch ACTION_UP");
mIsScrolling = false;
handleScrollFinished();
};
}
return false;
}
};
// attach the OnTouchListener to the image view
mImageView.setOnTouchListener(mGestureListener);
}
其他提示
您应该看一看 http://developer.android.com /reference/android/widget/Scroller.html 。 尤其是,这可能会有所帮助(按相关性排序):
isFinished();
computeScrollOffset();
getFinalY(); getFinalX(); and getCurrY() getCurrX()
getDuration()
这意味着你必须创建一个滚轮。
如果你想使用触摸你也可以使用GestureDetector和定义自己的画布上滚动。下面的示例是创建一个ScrollableImageView,为了使用它,你必须确定你的图像的测量。您可以定义自己的滚动范围和整理你的滚动形象得到重绘后。
http://www.anddev.org/viewtopic.php?p = 31487#31487
根据您的代码,您应该考虑无效(int类型l,诠释T,INT R,INT B);为无效。
SimpleOnGestureListener.onFling()
这似乎发生时滚动结束(即用户让手指去),这就是我使用,它为我的伟大工程。
说回这几个月后,我现在已经遵循了不同的策略:通过处理器(作为Android的蛇样品中)将消息发送到应用程序每125毫秒它会提示它来检查滚动是否有被启动和是否大于100毫秒自上次滚动事件是否已经过去。
这似乎工作得很好,但如果任何人都可以看到任何缺陷或可能的改进我应该感谢听到他们的。
相关的代码是在MyView的类:
public class MyView extends android.view.View {
...
private long timeCheckInterval = 125; // milliseconds
private long scrollEndInterval = 100;
public long latestScrollEventTime;
public boolean scrollInProgress = false;
public MyView(Context context) {
super(context);
}
private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();
class timeCheckHandler extends Handler{
@Override
public void handleMessage(Message msg) {
long now = System.currentTimeMillis();
if (scrollInProgress && (now>latestScrollEventTime+scrollEndInterval)) {
scrollInProgress = false;
//滚动已结束,所以在这里插入代码
//它调用doDrawing()方法
//重绘位图重新定中心,其中滚动结束
[ layout or view ].invalidate();
}
this.sleep(timeCheckInterval);
}
public void sleep(long delayMillis) {
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
}
@Override protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//代码绘制大的缓冲位图上视图的画布 //定位以采取任何滚动正在进行中的帐户
}
public void doDrawing() {
//代码做详细(和耗时)的描绘 //到大的缓冲位图
//以下指令复位时间检查时钟 //时钟刚开始的时候 //应用程序启动时的主要活动调用此方法
mTimeCheckHandler.sleep(timeCheckInterval);
}
// MyView的类的其余部分
}
和在MyGestureDetector类
public class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
[MyView].scrollInProgress = true;
long now = System.currentTimeMillis();
[MyView].latestScrollEventTime =now;
[MyView].scrollX += (int) distanceX;
[MyView].scrollY += (int) distanceY;
//下一指令使被称为视图的OnDraw方法 //图表缓冲区位图在屏幕上 //偏移以考虑到滚动的
[MyView].invalidate();
}
//其余MyGestureDetector类的
}
我一直在寻找这个同样的问题。只见阿科什锆石回答你的问题。我创建了类似的东西,但我的版本,我注意到它只是工作的一个常规滚动 - 这意味着一个不产生一扔。但是,如果一个一扔没有得到产生 - 无论如果我处理的一扔或者没有,那么它并没有“的onTouchEvent”检测“ACTION_UP”。现在,也许这只是一些我的执行,但如果是我无法找出原因。
经过进一步调查,我发现一个一扔期间,“ACTION_UP”被传递到“onFling”中的“E2”每次。所以我想那一定是为什么它没有被在“的onTouchEvent”在这些情况下进行处理。
要让它为我工作,我只需要调用“onFling”处理“ACTION_UP”的方法,然后它的工作对两种类型的滚动。下面是我带的具体步骤在我的应用程序来实现:
在一个构造-initialized一个 “gestureScrolling” 布尔 “假”。
-I其设置为 “真”,在 “onScroll”
-created处理“ACTION_UP”事件的方法。里面那个事件,我重置“gestureSCrolling”为false,然后做了处理的其余部分我需要做的。
-in “的onTouchEvent”,如果检测到 “ACTION_UP” 和 “gestureScrolling”=真,然后我打电话给我的方法来处理 “ACTION_UP”
-and,我没有,这是不同的部分是:我也被称为我的方法来处理“ACTION_UP”的“onFling”内
我相信这是对你太晚了,但是,看来我已经找到了合适的解决方案,以你原来的问题,而不是必要的意向。
如果使用的是滚轮/ OverScroller对象用于滚动,则应该从下面的函数检查返回值。
public boolean computeScrollOffset()
享受
harvinder
这是为我工作。
我丰富了现有的 GestureDetector.OnGestureListener 强>使用的 onFingerUp()方式。这听众做的一切,内置GestureDetector而且还可以收听到手指事件(它不是onFling(),因为这只有当手指与快速轻扫动作一起举起被调用)。
import android.content.Context;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class FingerUpGestureDetector extends GestureDetector {
FingerUpGestureDetector.OnGestureListener fListener;
public FingerUpGestureDetector(Context context, OnGestureListener listener) {
super(context, listener);
fListener = listener;
}
public FingerUpGestureDetector(Context context, GestureDetector.OnGestureListener listener, OnGestureListener fListener) {
super(context, listener);
this.fListener = fListener;
}
public FingerUpGestureDetector(Context context, GestureDetector.OnGestureListener listener, Handler handler, OnGestureListener fListener) {
super(context, listener, handler);
this.fListener = fListener;
}
public FingerUpGestureDetector(Context context, GestureDetector.OnGestureListener listener, Handler handler, boolean unused, OnGestureListener fListener) {
super(context, listener, handler, unused);
this.fListener = fListener;
}
public interface OnGestureListener extends GestureDetector.OnGestureListener {
boolean onFingerUp(MotionEvent e);
}
public static class SimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener implements FingerUpGestureDetector.OnGestureListener {
@Override
public boolean onFingerUp(MotionEvent e) {
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (super.onTouchEvent(ev)) return true;
if (ev.getAction() == MotionEvent.ACTION_UP) {
return fListener.onFingerUp(ev);
}
return false;
}
}
我还没有完成这件事,但我自己)看onTouch(你总是得到一个序列0 <2> 1,所以最终必须是一个1手指抬起。
我不知道Android的,但看着似乎罗布的文档是正确的:的 Android的ACTION_UP恒定尝试从的getAction检查ACTION_UP()?
编辑:这是什么e1.getAction()说明了什么?它是否还回ACTION_UP?文档指出保持初始关闭事件,所以也许它还会当指针向上通知
编辑:只有两件事我能想到的。你在任何时候返回false?可能阻止ACTION_UP
唯一的其他东西我会尝试是有一个单独的事件,也许onDown,并设置内onScroll的标志,如isScrolling。当ACTION_UP给予onDown和isScrolling设置,那么你可以做任何你想做和复位isScrolling为false。也就是说,假设onDown获取与onScroll沿着调用,并且将的getAction期间onDown返回ACTION_UP
我还没有试过/使用该但对于一种方法一个想法:
<强>停止/中断在每个滚动事件重绘帆布等待1秒,然后开始在每个滚动重绘画布。强>
这会导致仅在滚动结束执行重绘作为只有最后滚动实际上将不间断重绘来完成。
希望这样的想法可以帮助你:)
从GestureListener API的onScroll事件提取物:链接文本
公共抽象布尔onScroll (MotionEvent E1,E2 MotionEvent,浮 distanceX,浮法distanceY)自:API 级别1
<强>返回 *返回:如果该事件被消耗掉,否则为假强>
也许一旦事件已被消耗时,动作结束,并且用户已经采取了他们的手指从屏幕或者至少完成了这个onScroll动作
您可以使用这个在IF语句来扫描== true,然后下一个动作开始。
我想这会工作,因为你需要
protected class SnappingGestureDetectorListener extends SimpleOnGestureListener{
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){
boolean result = super.onScroll(e1, e2, distanceX, distanceY);
if(!result){
//Do what you need to do when the scrolling stop here
}
return result;
}
}
我试图在添加额外的功能,以手势检测器。希望它可以帮助别人把自己的时间来更好地利用...
https://gist.github.com/WildOrangutan/043807ddbd68978179b7cea3b53c71e8