http://blog.csdn.net/dawanganban/article/details/20408505
上一篇《是男人就下100层【第一层】——高仿微信界面(7)》中我们实现了下弹式菜单,这一篇我们来看看如何实现微信中的摇一摇功能。
首先我们来布局我们的摇一摇界面
布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#111"
>
<relativelayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerinparent="true" >
<imageview
android:id="@+id/shakebg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerinparent="true"
android:src="@drawable/shakehideimg_man2" />
<linearlayout
android:layout_width="fill_parent"
android:layout_centerinparent="true"
android:orientation="vertical" >
<relativelayout
android:id="@+id/shakeimgup"
android:layout_width="fill_parent"
android:layout_height="190dp"
android:background="#111">
<imageview
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignparentbottom="true"
android:layout_centerhorizontal="true"
android:src="@drawable/shake_logo_up"
/>
</relativelayout>
android:id="@+id/shakeimgdown"
android:src="@drawable/shake_logo_down"
</relativelayout>
</linearlayout>
</relativelayout>
<relativelayout
android:id="@+id/shake_title_bar"
android:layout_height="45dp"
android:background="@drawable/title_bar"
android:gravity="center_vertical" >
<button
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_centervertical="true"
android:text="返回"
android:textsize="14sp"
android:textcolor="#fff"
android:onclick="shake_activity_back"
android:background="@drawable/title_btn_back"/>
<textview
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="摇一摇"
android:layout_centerinparent="true"
android:textsize="20sp"
android:textcolor="#ffffff" />
<imagebutton
android:layout_width="67dp"
android:layout_alignparentright="true"
android:layout_marginright="5dp"
android:src="@drawable/mm_title_btn_menu"
android:background="@drawable/title_btn_right"
android:onclick="linshi"
/>
<slidingdrawer
android:id="@+id/slidingdrawer1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:content="@+id/content"
android:handle="@+id/handle" >
<button
android:id="@+id/handle"
android:layout_height="wrap_content"
android:background="@drawable/shake_report_dragger_up" />
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f9f9f9" >
<imageview
android:layout_width="match_parent"
android:scaletype="fitxy"
android:src="@drawable/shake_line_up" />
</slidingdrawer>
</relativelayout>
这个布局里面用到了很多相对布局,最外面是一个相对布局(我们先称为r1),r1内是两个相对布局(分别称为r2、r3)和一个抽屉组件,r3是上部标题栏,r2中有一个imageview和一个线性布局,这两个组件都位于r2的中心,所以上面的线性布局会将下面的imageview遮住,为什么要遮住,玩过微信摇一摇的朋友应该明白。
slidingdrawer隐藏屏外的内容,并允许用户通过handle以显示隐藏内容。它可以垂直或水平滑动,它有俩个view组成,其一是可以拖动的handle,其二是隐藏内容的view.它里面的控件必须设置布局,在布局文件中必须指定handle和content.
接下来我们看看如何检查手机摇晃,摇一摇让手机震动
package com.example.weixin.listener;
import android.content.context;
import android.hardware.sensor;
import android.hardware.sensorevent;
import android.hardware.sensoreventlistener;
import android.hardware.sensormanager;
import android.util.log;
/**
* 一个检测手机摇晃的监听器
*/
public class shakelistener implements sensoreventlistener {
// 速度阈值,当摇晃速度达到这值后产生作用
private static final int speed_shreshold = 3000;
// 两次检测的时间间隔
private static final int uptate_interval_time = 70;
// 传感器管理器
private sensormanager sensormanager;
// 传感器
private sensor sensor;
// 重力感应监听器
private onshakelistener onshakelistener;
// 上下文
private context mcontext;
// 手机上一个位置时重力感应坐标
private float lastx;
private float lasty;
private float lastz;
// 上次检测时间
private long lastupdatetime;
// 构造器
public shakelistener(context c) {
// 获得监听对象
mcontext = c;
start();
}
// 开始
public void start() {
// 获得传感器管理器
sensormanager = (sensormanager) mcontext
.getsystemservice(context.sensor_service);
if (sensormanager != null) {
// 获得重力传感器
sensor = sensormanager.getdefaultsensor(sensor.type_accelerometer);
}
// 注册
if (sensor != null) {
sensormanager.registerlistener(this, sensor,
sensormanager.sensor_delay_game);
// 停止检测
public void stop() {
sensormanager.unregisterlistener(this);
// 设置重力感应监听器
public void setonshakelistener(onshakelistener listener) {
onshakelistener = listener;
// 重力感应器感应获得变化数据
public void onsensorchanged(sensorevent event) {
// 现在检测时间
long currentupdatetime = system.currenttimemillis();
// 两次检测的时间间隔
long timeinterval = currentupdatetime - lastupdatetime;
// 判断是否达到了检测时间间隔
if (timeinterval < uptate_interval_time)
return;
// 现在的时间变成last时间
lastupdatetime = currentupdatetime;
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 获得x,y,z的变化值
float deltax = x - lastx;
float deltay = y - lasty;
float deltaz = z - lastz;
// 将现在的坐标变成last坐标
lastx = x;
lasty = y;
lastz = z;
double speed = math.sqrt(deltax * deltax + deltay * deltay + deltaz
* deltaz)
/ timeinterval * 10000;
//log.v("thelog", "===========log===================");
// 达到速度阀值,发出提示
if (speed >= speed_shreshold) {
onshakelistener.onshake();
public void onaccuracychanged(sensor sensor, int accuracy) {
// 摇晃监听接口
public interface onshakelistener {
public void onshake();
}
sensormanager是一个系统提供来管理传感器的服务。
sensormanager通过getdefaultsensor(int type)方法来获取指定类型的传感器。
// 获得重力传感器
sensor = sensormanager.getdefaultsensor(sensor.type_accelerometer);
sensormanager提供了一个注册传感器的方法:registerlistener
sensormanager.registerlistener(this, sensor,
sensoreventlistener接口定义了两个方法需要实现
onsensorchanged()方法,当传感器的值发生改变时触发该方法。
onaccuracychanged()方法,当传感器的精度发生改变时触发该方法。
// 重力感应器感应获得变化数据
public void onsensorchanged(sensorevent event) {
// 现在检测时间
long currentupdatetime = system.currenttimemillis();
long timeinterval = currentupdatetime - lastupdatetime;
// 判断是否达到了检测时间间隔
if (timeinterval < uptate_interval_time)
return;
// 现在的时间变成last时间
lastupdatetime = currentupdatetime;
// 获得x,y,z坐标
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
// 获得x,y,z的变化值
float deltax = x - lastx;
float deltay = y - lasty;
float deltaz = z - lastz;
// 将现在的坐标变成last坐标
lastx = x;
lasty = y;
lastz = z;
double speed = math.sqrt(deltax * deltax + deltay * deltay + deltaz
* deltaz)
/ timeinterval * 10000;
//log.v("thelog", "===========log===================");
// 达到速度阀值,发出提示
if (speed >= speed_shreshold) {
onshakelistener.onshake();
坐标对应的关系看下图可知
这里计算速度的公式是高中学过的知识v=s/t=(a^2+b^2+c^2)/t
double speed = math.sqrt(deltax * deltax + deltay * deltay + deltaz
在activity中创建摇动监听实例并设置监听
mshakelistener = new shakelistener(this);
mshakelistener.setonshakelistener(new onshakelistener() {
public void onshake() {
//toast.maketext(getapplicationcontext(), "抱歉,暂时没有找到在同一时刻摇一摇的人。\n再试一次吧!", toast.length_short).show();
startanim(); //开始 摇一摇手掌动画
mshakelistener.stop();
startvibrato(); //开始 震动
new handler().postdelayed(new runnable(){
@override
public void run(){
//toast.maketext(getapplicationcontext(), "抱歉,暂时没有找到\n在同一时刻摇一摇的人。\n再试一次吧!", 500).setgravity(gravity.center,0,0).show();
toast mtoast;
mtoast = toast.maketext(getapplicationcontext(),
"抱歉,暂时没有找到\n在同一时刻摇一摇的人。\n再试一次吧!", 10);
//mtoast.setgravity(gravity.center, 0, 0);
mtoast.show();
mvibrator.cancel();
mshakelistener.start();
}
}, 2000);
});
在设置监听之前,在activity的oncreate方法中需呀获得系统提供的振动服务对象
vibrator mvibrator = (vibrator)getapplication().getsystemservice(vibrator_service);
有关vibrator的使用请看我的另一篇博文:http://blog.csdn.net/dawanganban/article/details/17531697
public void startvibrato(){ //定义震动
mvibrator.vibrate( new long[]{500,200,500,200}, -1); //第一个{}里面是节奏数组, 第二个参数是重复次数,-1为不重复,非-1俄日从pattern的指定下标开始重复
摇一摇的时候还有一个图片移动的动画,设置动画代码如下:
public void startanim () { //定义摇一摇动画动画
animationset animup = new animationset(true);
translateanimation mytranslateanimup0 = new translateanimation(animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,-0.5f);
mytranslateanimup0.setduration(1000);
translateanimation mytranslateanimup1 = new translateanimation(animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,+0.5f);
mytranslateanimup1.setduration(1000);
mytranslateanimup1.setstartoffset(1000);
animup.addanimation(mytranslateanimup0);
animup.addanimation(mytranslateanimup1);
mimgup.startanimation(animup);
animationset animdn = new animationset(true);
translateanimation mytranslateanimdn0 = new translateanimation(animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,+0.5f);
mytranslateanimdn0.setduration(1000);
translateanimation mytranslateanimdn1 = new translateanimation(animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,0f,animation.relative_to_self,-0.5f);
mytranslateanimdn1.setduration(1000);
mytranslateanimdn1.setstartoffset(1000);
animdn.addanimation(mytranslateanimdn0);
animdn.addanimation(mytranslateanimdn1);
mimgdn.startanimation(animdn);
运行效果如下:
源代码下载:http://download.csdn.net/detail/lxq_xsyu/6990129