Skip to content

Instantly share code, notes, and snippets.

@kuanyingchou
Last active January 16, 2016 17:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kuanyingchou/50750564c4a50dc22cfe to your computer and use it in GitHub Desktop.
Save kuanyingchou/50750564c4a50dc22cfe to your computer and use it in GitHub Desktop.
package com.example.ken.remote;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.MotionEvent;
public class BlindGestureDetector {
private float mX = 0;
private float mY = 0;
private boolean mIsPressed = false;
private float mDiff = 0;
private Emitter mEmitter;
private Context mContext;
private Listener mListener;
public BlindGestureDetector(Context context, BlindGestureDetector.Listener listener) {
this.mListener = listener;
this.mContext = context;
}
public boolean onTouchEvent(MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch(action) {
case (MotionEvent.ACTION_DOWN) :
mX = event.getX(); // ignore other fingers
mY = event.getY();
mIsPressed = true;
killEmitter();
mEmitter = new Emitter();
mEmitter.execute();
return true;
case (MotionEvent.ACTION_MOVE) :
float ny = event.getY();
if(mIsPressed) {
mDiff = ny - mY; //TODO: horizontal scrolling
}
return true;
case (MotionEvent.ACTION_UP) :
case (MotionEvent.ACTION_CANCEL) :
case (MotionEvent.ACTION_OUTSIDE) :
mDiff = mX = mY = 0;
mIsPressed = false;
killEmitter();
return true;
default :
// do nothing
}
return false;
}
private void killEmitter() {
if(mEmitter != null && ! mEmitter.isCancelled()) {
mEmitter.cancel(false);
mEmitter = null;
}
}
private class Emitter extends AsyncTask<Void, Direction, Void> {
private int mTick = 0;
private int mInterval = 100;
private int mThreshold = 10;
private int mStep = 100;
@Override
protected Void doInBackground(Void[] params) { // background thread
while(! isCancelled()) {
float distance = Math.abs(mDiff);
int cycle = getCycle(distance);
//Log.d("lalala", String.valueOf(distance) + " - " + cycle);
if(distance >= mThreshold && mTick % cycle == 0) {
publishProgress(getDirection(mDiff));
}
++mTick;
try {
Thread.sleep(mInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
private Direction getDirection(float diff) {
return (diff >= 0) ? Direction.Down : Direction.Up;
}
private int getCycle(float distance) {
int level = (int)(distance / mStep ); //TODO: consider screen density
if(level > 4) level = 4; // 0 ~ 499 -> 0 ~ 4, >= 500 -> 4
return (4-level+1); // 0 ~ 4 -> 5 ~ 1
}
@Override
protected void onProgressUpdate(Direction... values) { // UI thread
super.onProgressUpdate(values);
switch(values[0]) {
case Down:
mListener.onScrollDown();
break;
case Up:
mListener.onScrollUp();
break;
default:
;
}
}
}
private enum Direction { Up, Down };
public interface Listener {
void onScrollUp();
void onScrollDown();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment