Android事件处理(内含手势)

基于回调机制的事件处理

onKeyDown()方法:当手机上的物理按键被按下时会回调此方法

onKeyUp()方法:当手机上的按下物理按键抬起时会回调此方法

onTouchEvent()方法:触摸屏幕回调方法

onFocusChanged()方法:View控件焦点改变时回调此方法(书p208)

演示

/*
 物理按键被按下
 @param keyCode 被按下的物理按键ID
 @param event 按键事件的对象,包含事件的详细信息
 @return 返回为true表示已经完整的处理事件,并不希望其他的回调方法进行处理。
 返回为false表示并没有完全处理事件,更希望其他回调方法再次进行处理。
 */
private boolean flag = true;
 
 @Override
 public boolean onKeyDown(int keyCode, KeyEvent event) {
    
    
   Toast.makeText(this, "物理按键被按下", Toast.LENGTH_SHORT).show();
   if (keyCode == KeyEvent.KEYCODE_BACK) {
    
    
     Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
     if (flag) {
    
    
       flag = false;
       return true;//屏蔽后退按键
     }
   }
   return super.onKeyDown(keyCode, event);
 }
 
 @Override
 public boolean onKeyUp(int keyCode, KeyEvent event) {
    
    
   Toast.makeText(this, "物理按键被抬起", Toast.LENGTH_SHORT).show();
   return super.onKeyUp(keyCode, event);
 }
 
/*
 触摸事件
 
 @param event
 @return
 */
 @Override
 public boolean onTouchEvent(MotionEvent event) {
    
    
   flag = true;
   switch (event.getAction()) {
    
    
     case MotionEvent.ACTION_DOWN:
       Toast.makeText(this, "按下", Toast.LENGTH_SHORT).show();
       break;
     case MotionEvent.ACTION_UP:
       Toast.makeText(this, "抬起", Toast.LENGTH_SHORT).show();
       break;
     case MotionEvent.ACTION_MOVE:
       Toast.makeText(this, "滑动", Toast.LENGTH_SHORT).show();
       break;
 
   }
   return super.onTouchEvent(event);
 }

物理按键

常用的物理按键方法

onKeyDown():按下操作

onKeyUp():抬起操作

onKeyLongPress():长按操作

案例连按两次返回键退出应用

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    
    
    if (keyCode == KeyEvent.KEYCODE_BACK) {
    
    
        exit();
        return true;//屏蔽后退按键
    }
    return super.onKeyDown(keyCode, event);
}

private void exit() {
    
    
    if(System.currentTimeMillis()-exitTime>2000){
    
    
        Toast.makeText(this, "再按一次退出程序", Toast.LENGTH_SHORT).show();
        exitTime=System.currentTimeMillis();
    }else {
    
    
        finish();
        System.exit(0);
    }
}

常用的物理按键

音量+:KEYCODE_VOLUME_UP

音量-:KEYCODE_VOLUME_DOWN

电源键:KEYCODE_POWER

菜单键:KEYCODE_MENU

主屏键:KEYCODE_HOME

返回键:KEYCODE_BACK

基于监听的事件处理

长按事件处理

tv.setOnLongClickListener(new View.OnLongClickListener() {
    
    
    @Override
    public boolean onLongClick(View v) {
    
    
        //注册到菜单中
        registerForContextMenu(v);
        //打开菜单框
        openContextMenu(v);
        //要返回true才会弹出,否则只会闪一下
        return true;
    }
});
//菜单项方法
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    
    
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add("收藏");
    menu.add("举报");
}

焦点改变事件处理

iv1 =findViewById(R.id.iv1);
iv2 =findViewById(R.id.iv2);
iv1.setOnFocusChangeListener(this);
iv2.setOnFocusChangeListener(this);
/*
  检测控件是否获得焦点
 
  @param v        表示触发焦点发生改变的事件源
  @param hasFocus 是否获得焦点
 */
@Override
public void onFocusChange(View v, boolean hasFocus) {
    
    
    switch (v.getId()){
    
    
        case R.id.iv1:
            tv.setText("您选择了滑稽");
            break;
        case R.id.iv2:
            tv.setText("您选择了郭韬");
            break;
    }
}

键盘监听事件处理

