android开发基础6-android事件处理和手势(明日科技教程)

事件处理概述

基于监听的事件处理

事件监听器
事件源
事件
在这里插入图片描述

Button button = findViewById(R.id.button_1);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this,"单击了按钮",Toast.LENGTH_SHORT).show();
    }
});

基于回调的事件处理

重写android组件特定的回调方法
重写activity的回调方法

常重写的回调方法有:onTouchEvnet、onKeyDown、onKeyUp

public class MainActivity extends Activity {
    private long exitTime = 0; //退出时间变量值
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            exit();
            return true;  //拦截返回键
        }
        return super.onKeyDown(keyCode, event);
    }
    public void exit() {
        if ((System.currentTimeMillis() - exitTime) > 2000) { //计算按键时间差是否大于两秒
            Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
            exitTime = System.currentTimeMillis();
        } else {
            finish();
            System.exit(0); //销毁强制退出
        }
    }
}

两个事件处理方式:

  • 通过的事件 - 使用基于回调的事件处理
  • 特定的事件 - 使用基于监听的事件处理

物理按键事件处理

物理按键:菜单键、主屏建、返回键、音量键、电源键
在这里插入图片描述

每个物理按键都有3个状态:
按下,但是没有松开 : onKeyDown
松开按钮的时候 : onKeyUp
长按按键 : onKeyLongPress

区分时按下的哪个键 :
android对每一个物理键都通过常量进行了定义,如返回键 KEYCODE_BACK

实例:连续按两次返回键退出应用

public class MainActivity extends Activity {
    private long exitTime = 0; //退出时间变量值
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            exit();
            return true;  //拦截返回键
        }
        return super.onKeyDown(keyCode, event);
    }
    public void exit() {
        if ((System.currentTimeMillis() - exitTime) > 2000) { //计算按键时间差是否大于两秒
            Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
            exitTime = System.currentTimeMillis();
        } else {
            finish();
            System.exit(0); //销毁强制退出
        }
    }
}

触摸屏事件处理

单击事件

setOnClickListener实现View.OnClickListener接口中的onClick方法

Button button = findViewById(R.id.button_1);
button.setOnClickListener(new View.OnClickListener() {
    @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this,"单击了按钮",Toast.LENGTH_SHORT).show();
        }
    }); 
}

长按事件

长按,选中文字
长按,选择已读、删除

长按时间:2秒以上才会触发
setOnLongClickListener实现View.OnLongClickListener接口中的onLongClick方法

长按图片弹出菜单

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = (ImageView) findViewById(R.id.imageView); //获取图片组件
        imageView.setOnLongClickListener(new View.OnLongClickListener() { //创建长按监听事件
            @Override
            public boolean onLongClick(View v) {
                registerForContextMenu(v); //将长按事件注册菜单中
                openContextMenu(v); //打开菜单
                return false;
            }
        });
    }
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { //创建菜单
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add("收藏"); //为菜单添加参数
        menu.add("举报");
    }
}

触摸事件

setOnTouchListener实现View.OnTouchListener接口中的onTouch方法

MotionEvent 类 :保存发生触摸的位置、时间等细节信息

实例:通过触摸屏帮企鹅戴好帽子

1、主layout文件,仅配置一个没有帽子的企鹅图片
2、创建帽子的View

/**
 * Created by Administrator on 2016/3/4.
 */
public class HatView extends View {
    public float bitmapX; // 帽子显示位置的X坐标
    public float bitmapY; // 帽子显示位置的Y坐标


    public HatView(Context context) {//重写构造方法
        super(context);
        bitmapX = 65; // 设置帽子的默认显示位置的X坐标
        bitmapY = 0; // 设置帽子的默认显示位置的Y坐标
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(); //创建Paint对象
        //根据图片生成位图对象
        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.hat);
        canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint); // 绘制帽子
        if (bitmap.isRecycled()) { // 判断图片是否回收
            bitmap.recycle(); // 强制回收图片
        }
    }
}

3、触摸屏操作

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout); // 获取相对局管理器
        final HatView hat = new HatView(MainActivity.this); // 创建并实例化HatView类
        // 为帽子添加触摸事件监听
        hat.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                hat.bitmapX = event.getX()-80; // 设置帽子显示位置的X坐标
                hat.bitmapY = event.getY()-50; // 设置帽子显示位置的Y坐标
                hat.invalidate(); // 重绘hat组件
                return true;
            }
        });
        relativeLayout.addView(hat); //将hat添加到布局管理器中
    }
}

单击事件和触摸事件的区别

在单击事件方法时,实际单击事件和触摸事件都发生了
先触发触摸事件,如果触摸消费事件没有完全消费掉,再触发单击事件

在重写触摸事件时,返回了true,表示消费了触摸事件,否则没有完全消费触摸事件,再交给后面的事件进行处理

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       Button button= (Button) findViewById(R.id.btn);  //获得按钮对象
//        为按钮添加单击事件监听器
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("onClick","单击事件");
            }
        });
