Android手势和shape

现在所有的手机绝大部分已经都是触屏的,固这些手机都会对手指对屏幕的操作进行监控。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 stub
				return super.onDown(e);
			}</span>

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

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

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

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


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

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

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

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

<span style="font-size:18px;">public boolean onDoubleTap(MotionEvent e) {
				// TODO Auto-generated method stub
				return 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;

	@Override
	protected 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);
			}
			
			@Override
			public 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);
	}

	@Override
	public 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 0
onTouch execute,action 1
onClick   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;

	@Override
	protected 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);
			}
			
			@Override
			public 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);
	}

	@Override
	public 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;

	@Override
	protected 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() {

			@Override
			public void onClick(View v) {
				// 3,获取原有的状态
				boolean isCheck = siv_sim_bound.isCheck();
				// 4,将原有的状态取反
				// 5,状态设置给当前条目
				siv_sim_bound.setCheck(!isCheck);

				if (!isCheck) {
					// 6,存储(序列号)
					// 6.1获取sim卡序列号TelephonyManager
					TelephonyManager 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中发送短信到安全号码
	
	@Override
	public 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();
		}
	}

	@Override
	public void showPrePage() {
		Intent intent = new Intent(getApplicationContext(), Setup1Activity.class);
		startActivity(intent);
		finish();
	}
}

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















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值