iv1.setOnKeyListener(this);
iv2.setOnKeyListener(this); 
/*
  键盘监听事件处理
  @param v 表示事件源
  @param keyCode 键盘的键盘码
  @param event 键盘事件封装对象,包含事件详细信息,发生的事件、事件类型等信息
  @return
 */
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
    
    
    switch (keyCode){
    
    
        case KeyEvent.KEYCODE_A: //键盘上的A
            iv1.performClick();//模拟按钮单击
            iv1.requestFocus();//使按钮1获得焦点
            break;
        case KeyEvent.KEYCODE_B: //键盘上的B
            iv2.performClick();//模拟按钮单击
            iv2.requestFocus();//使按钮2获得焦点
            break;
    }
    return false;
}

触摸事件监听

iv1.setOnTouchListener(this);
iv2.setOnTouchListener(this);
/*
  触摸事件
  @param v 被触摸的对象
  @param event 触摸事件封装类
  @return
 */
@Override
public boolean onTouch(View v, MotionEvent event) {
    
    
    switch (v.getId()){
    
    
        case R.id.iv1:
            Toast.makeText(this, "滑稽被摸了", Toast.LENGTH_SHORT).show();
            break;
        case R.id.iv2:
            Toast.makeText(this, "郭韬被摸了", Toast.LENGTH_SHORT).show();
            break;
    }
    return false;
}

案例——触摸改变控件位置

package com.example.touch;

 public class Funny extends View {
    
    
   public float funnyX;
   public float funnyY;
   public Funny(Context context) {
    
    
     super(context);
     funnyX=0;
     funnyY=0;
   }

   @Override
   protected void onDraw(Canvas canvas) {
    
    
     super.onDraw(canvas);
     //画笔
     Paint paint =new Paint();
     //
     Bitmap bitmap= BitmapFactory.decodeResource(this.getResources(),R.drawable.funny);
     //绘制滑稽
     canvas.drawBitmap(bitmap,funnyX,funnyY,paint);
     //如果没有回收强制回收图片
     if(bitmap.isRecycled()){
    
    
       bitmap.recycle();
     }
   }
 }

 

package com.example.touch;

 public class MainActivity extends AppCompatActivity {
    
    

   @Override
   protected void onCreate(Bundle savedInstanceState) {
    
    
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     //创建滑稽对象
     final Funny funny=new Funny(this);
     //添加触摸事件
     funny.setOnTouchListener(new View.OnTouchListener() {
    
    
       @Override
       public boolean onTouch(View v, MotionEvent event) {
    
    
         //触摸的时候根据手指重新定义滑稽坐标
         funny.funnyX=event.getX()-funny.getWidth()/5;
         funny.funnyY=event.getY()-funny.getHeight()/5;
         //重绘制滑稽
         funny.invalidate();
         return true;
       }
     });
     //将滑稽添加到布局管理器中
     RelativeLayout relativeLayout=findViewById(R.id.rl);
     relativeLayout.addView(funny);
   }
 }

触摸

OnGestureListener接口