//        为按钮添加触摸事件监听器
        button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction()==MotionEvent.ACTION_DOWN){	//表示手指按下时
                    Log.i("onTouch","按下");
                }else if (event.getAction()==MotionEvent.ACTION_UP){	//表示手指抬起时
                    Log.i("onTouch","抬起");
                }
                return false;		//表示未消耗掉这个事件
            }
        });
    }
}

手势

手势检测

GestureDetector 手势检测的类
GestureDetector.OnGestureListener一个监听器,对用户的手势行为进行响应
包含6个需要重写的方法
onDown : 触摸事件按下时触发
onFling : 用户的手指在屏幕上拖过是触发
onLongPress : 长按时触发
onScroll :
onShowPress
onSingleTapUp : 手势轻击

实例:实现手机相册的查看相片功能
使用了ViewFlipper,使用动画显示多个组件的切换效果

1、在主layout文件中使用ViewFlipper

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.mingrisoft.MainActivity">
	<ViewFlipper
	    android:id="@+id/flipper"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
	    >
	</ViewFlipper>
</RelativeLayout>

2、创建4个切换动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
    android:fromXDelta="-100%p"
    android:toXDelta="0"
    android:duration="500"/>
</set>

3、手势检测

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener {

    ViewFlipper flipper; //定义ViewFlipper
    GestureDetector detector; //定义手势检测器
    Animation[] animation = new Animation[4];//定义动画数组,为ViewFlipper指定切换动画
    final int distance = 50; //定义手势动作两点之间最小距离
    //定义图片数组
    private int[] images = new int[]{R.drawable.img01, R.drawable.img02, R.drawable.img03,
            R.drawable.img04, R.drawable.img05, R.drawable.img06, R.drawable.img07, R.drawable.img08,
            R.drawable.img09,
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        detector = new GestureDetector(this, this); //创建手势检测器
        flipper = (ViewFlipper) findViewById(R.id.flipper); //获取ViewFlipper
        for (int i = 0; i < images.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(images[i]);
            flipper.addView(imageView); //加载图片
        }
        //初始化动画数组
        animation[0] = AnimationUtils.loadAnimation(this, R.anim.slide_in_left);
        animation[1] = AnimationUtils.loadAnimation(this, R.anim.slide_out_left);
        animation[2] = AnimationUtils.loadAnimation(this, R.anim.slide_in_right);
        animation[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) {
        /*
        如果第一个触点事件的X坐标到第二个触点事件的X坐标的距离超过distance就是从右向左滑动
         */
        if (e1.getX() - e2.getX() > distance) {
            //为flipper设置切换的动画效果
            flipper.setInAnimation(animation[2]);
            flipper.setOutAnimation(animation[1]);
            flipper.showPrevious();
            return true;
            /*
            如果第二个触点事件的X坐标到第一个触点事件的X坐标的距离超过distance就是从左向右滑动
             */
        } else if (e2.getX() - e1.getX() > distance) {
            //为flipper设置切换的动画
            flipper.setInAnimation(animation[0]);
            flipper.setOutAnimation(animation[3]);
            flipper.showNext();
            return true;
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //将该Activity上的触碰事件交给GestureDetector处理
        return detector.onTouchEvent(event);
    }
}

手势的创建和导出

通过下面软件创建手势
在这里插入图片描述
生成的手势文件在sdcard目录下

手势的识别

1、将保存的手势文件保存到raw目录下
2、在layout目录下添加EditText和一个手势组件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/beijing"
    tools:context="com.mingrisoft.MainActivity">
    <EditText
        android:id="@+id/editText"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="40dp"
        android:layout_marginTop="190dp"/>
	<android.gesture.GestureOverlayView
	    android:id="@+id/gesture"
	    android:layout_width="320dp"
	    android:layout_height="180dp"
	    android:layout_alignParentBottom="true"
	    android:gestureStrokeType="multiple"
	    >
	</android.gesture.GestureOverlayView>
</RelativeLayout>

3、识别手势并输出

public class MainActivity extends Activity implements GestureOverlayView.OnGesturePerformedListener {
    private GestureLibrary library;
    private EditText editText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        library = GestureLibraries.fromRawResource
                (MainActivity.this, R.raw.gestures); //加载手势文件
        editText = (EditText) findViewById(R.id.editText); //获取编辑框
        if (!library.load()) {// 如果加载失败则退出
            finish();
        }
        GestureOverlayView gestureOverlayView = (GestureOverlayView) findViewById(R.id.gesture);
        gestureOverlayView.setGestureColor(Color.BLACK);
        gestureOverlayView.setFadeOffset(1000);
        gestureOverlayView.addOnGesturePerformedListener(this);// 增加事件监听器
    }
    @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);// 更新编辑框
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值