使用 OnSwipeTouchListener 制作字母 L
Making the letter L with OnSwipeTouchListener
我在网上找到了一个很好的监听器 class 来制作一个 OnSwipeTouchListener。该侦听器可以确定用户何时向下、向上、向左或向右滑动:
public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
protected OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}
}
我是这样使用它的:
findViewById(R.id.framelayout).setOnTouchListener(new OnSwipeTouchListener(this) {
@Override
public void onSwipeDown() {
Toast.makeText(MainActivity.this, "Down", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeLeft() {
Toast.makeText(MainActivity.this, "Left", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeUp() {
Toast.makeText(MainActivity.this, "Up", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeRight() {
Toast.makeText(MainActivity.this, "Right", Toast.LENGTH_SHORT).show();
}
});
现在,我想添加函数onSwipeL()。这个函数是当用户用手指做出字母L时,就像onSwipeDown() + onSwipeRight()。
最好的方法是制作函数 onSwipeDoubleL()。这是用户用手指倒转双 L 的时候。就像同时制作 :
- onSwipeDown() + onSwipeRight()
- onSwipeDown() + onSwipeLeft()
这可能吗?
有两种选择。
- 首先 - 使用一些布尔值。 isSwipedRight(例如)。如果
isSwipedDown
为真,请检查 onSwipeRight()
,如果是,则执行操作。在 onSwipeDown()
中将布尔值设置为 true,在所有其他(不包括向下)中设置为 false。
- 创建你自己的onTouchListener 并自己测量距离。
我真的不明白你为什么需要这个手势。但这是我的解决方案。我们应该捕捉触摸事件,所以重写 onTouchEvent 方法。现在我们需要读取屏幕上的手指索引。
如果我们得到不止一次触摸,请为 X 坐标大于 "left finger" 的手指应用右食指。我不能说我是否找到了正确的索引。所以我检查索引坐标。
下一步我们保存起点并开始向下移动。如果我们在屏幕上有 2 个手指,请检查右手和左手手指,否则只有左手(或您希望的右手)。
如果我们在 "down" 距离大于最小值时捕获事件并开始移动到 left/right,我们需要保存新的起点以计算距离。
并等待用户移动到距离超过分钟的 left/right。最后用 "left" 和 "right" 手指检查是否成功或刚好离开(一触)。
我们还需要考虑移动时的不准确性(错误,错误)。用户不能向下或向左移动完全正确,因此解决方案高度依赖于此参数。您必须平衡范围和精度参数以舒适的手势控制。
代码未优化,仅展示基本思路。也许你会发现更多的小解决方案。对不起我的英语水平
public class MainMenuActivity extends AppCompatActivity {
boolean movingDownL = false;
boolean movingDownR = false;
boolean movingLeft = false;
boolean movingRight = false;
boolean movingSuccessL = false;
boolean movingSuccessR = false;
// Deviation in pixels from the route (error value)
int downInaccuracy = 30; // Down
int lnrInaccuracy = 10; // Left and Right
// Minimum distance to apply move (300 px in down and 100 to the left/right)
int downMinDistance = 300;
int lnrMinDistance = 50;
Point oldCoordsL = new Point(0, 0); // Old coordinates left
Point oldCoordsR = new Point(0, 0); // Old coordinates right
Point startPointL = new Point(0, 0);
Point startPointR = new Point(0, 0);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int pIndexL = event.findPointerIndex(event.getPointerId(0));
int pIndexR = 0;
// If we have more than 1 touch read second finger index
if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1));
// Check if we do not mistake when read fingers id
if(event.getPointerCount() > 1 && event.getX(pIndexL) > event.getX(pIndexR)) {
int tmp = pIndexR;
pIndexR = pIndexL;
pIndexL = tmp;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
movingDownL = true; // Start moving fingers
movingDownR = true;
movingSuccessL = false;
movingSuccessR = false;
// Get start point left and right if we need
if(event.getPointerCount() > 1) {
startPointR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
oldCoordsR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
}
startPointL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
oldCoordsL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
break;
case MotionEvent.ACTION_MOVE:
// Add right finger handler
if(event.getPointerCount() > 1) {
if(!movingDownR) {
// Check if we still moving to down
if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy &&
oldCoordsR.y < event.getY(pIndexR)) break;
// Start moving to the right
if(Math.abs(oldCoordsR.y - event.getY(pIndexR)) < lnrInaccuracy &&
oldCoordsR.x > event.getX(pIndexR) && !movingRight) {
movingRight = true;
startPointR = new Point(new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR)));
}
}else {
if (Math.abs(oldCoordsR.x - event.getX(pIndexR)) > downInaccuracy ||
oldCoordsR.y < event.getY(pIndexR)) {
movingDownR = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= downMinDistance){
// Start moving to the left/right
movingDownR = false;
}
}
}
// Left finger handler by default even if we got only one touch
// Check if we need move to any side
if(!movingDownL) {
// Check if we still moving to down
if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy &&
oldCoordsL.y < event.getY(pIndexL)) break;
// Start moving to the left
if(Math.abs(oldCoordsL.y - event.getY(pIndexL)) < lnrInaccuracy &&
oldCoordsL.x < event.getX(pIndexL) && !movingLeft) {
movingLeft = true;
startPointL = new Point(new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL)));
}
}else {
if (Math.abs(oldCoordsL.x - event.getX(pIndexL)) > downInaccuracy ||
oldCoordsL.y > event.getY(pIndexL)) {
movingDownL = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= downMinDistance){
// Start moving to the left/right
movingDownL = false;
}
}
// Left move handler
if(movingLeft) {
if (Math.abs(oldCoordsL.y - event.getY(pIndexL)) > lnrInaccuracy ||
oldCoordsL.x > event.getX(pIndexL)) {
movingLeft = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= lnrMinDistance) {
movingLeft = false;
movingSuccessL = true; // L from left finger is OK
}
}
// Right move handler
if(movingRight) {
if (Math.abs(oldCoordsR.y - event.getY(pIndexR)) > lnrInaccuracy ||
oldCoordsR.x < event.getX(pIndexR)) {
movingRight = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= lnrMinDistance) {
movingRight = false;
movingSuccessR = true; // L from right finger is OK
}
}
if(movingSuccessL && movingSuccessR) {
Toast.makeText(this, "Yeah, it's look like double L", Toast.LENGTH_SHORT).show();
} else if(movingSuccessL) Toast.makeText(this, "Yeah, it's look like L", Toast.LENGTH_SHORT).show();
oldCoordsL = new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL));
oldCoordsR = new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR));
break;
case MotionEvent.ACTION_UP:
movingDownL = false;
movingDownR = false;
movingLeft = false;
movingRight = false;
break;
default:
return false;
}
return true;
}
private double findDistance(Point p1, Point p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
}
我在网上找到了一个很好的监听器 class 来制作一个 OnSwipeTouchListener。该侦听器可以确定用户何时向下、向上、向左或向右滑动:
public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
protected OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}
}
我是这样使用它的:
findViewById(R.id.framelayout).setOnTouchListener(new OnSwipeTouchListener(this) {
@Override
public void onSwipeDown() {
Toast.makeText(MainActivity.this, "Down", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeLeft() {
Toast.makeText(MainActivity.this, "Left", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeUp() {
Toast.makeText(MainActivity.this, "Up", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeRight() {
Toast.makeText(MainActivity.this, "Right", Toast.LENGTH_SHORT).show();
}
});
现在,我想添加函数onSwipeL()。这个函数是当用户用手指做出字母L时,就像onSwipeDown() + onSwipeRight()。
最好的方法是制作函数 onSwipeDoubleL()。这是用户用手指倒转双 L 的时候。就像同时制作 :
- onSwipeDown() + onSwipeRight()
- onSwipeDown() + onSwipeLeft()
这可能吗?
有两种选择。
- 首先 - 使用一些布尔值。 isSwipedRight(例如)。如果
isSwipedDown
为真,请检查onSwipeRight()
,如果是,则执行操作。在onSwipeDown()
中将布尔值设置为 true,在所有其他(不包括向下)中设置为 false。 - 创建你自己的onTouchListener 并自己测量距离。
我真的不明白你为什么需要这个手势。但这是我的解决方案。我们应该捕捉触摸事件,所以重写 onTouchEvent 方法。现在我们需要读取屏幕上的手指索引。
如果我们得到不止一次触摸,请为 X 坐标大于 "left finger" 的手指应用右食指。我不能说我是否找到了正确的索引。所以我检查索引坐标。
下一步我们保存起点并开始向下移动。如果我们在屏幕上有 2 个手指,请检查右手和左手手指,否则只有左手(或您希望的右手)。
如果我们在 "down" 距离大于最小值时捕获事件并开始移动到 left/right,我们需要保存新的起点以计算距离。
并等待用户移动到距离超过分钟的 left/right。最后用 "left" 和 "right" 手指检查是否成功或刚好离开(一触)。
我们还需要考虑移动时的不准确性(错误,错误)。用户不能向下或向左移动完全正确,因此解决方案高度依赖于此参数。您必须平衡范围和精度参数以舒适的手势控制。
代码未优化,仅展示基本思路。也许你会发现更多的小解决方案。对不起我的英语水平
public class MainMenuActivity extends AppCompatActivity {
boolean movingDownL = false;
boolean movingDownR = false;
boolean movingLeft = false;
boolean movingRight = false;
boolean movingSuccessL = false;
boolean movingSuccessR = false;
// Deviation in pixels from the route (error value)
int downInaccuracy = 30; // Down
int lnrInaccuracy = 10; // Left and Right
// Minimum distance to apply move (300 px in down and 100 to the left/right)
int downMinDistance = 300;
int lnrMinDistance = 50;
Point oldCoordsL = new Point(0, 0); // Old coordinates left
Point oldCoordsR = new Point(0, 0); // Old coordinates right
Point startPointL = new Point(0, 0);
Point startPointR = new Point(0, 0);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int pIndexL = event.findPointerIndex(event.getPointerId(0));
int pIndexR = 0;
// If we have more than 1 touch read second finger index
if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1));
// Check if we do not mistake when read fingers id
if(event.getPointerCount() > 1 && event.getX(pIndexL) > event.getX(pIndexR)) {
int tmp = pIndexR;
pIndexR = pIndexL;
pIndexL = tmp;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
movingDownL = true; // Start moving fingers
movingDownR = true;
movingSuccessL = false;
movingSuccessR = false;
// Get start point left and right if we need
if(event.getPointerCount() > 1) {
startPointR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
oldCoordsR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
}
startPointL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
oldCoordsL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
break;
case MotionEvent.ACTION_MOVE:
// Add right finger handler
if(event.getPointerCount() > 1) {
if(!movingDownR) {
// Check if we still moving to down
if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy &&
oldCoordsR.y < event.getY(pIndexR)) break;
// Start moving to the right
if(Math.abs(oldCoordsR.y - event.getY(pIndexR)) < lnrInaccuracy &&
oldCoordsR.x > event.getX(pIndexR) && !movingRight) {
movingRight = true;
startPointR = new Point(new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR)));
}
}else {
if (Math.abs(oldCoordsR.x - event.getX(pIndexR)) > downInaccuracy ||
oldCoordsR.y < event.getY(pIndexR)) {
movingDownR = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= downMinDistance){
// Start moving to the left/right
movingDownR = false;
}
}
}
// Left finger handler by default even if we got only one touch
// Check if we need move to any side
if(!movingDownL) {
// Check if we still moving to down
if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy &&
oldCoordsL.y < event.getY(pIndexL)) break;
// Start moving to the left
if(Math.abs(oldCoordsL.y - event.getY(pIndexL)) < lnrInaccuracy &&
oldCoordsL.x < event.getX(pIndexL) && !movingLeft) {
movingLeft = true;
startPointL = new Point(new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL)));
}
}else {
if (Math.abs(oldCoordsL.x - event.getX(pIndexL)) > downInaccuracy ||
oldCoordsL.y > event.getY(pIndexL)) {
movingDownL = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= downMinDistance){
// Start moving to the left/right
movingDownL = false;
}
}
// Left move handler
if(movingLeft) {
if (Math.abs(oldCoordsL.y - event.getY(pIndexL)) > lnrInaccuracy ||
oldCoordsL.x > event.getX(pIndexL)) {
movingLeft = false;
break;
} else if(findDistance(startPointL,
new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= lnrMinDistance) {
movingLeft = false;
movingSuccessL = true; // L from left finger is OK
}
}
// Right move handler
if(movingRight) {
if (Math.abs(oldCoordsR.y - event.getY(pIndexR)) > lnrInaccuracy ||
oldCoordsR.x < event.getX(pIndexR)) {
movingRight = false;
break;
} else if(findDistance(startPointR,
new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= lnrMinDistance) {
movingRight = false;
movingSuccessR = true; // L from right finger is OK
}
}
if(movingSuccessL && movingSuccessR) {
Toast.makeText(this, "Yeah, it's look like double L", Toast.LENGTH_SHORT).show();
} else if(movingSuccessL) Toast.makeText(this, "Yeah, it's look like L", Toast.LENGTH_SHORT).show();
oldCoordsL = new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL));
oldCoordsR = new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR));
break;
case MotionEvent.ACTION_UP:
movingDownL = false;
movingDownR = false;
movingLeft = false;
movingRight = false;
break;
default:
return false;
}
return true;
}
private double findDistance(Point p1, Point p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
}