package com.example.mygesture;
 
 //第一步:实现GestureDetector.OnGestureListener接口实现所有方法
 public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener {
    
    
   Animation[] animations=new Animation[4];
   final int distance=50;
   private int[] images=new int[]{
    
    R.drawable.drink1,R.drawable.drink2,R.drawable.drink3,R.drawable.drink4,R.drawable.drink5,R.drawable.drink6};
   private ViewFlipper flipper;
 //第二步:定义一个全局的手势检测器
   GestureDetector detector;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
    
    
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     detector=new GestureDetector(MainActivity.this,this);
     //第三步:将要显示的图片加载到ViewFlipper中,并且初始化动画数组
     flipper=findViewById(R.id.flipper);
     for(int i=0;i<images.length;i++){
    
    
       ImageView imageView=new ImageView(MainActivity.this);
       imageView.setImageResource(images[i]);
       flipper.addView(imageView);
     }
     animations[0]= AnimationUtils.loadAnimation(this,R.anim.slide_in_left);//左进
     animations[1]= AnimationUtils.loadAnimation(this,R.anim.slide_out_left);//左出
     animations[2]= AnimationUtils.loadAnimation(this,R.anim.slide_in_right);//右进
     animations[3]= AnimationUtils.loadAnimation(this,R.anim.slide_out_right);//右出
   }
   //触摸事件按下时触发
   @Override
   public boolean onDown(MotionEvent e) {
    
    
     return false;
   }
   //用户按下未移动
   @Override
   public void onShowPress(MotionEvent e) {
    
    
 
   }
   //用户轻击时触发
   @Override
   public boolean onSingleTapUp(MotionEvent e) {
    
    
     return false;
   }
   //移动时触发?
   @Override
   public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    
    
     return false;
   }
   //用户长按时触发
   @Override
   public void onLongPress(MotionEvent e) {
    
    
 
   }
 
   //用户拖动时触发
   @Override
   public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    
    
     //第四步:在onFling()方法中通过触摸事件的X坐标判断是向左滑动还是向右滑动
     if(e1.getX()-e2.getX()>distance){
    
    
       //从右向左滑动
       flipper.setInAnimation(animations[2]);//右进
       flipper.setOutAnimation(animations[1]);//左出
       //显示前一张图片
       flipper.showPrevious();
       return true;
     }else if(e2.getX()-e1.getX()>distance){
    
    
       //从左向右滑动
       flipper.setInAnimation(animations[0]);//左进
       flipper.setOutAnimation(animations[3]);//右出
       //显示下一张图片
       flipper.showNext();
       return true;
     }
     return false;
   }
   //第五步:将Activity上的触摸事件交给GestureDetector处理
   @Override
   public boolean onTouchEvent(MotionEvent event) {
    
    
 //    return super.onTouchEvent(event);
     return detector.onTouchEvent(event);
   }
 }

OnDoubleTapListener接口

需要配合GestureDetector.OnGestureListener使用



 //当用户单击屏幕时会触发此方法
 @Override
 public boolean onSingleTapConfirmed(MotionEvent e) {
    
    
   Toast.makeText(this, "单击", Toast.LENGTH_SHORT).show();
   return false;
 }
 //当用户双击屏幕时会触发此方法
 @Override
 public boolean onDoubleTap(MotionEvent e) {
    
    
   Toast.makeText(this, "双击", Toast.LENGTH_SHORT).show();
   return false;
 }
 //双击以后的输入事件都会会触发此方法
 @Override
 public boolean onDoubleTapEvent(MotionEvent e) {
    
    
   Toast.makeText(this, "双击后触发的方法", Toast.LENGTH_SHORT).show();
   return false;
 }

手势的创建

1.交互界面代码

<?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <TextView
     android:id="@+id/tv"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textSize="25sp"
     android:text="请在屏幕下方绘制手势"/>
   <android.gesture.GestureOverlayView
     android:id="@+id/gesture"
     android:layout_width="match_parent"
     android:layout_height="match_parent"

//设置为多笔绘制
     android:gestureStrokeType="multiple"/>
 </RelativeLayout>

2.对话框界面代码

<?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent">
   <TextView
     android:id="@+id/tv_add"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_margin="8dp"
     android:text="请输入手势名称"
     android:textSize="18dp"/>
   <EditText
     android:id="@+id/gesture_name"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_toRightOf="@id/tv_add"/>
   <ImageView
     android:id="@+id/show"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_below="@id/gesture_name"
     android:layout_centerHorizontal="true"/>
 </RelativeLayout>

3.java控制代码

