android手势
A. android手机有哪些手势操作,能具体点吗
android手机有哪些手势操作:
“点击”,也叫“单击”,即轻触屏幕一下。无论是搭载何种操作系统的触控手机,这个都是出现频率最高的动作。点击主要用来打开程序,还有功能表(抽屉)。
“点住”,也叫“长按”、“按住”,按住屏幕超过两秒。此动作通常用来调出“菜单”。某些应用程序在界面空白处长按可以调出菜单;某些条目长按也可以弹出菜单,比如当您需要转发短信时,在短信对话界面长按短信内容,必然会弹出菜单,菜单中通常会有“转发”选项。
在进行文字编辑时,点住文字部分,然后调出光标进行精准定位。
当然,此动作也可用于多选、快捷视图,比如在“图库(相册)”中,默认视图下,长按相册文件夹、可对文件夹进行多选操作;打开相册文件夹后,长按照片,同样可对照片进行多选操作,选择完毕后可进行批量操作(发送、删除)。
“拖动”,准确来说应该叫做“按住并拖动”。“拖动”主屏幕编辑时的常见动作,比如对桌面“小组件”或者“图标”进行位置编辑时。另外也用于进度定位,比如播放音乐或者视频时,需要常常拖动进度条。
“双击”就是短时间内连续双击屏幕两次,主要用于快速缩放,比如浏览图片时双击可以快速放大,再次双击可以复位;浏览网页时,对文章正文部分双击可使文字自适应屏幕,当然某些视频播放器双击可切换至全屏模式。
滑动,也算是一个常见操作。主要用于查看屏幕无法完全显示的页面,功能类似鼠标的滚轮。此操作主要用于查看图片、网页、纯文本(短信、邮件、笔记)。
某些视频播放器还定义了特殊功能,比如亮度调节、快进快退,比如“MX Player”、“VPlayer”。
“缩放”动作,是查看图片、网页时最常见的操作,照相时也可使用缩放手势来进行调焦。在MX Player中,甚至可以将视频画面进行缩放。
B. Android的双指手势是怎么实现的
android对多点触摸的支持
使用MotionEvent对象方式处理,比如开始触控时会触发ACTION_DOWN而移动操作时为 ACTION_MOVE最终放开手指时触发ACTION_UP事件。当然还有用户无规则的操作可能触发ACTION_CANCEL这个动作。
对于onTouchEvent方法的参数MotionEvent我们可以详细处理来实现对多点触控的了解,
C. Android的手势GestureDetector, onFling之前肯定有onscroll吗
Fling之前必然有scroll,因为Fling就是scroll达到一定速度的后续结果。
你在onScroll时,是无法判定之后会不会有fling,这个判定只能在ACTION_UP之后,通过计算手势的速度来决定。
你可能说,我可以中间根据scroll的速度来判断,可是呢,ta可能很快的滚过,但是马上慢下来,再慢慢抬起。所以在最后抬起之前判断,是做不到完全准确的。
D. 如何通过手势实现android view 的 缩放 平移
代码主要分两部分,一个activity一个view,代码如下:
java">packagecom.example.touch;
importandroid.app.Activity;
importandroid.os.Bundle;
{
/**.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
TouchImageViewimg=newTouchImageView(this);
setContentView(img);
}
}
packagecom.example.touch;
importandroid.graphics.Bitmap;
importandroid.graphics.Bitmap.Config;
importandroid.graphics.BitmapFactory;
importandroid.graphics.Canvas;
importandroid.graphics.Matrix;
importandroid.graphics.PointF;
importandroid.util.DisplayMetrics;
importandroid.util.FloatMath;
importandroid.view.MotionEvent;
importandroid.widget.ImageView;
{
floatx_down=0;
floaty_down=0;
PointFstart=newPointF();
PointFmid=newPointF();
floatoldDist=1f;
floatoldRotation=0;
Matrixmatrix=newMatrix();
Matrixmatrix1=newMatrix();
MatrixsavedMatrix=newMatrix();
privatestaticfinalintNONE=0;
privatestaticfinalintDRAG=1;
privatestaticfinalintZOOM=2;
intmode=NONE;
booleanmatrixCheck=false;
intwidthScreen;
intheightScreen;
Bitmapgintama;
publicTouchImageView(){
super(activity);
gintama=BitmapFactory.decodeResource(getResources(),R.drawable.gintama);
DisplayMetricsdm=newDisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
widthScreen=dm.widthPixels;
heightScreen=dm.heightPixels;
matrix=newMatrix();
}
protectedvoidonDraw(Canvascanvas){
canvas.save();
canvas.drawBitmap(gintama,matrix,null);
canvas.restore();
}
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getAction()&MotionEvent.ACTION_MASK){
caseMotionEvent.ACTION_DOWN:
mode=DRAG;
x_down=event.getX();
y_down=event.getY();
savedMatrix.set(matrix);
break;
caseMotionEvent.ACTION_POINTER_DOWN:
mode=ZOOM;
oldDist=spacing(event);
oldRotation=rotation(event);
savedMatrix.set(matrix);
midPoint(mid,event);
break;
caseMotionEvent.ACTION_MOVE:
if(mode==ZOOM){
matrix1.set(savedMatrix);
floatrotation=rotation(event)-oldRotation;
floatnewDist=spacing(event);
floatscale=newDist/oldDist;
matrix1.postScale(scale,scale,mid.x,mid.y);//缩放
matrix1.postRotate(rotation,mid.x,mid.y);//旋转
matrixCheck=matrixCheck();
if(matrixCheck==false){
matrix.set(matrix1);
invalidate();
}
}elseif(mode==DRAG){
matrix1.set(savedMatrix);
matrix1.postTranslate(event.getX()-x_down,event.getY()
-y_down);//平移
matrixCheck=matrixCheck();
matrixCheck=matrixCheck();
if(matrixCheck==false){
matrix.set(matrix1);
invalidate();
}
}
break;
caseMotionEvent.ACTION_UP:
caseMotionEvent.ACTION_POINTER_UP:
mode=NONE;
break;
}
returntrue;
}
privatebooleanmatrixCheck(){
float[]f=newfloat[9];
matrix1.getValues(f);
//图片4个顶点的坐标
floatx1=f[0]*0+f[1]*0+f[2];
floaty1=f[3]*0+f[4]*0+f[5];
floatx2=f[0]*gintama.getWidth()+f[1]*0+f[2];
floaty2=f[3]*gintama.getWidth()+f[4]*0+f[5];
floatx3=f[0]*0+f[1]*gintama.getHeight()+f[2];
floaty3=f[3]*0+f[4]*gintama.getHeight()+f[5];
floatx4=f[0]*gintama.getWidth()+f[1]*gintama.getHeight()+f[2];
floaty4=f[3]*gintama.getWidth()+f[4]*gintama.getHeight()+f[5];
//图片现宽度
doublewidth=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
//缩放比率判断
if(width<widthScreen/3||width>widthScreen*3){
returntrue;
}
//出界判断
if((x1<widthScreen/3&&x2<widthScreen/3
&&x3<widthScreen/3&&x4<widthScreen/3)
||(x1>widthScreen*2/3&&x2>widthScreen*2/3
&&x3>widthScreen*2/3&&x4>widthScreen*2/3)
||(y1<heightScreen/3&&y2<heightScreen/3
&&y3<heightScreen/3&&y4<heightScreen/3)
||(y1>heightScreen*2/3&&y2>heightScreen*2/3
&&y3>heightScreen*2/3&&y4>heightScreen*2/3)){
returntrue;
}
returnfalse;
}
//触碰两点间距离
privatefloatspacing(MotionEventevent){
floatx=event.getX(0)-event.getX(1);
floaty=event.getY(0)-event.getY(1);
returnFloatMath.sqrt(x*x+y*y);
}
//取手势中心点
privatevoidmidPoint(PointFpoint,MotionEventevent){
floatx=event.getX(0)+event.getX(1);
floaty=event.getY(0)+event.getY(1);
point.set(x/2,y/2);
}
//取旋转角度
privatefloatrotation(MotionEventevent){
doubledelta_x=(event.getX(0)-event.getX(1));
doubledelta_y=(event.getY(0)-event.getY(1));
doubleradians=Math.atan2(delta_y,delta_x);
return(float)Math.toDegrees(radians);
}
//将移动,缩放以及旋转后的图层保存为新图片
//本例中没有用到该方法,需要保存图片的可以参考
publicBitmapCreatNewPhoto(){
Bitmapbitmap=Bitmap.createBitmap(widthScreen,heightScreen,
Config.ARGB_8888);//背景图片
Canvascanvas=newCanvas(bitmap);//新建画布
canvas.drawBitmap(gintama,matrix,null);//画图片
canvas.save(Canvas.ALL_SAVE_FLAG);//保存画布
canvas.restore();
returnbitmap;
}
}
E. android 双指手势问题
判断pointer1和pointer2的down,同时为down时在move事件中去做距离的计算(起始距离至少为60),记录两点的起始位置和结束位置。当两点起始距离达到要求的时候执行跳转。
如果你要做角度。(只允许这一种情况下)左边的起始X肯定大于结束X,起始Y肯定大于结束Y;右边的起始X肯定小于结束X,起始Y肯定大于结束Y。
F. 怎样在安卓软件中添加手势
1.Android QuickDo(手势快速操作,模拟实体键)模拟实体键(返回 home 音量加 音量减 锁屏 搜索键 menu键)需root。
2.魔幻手势
G. android 手势判断是横向滑动还是纵向 csdn
对于Android中的手势识别可以从以下三个Listener入手——OnTouchListener、OnGestureListener、OnDoubleTapListener。这三个监听器分别是触摸监听、手势滑动监听和屏幕双击操作监听。很多的时候我们需要这些手势识别的操作,例如我们自定义控件的时候就经常会用到。下面就对这三个监听器分别进行介绍。
触摸监听器OnTouchListener
让我们的Activity去现实此接口,并重写onTouch方法。重写OnTouchListener的onTouch方法 此方法在触摸屏被触摸,即发生触摸事件(接触和抚摸两个事件)的时候被调用。示范代码如下:
@Override
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
Toast.makeText(this, "onTouch", TIME_OUT).show();
return true;
}
手势滑动监听器OnGestureListener
让我们的Activity去现实此接口,并重写onFling、onLongPress、onScroll、onDown、onShowPress、onSingleTapUp方法。示范代码如下:
/**
* 手势滑动时别调用
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE) {
Toast.makeText(this, "向左滑动", TIME_OUT).show();
} else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE) {
Toast.makeText(this, "向右滑动", TIME_OUT).show();
}
return false;
}
/**
* 长按时被调用
*/
@Override
public void onLongPress(MotionEvent e) {
Toast.makeText(this, "触发长按回调", TIME_OUT).show();
}
/**
* 滚动时调用
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
Toast.makeText(this, "触发滚动回调", TIME_OUT).show();
return false;
}
/**
* 在按下动作时被调用
*/
@Override
public boolean onDown(MotionEvent e) {
Toast.makeText(this, "按下回调", TIME_OUT).show();
return false;
}
/**
* 按住时被调用
*/
@Override
public void onShowPress(MotionEvent e) {
Toast.makeText(this, "按住不松回调", TIME_OUT).show();
}
/**
* 抬起时被调用
*/
@Override
public boolean onSingleTapUp(MotionEvent e) {
Toast.makeText(this, "触发抬起回调", TIME_OUT).show();
return false;
}
双击屏幕监听器OnDoubleTapListener
让我们的Activity去现实此接口,并重写onDoubleTap、onDoubleTapEvent、onSingleTapConfirmed方法。示范代码如下:
@Override
public boolean onDoubleTap(MotionEvent arg0) {
Toast.makeText(this, "触发双击回调", TIME_OUT).show();
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent arg0) {
Toast.makeText(this, "触发双击的按下跟抬起回调", TIME_OUT).show();
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent arg0) {
Toast.makeText(this, "触发单击确认回调", TIME_OUT).show();
return false;
}
H. android怎样可以控制手势滑动的
我们先来明确一些概念,首先,Android的事件处理机制是基于Listener(监听器)来实现的,比我们今天所说的触摸屏相关的事件,就是通 过onTouchListener。其次,所有View的子类都可以通过setOnTouchListener()、 setOnKeyListener()等方法来添加对某一类事件的监听器。第三,Listener一般会以Interface(接口)的方式来提供,其中 包含一个或多个abstract(抽象)方法,我们需要实现这些方法来完成onTouch()、onKey()等等的操作。这样,当我们给某个view设 置了事件Listener,并实现了其中的抽象方法以后,程序便可以在特定的事件被dispatch到该view的时候,通过callbakc函数给予适 当的响应。
看一个简单的例子,就用最简单的TextView来说明(事实上和ADT中生成的skeleton没有什么区别)。
Java代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// init TextView
TextView tv = (TextView) findViewById(R.id.page);
// set OnTouchListener on TextView
tv.setOnTouchListener(this);
// show some text
tv.setText(R.string.text);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();
return false;
}
我们给TextView的实例tv设定了一个onTouchListener,因为GestureTest类实现了OnTouchListener 接口,所以简单的给一个this作为参数即可。onTouch方法则是实现了OnTouchListener中的抽象方法,我们只要在这里添加逻辑代码即 可在用户触摸屏幕时做出响应,就像我们这里所做的——打出一个提示信息。
这里,我们可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN, ACTION_MOVE, ACTION_UP, 和ACTION_CANCEL。ACTION_DOWN是指按下触摸屏,ACTION_MOVE是指按下触摸屏后移动受力点,ACTION_UP则是指松 开触摸屏,ACTION_CANCEL不会由用户直接触发(所以不在今天的讨论范围,请参考ViewGroup.onInterceptTouchEvent(MotionEvent))。借助对于用户不同操作的判断,结合getRawX()、getRawY()、getX()和getY()等方法来获取坐标后,我们可以实现诸如拖动某一个按钮,拖动滚动条等功能。待机可以看看MotionEvent类的文档,另外也可以看考TouchPaint例子。
回到今天所要说的重点,当我们捕捉到Touch操作的时候,如何识别出用户的Gesture?这里我们需要GestureDetector.OnGestureListener接口的帮助,于是我们的GestureTest类就变成了这个样子。
Java代码
public class GestureTest extends Activity implements OnTouchListener,
OnGestureListener {
....
}
随后,在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给 GestureDetector 来分析是否有合适的callback函数来处理用户的手势。
Java代码
@Override
public boolean onTouch(View v, MotionEvent event) {
// OnGestureListener will analyzes the given motion event
return mGestureDetector.onTouchEvent(event);
}
接下来,我们实现了以下6个抽象方法,其中最有用的当然是onFling()、onScroll()和onLongPress()了。我已经把每一个方法代表的手势的意思写在了注释里,大家看一下就明白了。
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发Java代码
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
return false;
}
// 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
// 注意和onDown()的区别,强调的是没有松开或者拖动的状态
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}
// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// TODO Auto-generated method stub
return false;
}
我们来试着做一个onFling()事件的处理吧,onFling()方法中每一个参数的意义我写在注释中了,需要注意的是Fling事件的处理代 码中,除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,我们还可以根据用户在X轴或者Y轴上的 移动速度作为条件。比如下面的代码中我们就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// 参数解释:
// e1:第1个ACTION_DOWN MotionEvent
// e2:最后一个ACTION_MOVE MotionEvent
// velocityX:X轴上的移动速度,像素/秒
// velocityY:Y轴上的移动速度,像素/秒
// 触发条件 :
// X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling left
Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();
} else
if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
// Fling right
Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
}
return false;
}
问题是,这个时候如果我们尝试去运行程序,你会发现我们根本得不到想要的结果,跟踪代码的执行的会发现onFling()事件一直就没有被捕捉到。这正是一开始困扰我的问题,这到底是为什么呢?
我在讨论组的Gesture detection这个帖子里找到了答案,即我们需要在onCreate中tv.setOnTouchListener(this);之后添加如下一句代码。
tv.setLongClickable(true);
只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。
这次遇到的这个问题和上次MapView中setOnKeyListener遇到的问题挺类似,其实都是对SDK的了解不够全面,遇到了一次记住了就好。不过话说回来,Google在文档方面确实需要加强了,起码可以在OnGestureListener中说明需要满足那些条件才可以保证手势被正确识别。