Android手势和shape

来源:互联网 发布:windows下pyqt4的安装 编辑:程序博客网 时间:2024/04/29 18:00

现在所有的手机绝大部分已经都是触屏的,固这些手机都会对手指对屏幕的操作进行监控。android提供了手势识别器来对手势操作进行了监听:

GestureDetector gestureDetector =new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {}

其中可以重写其方法有如下几种:

抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。

 public boolean onFling(MotionEvent event1, MotionEvent event2,               float velocityX, float velocityY) {          Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());          return true;      }  
按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。

<span style="font-size:18px;">public boolean onDown(MotionEvent e) {// TODO Auto-generated method stubreturn super.onDown(e);}</span>

长按(onLongPress): 手指按在持续一段时间,并且没有松开。

<span style="font-size:18px;">public void onLongPress(MotionEvent e) {// TODO Auto-generated method stubsuper.onLongPress(e);}</span>

滑动(onScroll): 手指在触摸屏上滑动。

<span style="font-size:18px;">public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// TODO Auto-generated method stubreturn super.onScroll(e1, e2, distanceX, distanceY);}</span>


抬起(onSingleTapUp):手指离开触摸屏的瞬间。

<span style="font-size:18px;">public boolean onSingleTapUp(MotionEvent e) {// TODO Auto-generated method stubreturn super.onSingleTapUp(e);}</span>

按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。

<span style="font-size:18px;">public void onShowPress(MotionEvent e) {// TODO Auto-generated method stubsuper.onShowPress(e);}</span>
双击( onDoubleTap):双击的时候触发

<span style="font-size:18px;">public boolean onDoubleTap(MotionEvent e) {// TODO Auto-generated method stubreturn super.onDoubleTap(e);}</span>
 使用OnGestureListener接口,这样需要重载OnGestureListener接口所有的方法,适合监听所有的手势。相比

另一个onTouchEvent(MotionEvent event)直接去识别优势就很明显,该方法只能提供比较简单的事件:

public boolean onTouchEvent(MotionEvent event){                 int action = MotionEventCompat.getActionMasked(event);                switch(action) {          case (MotionEvent.ACTION_DOWN) :              Log.d(DEBUG_TAG,"Action was DOWN");              return true;          case (MotionEvent.ACTION_MOVE) :              Log.d(DEBUG_TAG,"Action was MOVE");              return true;          case (MotionEvent.ACTION_UP) :              Log.d(DEBUG_TAG,"Action was UP");              return true;          case (MotionEvent.ACTION_CANCEL) :              Log.d(DEBUG_TAG,"Action was CANCEL");              return true;          case (MotionEvent.ACTION_OUTSIDE) :              Log.d(DEBUG_TAG,"Movement occurred outside bounds " +                      "of current screen element");              return true;                default :               return super.onTouchEvent(event);      }        } 

所以一般都是使用手势识别器,简单而强大为什么不用。


例子:

import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;public abstract class BaseSetupActivity extends Activity {private Intent intent;private GestureDetector gestureDetector;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 创建手势识别器gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {@Override// 重写手势识别器中的方法public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {// e1 起始点// e2 抬起点if (e1.getRawX() - e2.getRawX() > 50) {showNextPage();//关闭动画overridePendingTransition(0, 0);}if (e2.getRawX() - e1.getRawX() > 50) {showPrePage();//关闭动画overridePendingTransition(0, 0);}return super.onFling(e1, e2, velocityX, velocityY);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {if (e1.getRawX() - e2.getRawX() > 500) {showNextPage();//关闭动画overridePendingTransition(0, 0);}if (e2.getRawX() - e1.getRawX() > 500) {showPrePage();//关闭动画overridePendingTransition(0, 0);}return super.onFling(e1, e2, distanceX, distanceY);}});}// 抽象方法,去定义调转到下一页的方法public abstract void showNextPage();// 抽象方法,去定义调转到上一页的方法public abstract void showPrePage();// 统一处理跳转界面 下一页 交给子类处理 ,点击和滑动聚合在一起了public void nextPage(View v) {showNextPage();// 开启平移动画overridePendingTransition(R.anim.next_in_anim, R.anim.next_out_anim);}// 统一处理跳转界面 上一页 交给子类处理 , 点击和滑动聚合在一起了public void prePage(View v) {showPrePage();// 开启平移动画overridePendingTransition(R.anim.next_in_anim, R.anim.next_out_anim);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 通过手势识别器去识别不同的事件类型gestureDetector.onTouchEvent(event);return super.onTouchEvent(event);}}
通过投掷和滑动的手势进行界面的跳转(跳转的代码没有写出)

事件的分发:


当Android在监听到屏幕上的手势事件后,会根据布局视图的层级进行分发,从结构最外层的ViewGroug往下面传递,
一直到中途被某一层级的View截断而消费掉,不在往下传递,属于消费事件。要先了解事件分发的函数:

View中有两个方法参与到Touch事件分发
onDispatchTouchEvent(MotionEvent event)和onTouch(MotionEvent event)
ViewGroup有三个方法参与到Touch事件分发
onDispatchTouchEvent(MotionEvent event),onInterceptTouchEvent(MotionEvent ev),onTouch(MotionEvent event)

了解三个函数的含义:

1、dispatchTouchEvent

dispatch是否分发事件,整个事件的驱动都在这个方法中,他会先调用自己的onInterceptTouchEvent,再递归调用child的dispatchTouchEvent,这样就可以将事件一直传下去,如果我们覆写了这个方法,而且没有调用super.dispatchTouchEvent(),也就是我们将事件调用的递归过程在这里截断了,child就不会收到该事件的传递,所以这里可以对事件的进行第一次拦截,这里返回true,表示该View已经消费了这个事件,事件传递结束;返回false,表示没有消费,事件返回父控件onTouchEven进行处理。

2、onInterceptTouchEvent
intercept意思是拦截、截断,所以该方法的作用就是判断是否要将这个事件断下来。返回true,事件截断,进入onTouchEvent消费事件;返回false,不进行拦截,事件继续向下传递,进入到子view的dispatchTouchEvent。
3、onTouchEvent
代表是否该view消费了该事件,也就是是否对该事件的发生进行了相应的处理,返回true一个事件就到这里结束了,返回false说明事件没有被消费,事件向上返回到父控件的onTouchEvent方法。

一个简单的例子:

写一个button按钮的监听:

<span style="font-size:18px;">button.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View v) {          Log.d("TAG", "onClick execute");      }  });  </span>
再写button的onTouch的监听:

<span style="font-size:18px;">button.setOnTouchListener(new OnTouchListener() {      @Override      public boolean onTouch(View v, MotionEvent event) {          Log.d("TAG", "onTouch execute, action " + event.getAction());          return false;      }  }); </span>
当点击了button后,这里肯定会触发onTouch的ACTION_DOWN和ACTION_UP事件,可能你按的时候抖了一下就产生ACTION_MOVE事件

固这里打印会有:

onTouch execute,action 0onTouch execute,action 1onClick   execute
首先:源码中只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法。那当我们去点击按钮的时候,就会去调用Button类里的dispatchTouchEvent方法,可是你会发现Button类里并没有这个方法,那么就到它的父类TextView里去找一找,你会发现TextView里也没有这个方法,那没办法了,只好继续在TextView的父类View里找一找,这个时候你终于在View里找到了这个方法(super回调父类方法),示意图如下:



这里就简单描叙下:http://files.cnblogs.com/files/sunzn/PRE_andevcon_mastering-the-android-touch-system.pdf

事件分发大神的分析路径:

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

http://blog.csdn.net/guolin_blog/article/details/9097463
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

http://blog.csdn.net/guolin_blog/article/details/9153761


shape的用法:Android中常常使用shape来定义控件的一些显示属性:
直接看代码:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#CCCCCC"
        android:endColor="#CCCCCC"
        android:angle="45"/>

    <padding android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp" />
    <corners android:radius="16dp" />
</shape>
这里设置的为16dp的圆角矩形,在代码中通过R.drawable.name 进行访问,在xml中通过@drawable/filename进行访问
属性介绍:
android:startColor="#CCCCCC"  渐变色的开始颜色
android:endColor    颜色值 结束颜色
android:centerColor 整型   渐变中间颜色,即开始颜色与结束颜色之间的颜色
  android:angle       整型   渐变角度(PS:当angle=0时,渐变色是从左向右。 然后逆时针方向转,当angle=90时为从下往上。angle必须为45的整数倍)
android:type  渐变类型: linear 线性渐变,这是默认设置     radial 放射性渐变,以开始色为中心。    sweep 扫描线式的渐变。

android:centerX     整型   渐变中心X点坐标的相对位置
android:centerY   整型   渐变中心Y点坐标的相对位置
android:left="5dp"  整型 左内边距
android:top="5dp"  整型 上内边距
android:right="5dp"   整型 右内边距
android:bottom="5dp" 整型 下内边距  (设置padding时,不要再次去布局中设定,会产生冲突,drawable无效)
<corners android:radius="16dp" /> 设置圆角全局半径
android:topLeftRadius   整型 左上角半径
android:topRightRadius   整型 右上角半径
android:bottomLeftRadius 整型 左下角半径
android:bottomRightRadius 整型 右下角半径
<solid android:color="#00000000" />实心填充
 <stroke 
        android:width="2dp"
        android:color="#dcdcdc"  
        /> 

描边: android:width 整型 描边的宽度

android:color 颜色值 描边的颜色


BaseActivity的用处:
Android应用的时候最基本的类当然是Activity了,我们一般的情况下要建立一个或者多个基类Activity然后让别的Activity来继承于它
,(根据不同功能框架划分)减少代码的复用,工程框架更加清晰。
用法非常简单,java的基础知识(继承,抽象类,接口回掉,多态,动态绑定,封装方法)的几个知识点就行了:
我们继承于一个类,让它成为抽象类,加上一些初始化的抽象方法,这样我们再继承于这个类的时候就必须去实现这些抽象方法,
就不用我们去手动添加,这样也不会让我们丢失了一些操作,
如初始化界面intiUI();初始化数据intiDate()等方法,可以放到BaseActiviy的onCreate()中,就不用每次去写了。
1)肯定我们不用再去托运添加实现findViews()init()setLinsteners()这些初始化方法了
2)我们不用再在每个Activity中手动调用这自定义共有方法,因为我们的BaseActivity已经为我们做好了封装。
直接eclipse点几下就行了,比Ctrl+c Ctrl+v还快。以下列子:
多个界面的切换,都要用到下一页和上一页的功能:BaseSetupActivity
import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;public abstract class BaseSetupActivity extends Activity {private Intent intent;private GestureDetector gestureDetector;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 创建手势识别器gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {@Override// 重写手势识别器中的方法public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {// e1 起始点// e2 抬起点if (e1.getRawX() - e2.getRawX() > 50) {showNextPage();//关闭动画overridePendingTransition(0, 0);}if (e2.getRawX() - e1.getRawX() > 50) {showPrePage();//关闭动画overridePendingTransition(0, 0);}return super.onFling(e1, e2, velocityX, velocityY);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {if (e1.getRawX() - e2.getRawX() > 500) {showNextPage();//关闭动画overridePendingTransition(0, 0);}if (e2.getRawX() - e1.getRawX() > 500) {showPrePage();//关闭动画overridePendingTransition(0, 0);}return super.onFling(e1, e2, distanceX, distanceY);}});}// 抽象方法,去定义调转到下一页的方法public abstract void showNextPage();// 抽象方法,去定义调转到上一页的方法public abstract void showPrePage();// 统一处理跳转界面 下一页 交给子类处理 ,点击和滑动聚合在一起了public void nextPage(View v) {showNextPage();// 开启平移动画overridePendingTransition(R.anim.next_in_anim, R.anim.next_out_anim);}// 统一处理跳转界面 上一页 交给子类处理 , 点击和滑动聚合在一起了public void prePage(View v) {showPrePage();// 开启平移动画overridePendingTransition(R.anim.next_in_anim, R.anim.next_out_anim);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 通过手势识别器去识别不同的事件类型gestureDetector.onTouchEvent(event);return super.onTouchEvent(event);}}
某个界面的基础与BaseSetupActivity 实现了抽象方法,直接看最下面的方法就行了,其他的不管
package com.itheima.mobilesafe74.activity;import com.itheima.mobilesafe74.R;import com.itheima.mobilesafe74.utils.ConstantVaule;import com.itheima.mobilesafe74.utils.SpUtil;import com.itheima.mobilesafe74.utils.ToastUtil;import com.itheima.mobilesafe74.view.SettingItemView;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.telephony.TelephonyManager;import android.text.TextUtils;import android.view.View;import android.view.View.OnClickListener;import android.widget.Toast;public class Setup2Activity extends BaseSetupActivity {private SettingItemView siv_sim_bound;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.setup2);intiUi();}private void intiUi() {siv_sim_bound = (SettingItemView) findViewById(R.id.siv_sim_bound);// 1,读取已有的绑定状态 用来回显 sp中是否存储了sim卡的序列号String sim_number = SpUtil.getString(this, ConstantVaule.SIM_NUMBER, "");// 2,判断是否为空""if (TextUtils.isEmpty(sim_number)) {siv_sim_bound.setCheck(false);} else {siv_sim_bound.setCheck(true);}siv_sim_bound.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 3,获取原有的状态boolean isCheck = siv_sim_bound.isCheck();// 4,将原有的状态取反// 5,状态设置给当前条目siv_sim_bound.setCheck(!isCheck);if (!isCheck) {// 6,存储(序列号)// 6.1获取sim卡序列号TelephonyManagerTelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);// 6.2拿到sim卡序列卡号String simSerialNumber = manager.getSimSerialNumber();Toast.makeText(getApplicationContext(), simSerialNumber, 1).show();// 6.3存储SpUtil.putString(getApplicationContext(), ConstantVaule.SIM_NUMBER, simSerialNumber);} else {// 7,将存储序列号的节点,从sp中删除SpUtil.remove(getApplicationContext(), ConstantVaule.SIM_NUMBER);}}});}//老版手机更换手机sim卡,监听在开机发送开启广播,一旦捕获到此广播//就让其广播接收者的onReceiver中发送短信到安全号码@Overridepublic void showNextPage() {String SerialNumber = SpUtil.getString(this, ConstantVaule.SIM_NUMBER, "");if (TextUtils.isEmpty(SerialNumber)) {ToastUtil.show(this, "请绑定sim卡,亲");} else {Intent intent = new Intent(getApplicationContext(), Setup3Activity.class);startActivity(intent);finish();}}@Overridepublic void showPrePage() {Intent intent = new Intent(getApplicationContext(), Setup1Activity.class);startActivity(intent);finish();}}

总结:掌握shape的用法和属性,了解手势的分发机制,掌握手势管理器处理几种必用到的手势。学会BaseActivity的工程框架。















1 0
原创粉丝点击