package com.example.mygesture;
 
 public class MainActivity2 extends AppCompatActivity {
    
    
   private EditText gestureName;
   private GestureOverlayView gestureView;
   private Gesture mGesture;
 
   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_2);
     initView();
   }
 
 
   private void initView() {
    
    
     //获取手势编辑视图
     gestureView = (GestureOverlayView) findViewById(R.id.gesture);
     gestureView.setGestureColor(Color.BLUE);//设置手势绘制颜色
     gestureView.setGestureStrokeWidth(10);//设置手势绘制的宽度
     //为手势完成事件绑定事件监听器,手势完成后,触发该事件
     gestureView.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
    
    
       @Override
       public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    
    
         mGesture=gesture;
         //加载save_gesture.xml界面布局视图
         View dialog=getLayoutInflater().inflate(R.layout.save_gesture,null);
         ImageView imageView=dialog.findViewById(R.id.show);
         gestureName=dialog.findViewById(R.id.gesture_name);
 
         //根据Gesture包含的手势创建一个位图
         Bitmap bitmap=gesture.toBitmap(128,128,10,0xff0000ff);
         imageView.setImageBitmap(bitmap);
 
         //使用对话框显示dialog组件
         new AlertDialog.Builder(MainActivity2.this)
             .setView(dialog)
             .setPositiveButton("保存", new DialogInterface.OnClickListener() {
    
    
               @Override
               public void onClick(DialogInterface dialog, int which) {
    
    
                 ActivityCompat.requestPermissions(MainActivity2.this,new String[]{
    
    Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
               }
             })
             .setNegativeButton("取消",null).show();
       }
     });
   }
   public void saveFile(){
    
    
     if(mGesture!=null){
    
    
       //获取指定文件对应手势库
       GestureLibrary lib= GestureLibraries.fromFile("/sdcard/mygestures");
       lib.addGesture(gestureName.getText().toString(),mGesture);
       boolean result=lib.save();//保存手势库
       if(result) Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
       else Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show();
     }
   }
 
   @Override
   public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    
    
     super.onRequestPermissionsResult(requestCode, permissions, grantResults);
     if(requestCode==1){
    
    
       for(int i=0;i<permissions.length;i++){
    
    
         if(grantResults[i]== PackageManager.PERMISSION_GRANTED){
    
    
           saveFile();
         }else{
    
    
           Toast.makeText(this, "权限"+permissions[i]+"申请失败,不能保存手势库文件", Toast.LENGTH_SHORT).show();
         }
       }
     }
   }
 }

手势识别

0.创建raw文件夹将手势库文件放进去

1.布局文件

<?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
 
   <EditText
     android:id="@+id/editText"
     android:layout_width="200dp"
     android:layout_height="wrap_content"
     android:layout_centerHorizontal="true"
     />
   <android.gesture.GestureOverlayView
     android:id="@+id/gov"
     android:layout_width="320dp"
     android:layout_height="300dp"
     android:layout_alignParentBottom="true"
     android:layout_centerHorizontal="true"
     android:layout_marginBottom="100dp"
     android:gestureStrokeType="multiple"
     android:background="#000"/>
 
 </RelativeLayout>

2.java控制代码

package com.example.mygesture;
 
 import android.gesture.Gesture;
 import android.gesture.GestureLibraries;
 import android.gesture.GestureLibrary;
 import android.gesture.GestureOverlayView;
 import android.gesture.Prediction;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.widget.EditText;
 
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 
 import java.util.ArrayList;
 
 //第二步:让Activity实现GestureOverlayView.OnGesturePerformedListener接口,重写onGesturePerformed方法
 public class MainActivity3 extends AppCompatActivity implements GestureOverlayView.OnGesturePerformedListener {
    
    
   private GestureLibrary library;
   private EditText editText;
   private GestureOverlayView gov;
 
   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_3);
     initView();
   }
 
   @Override
   public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    
    
     //第五步:获取最佳匹配进行显示,并更新编辑框
     //获得全部预测结果
     ArrayList<Prediction> gestures=library.recognize(gesture);
     int index=0;//预测对象
     double score=0.0;//预测得分
     for(int i=0;i<gestures.size();i++){
    
    
       Prediction result=gestures.get(i);
       if(result.score>score){
    
    
         index=i;
         score=result.score;
       }
     }
     String text=editText.getText().toString();
     text+=gestures.get(index).name;
     editText.setText(text);
   }
 
   private void initView() {
    
    
     //第三步:加载raw文件中的手势文件,如果加载失败退出应用
     library= GestureLibraries.fromRawResource(MainActivity3.this,R.raw.mygestures);
     //判断加载是否成功
     if(!library.load()){
    
    
       finish();
     }
     //第四步:获得GestureOverlayView组件,并且为其设置属性和事件监听
     editText = (EditText) findViewById(R.id.editText);
     gov = (GestureOverlayView) findViewById(R.id.gov);
     gov.setGestureColor(Color.YELLOW);//颜色
     gov.setGestureStrokeWidth(10);//宽度
     gov.setFadeOffset(2000);//设置间隔为2秒
     //事件监听
     gov.addOnGesturePerformedListener(this);
 
   }
 
 }

猜你喜欢

转载自blog.csdn.net/qq_44408913/article/details/108450870