Android 高仿微信界面

http://blog.csdn.net/dawanganban/article/details/20408505

上一篇《是男人就下100层【第一层】——高仿微信界面(7)》中我们实现了下弹式菜单,这一篇我们来看看如何实现微信中的摇一摇功能。

首先我们来布局我们的摇一摇界面


布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"  
  6.     android:background="#111"  
  7.     >  
  8.       
  9.     <RelativeLayout  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="fill_parent"  
  12.         android:layout_centerInParent="true" >  
  13.               
  14.         <ImageView  
  15.             android:id="@+id/shakeBg"  
  16.             android:layout_width="wrap_content"  
  17.             android:layout_height="wrap_content"  
  18.             android:layout_centerInParent="true"          
  19.             android:src="@drawable/shakehideimg_man2" />  
  20.           
  21.         <LinearLayout  
  22.             android:layout_width="fill_parent"  
  23.             android:layout_height="wrap_content"  
  24.             android:layout_centerInParent="true"  
  25.             android:orientation="vertical" >  
  26.               
  27.             <RelativeLayout  
  28.                 android:id="@+id/shakeImgUp"     
  29.                 android:layout_width="fill_parent"  
  30.                 android:layout_height="190dp"                 
  31.                 android:background="#111">                 
  32.                 <ImageView                     
  33.                     android:layout_width="wrap_content"  
  34.                     android:layout_height="wrap_content"  
  35.                     android:layout_alignParentBottom="true"  
  36.                     android:layout_centerHorizontal="true"                                
  37.                     android:src="@drawable/shake_logo_up"  
  38.                      />                  
  39.             </RelativeLayout>  
  40.             <RelativeLayout  
  41.                 android:id="@+id/shakeImgDown"  
  42.                 android:layout_width="fill_parent"  
  43.                 android:layout_height="190dp"                 
  44.                 android:background="#111">                 
  45.                 <ImageView                     
  46.                     android:layout_width="wrap_content"  
  47.                     android:layout_height="wrap_content"  
  48.                     android:layout_centerHorizontal="true"                                
  49.                     android:src="@drawable/shake_logo_down"  
  50.                      />                  
  51.             </RelativeLayout>   
  52.         </LinearLayout>  
  53.     </RelativeLayout>  
  54.       
  55.     <RelativeLayout   
  56.         android:id="@+id/shake_title_bar"   
  57.         android:layout_width="fill_parent"  
  58.         android:layout_height="45dp"  
  59.         android:background="@drawable/title_bar"  
  60.         android:gravity="center_vertical"  >  
  61.             <Button  
  62.                 android:layout_width="70dp"  
  63.                 android:layout_height="wrap_content"  
  64.                 android:layout_centerVertical="true"  
  65.                 android:text="返回"  
  66.                 android:textSize="14sp"  
  67.                 android:textColor="#fff"  
  68.                 android:onClick="shake_activity_back"  
  69.                 android:background="@drawable/title_btn_back"/>    
  70.             <TextView  
  71.                 android:layout_width="wrap_content"   
  72.                 android:layout_height="wrap_content"   
  73.                 android:text="摇一摇"  
  74.                 android:layout_centerInParent="true"  
  75.                 android:textSize="20sp"       
  76.                 android:textColor="#ffffff" />   
  77.             <ImageButton   
  78.                 android:layout_width="67dp"   
  79.                 android:layout_height="wrap_content"  
  80.                 android:layout_alignParentRight="true"   
  81.                 android:layout_centerVertical="true"  
  82.                 android:layout_marginRight="5dp"  
  83.                 android:src="@drawable/mm_title_btn_menu"  
  84.                 android:background="@drawable/title_btn_right"  
  85.                 android:onClick="linshi"   
  86.                 />        
  87.     </RelativeLayout>  
  88.       
  89.   
  90.     <SlidingDrawer  
  91.         android:id="@+id/slidingDrawer1"  
  92.         android:layout_width="match_parent"  
  93.         android:layout_height="match_parent"  
  94.         android:content="@+id/content"  
  95.         android:handle="@+id/handle" >  
  96.         <Button  
  97.             android:id="@+id/handle"  
  98.             android:layout_width="wrap_content"  
  99.             android:layout_height="wrap_content"       
  100.                     
  101.             android:background="@drawable/shake_report_dragger_up" />  
  102.         <LinearLayout  
  103.             android:id="@+id/content"  
  104.             android:layout_width="match_parent"  
  105.             android:layout_height="match_parent"  
  106.             android:background="#f9f9f9" >              
  107.             <ImageView  
  108.                 android:layout_width="match_parent"  
  109.                 android:layout_height="wrap_content"  
  110.                 android:scaleType="fitXY"  
  111.                 android:src="@drawable/shake_line_up" />  
  112.         </LinearLayout>  
  113.     </SlidingDrawer>  
  114.   
  115. </RelativeLayout>  
这个布局里面用到了很多相对布局,最外面是一个相对布局(我们先称为R1),R1内是两个相对布局(分别称为R2、R3)和一个抽屉组件,R3是上部标题栏,R2中有一个ImageView和一个线性布局,这两个组件都位于R2的中心,所以上面的线性布局会将下面的ImageView遮住,为什么要遮住,玩过微信摇一摇的朋友应该明白。

SlidingDrawer隐藏屏外的内容,并允许用户通过handle以显示隐藏内容。它可以垂直或水平滑动,它有俩个View组成,其一是可以拖动的handle,其二是隐藏内容的View.它里面的控件必须设置布局,在布局文件中必须指定handle和content.

接下来我们看看如何检查手机摇晃,摇一摇让手机震动

  1. package com.example.weixin.listener;  
  2.   
  3. import android.content.Context;  
  4. import android.hardware.Sensor;  
  5. import android.hardware.SensorEvent;  
  6. import android.hardware.SensorEventListener;  
  7. import android.hardware.SensorManager;  
  8. import android.util.Log;  
  9.   
  10. /** 
  11.  * 一个检测手机摇晃的监听器 
  12.  */  
  13. public class ShakeListener implements SensorEventListener {  
  14.     // 速度阈值,当摇晃速度达到这值后产生作用  
  15.     private static final int SPEED_SHRESHOLD = 3000;  
  16.     // 两次检测的时间间隔  
  17.     private static final int UPTATE_INTERVAL_TIME = 70;  
  18.     // 传感器管理器  
  19.     private SensorManager sensorManager;  
  20.     // 传感器  
  21.     private Sensor sensor;  
  22.     // 重力感应监听器  
  23.     private OnShakeListener onShakeListener;  
  24.     // 上下文  
  25.     private Context mContext;  
  26.     // 手机上一个位置时重力感应坐标  
  27.     private float lastX;  
  28.     private float lastY;  
  29.     private float lastZ;  
  30.     // 上次检测时间  
  31.     private long lastUpdateTime;  
  32.   
  33.     // 构造器  
  34.     public ShakeListener(Context c) {  
  35.         // 获得监听对象  
  36.         mContext = c;  
  37.         start();  
  38.     }  
  39.   
  40.     // 开始  
  41.     public void start() {  
  42.         // 获得传感器管理器  
  43.         sensorManager = (SensorManager) mContext  
  44.                 .getSystemService(Context.SENSOR_SERVICE);  
  45.         if (sensorManager != null) {  
  46.             // 获得重力传感器  
  47.             sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
  48.         }  
  49.         // 注册  
  50.         if (sensor != null) {  
  51.             sensorManager.registerListener(this, sensor,  
  52.                     SensorManager.SENSOR_DELAY_GAME);  
  53.         }  
  54.   
  55.     }  
  56.   
  57.     // 停止检测  
  58.     public void stop() {  
  59.         sensorManager.unregisterListener(this);  
  60.     }  
  61.   
  62.     // 设置重力感应监听器  
  63.     public void setOnShakeListener(OnShakeListener listener) {  
  64.         onShakeListener = listener;  
  65.     }  
  66.   
  67.     // 重力感应器感应获得变化数据  
  68.     public void onSensorChanged(SensorEvent event) {  
  69.         // 现在检测时间  
  70.         long currentUpdateTime = System.currentTimeMillis();  
  71.         // 两次检测的时间间隔  
  72.         long timeInterval = currentUpdateTime - lastUpdateTime;  
  73.         // 判断是否达到了检测时间间隔  
  74.         if (timeInterval < UPTATE_INTERVAL_TIME)  
  75.             return;  
  76.         // 现在的时间变成last时间  
  77.         lastUpdateTime = currentUpdateTime;  
  78.   
  79.         // 获得x,y,z坐标  
  80.         float x = event.values[0];  
  81.         float y = event.values[1];  
  82.         float z = event.values[2];  
  83.   
  84.         // 获得x,y,z的变化值  
  85.         float deltaX = x - lastX;  
  86.         float deltaY = y - lastY;  
  87.         float deltaZ = z - lastZ;  
  88.   
  89.         // 将现在的坐标变成last坐标  
  90.         lastX = x;  
  91.         lastY = y;  
  92.         lastZ = z;  
  93.   
  94.         double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
  95.                 * deltaZ)  
  96.                 / timeInterval * 10000;  
  97.         //Log.v("thelog", "===========log===================");  
  98.         // 达到速度阀值,发出提示  
  99.         if (speed >= SPEED_SHRESHOLD) {  
  100.             onShakeListener.onShake();  
  101.         }  
  102.     }  
  103.   
  104.     public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  105.   
  106.     }  
  107.   
  108.     // 摇晃监听接口  
  109.     public interface OnShakeListener {  
  110.         public void onShake();  
  111.     }  
  112.   
  113. }  
SensorManager是一个系统提供来管理传感器的服务。

SensorManager通过getDefaultSensor(int type)方法来获取指定类型的传感器。

  1. // 获得重力传感器  
  2. sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);  
SensorManager提供了一个注册传感器的方法:registerListener

  1. sensorManager.registerListener(this, sensor,  
  2.                     SensorManager.SENSOR_DELAY_GAME);  
SensorEventListener接口定义了两个方法需要实现

onSensorChanged()方法,当传感器的值发生改变时触发该方法。

onAccuracyChanged()方法,当传感器的精度发生改变时触发该方法。

  1. // 重力感应器感应获得变化数据  
  2. public void onSensorChanged(SensorEvent event) {  
  3.     // 现在检测时间  
  4.     long currentUpdateTime = System.currentTimeMillis();  
  5.     // 两次检测的时间间隔  
  6.     long timeInterval = currentUpdateTime - lastUpdateTime;  
  7.     // 判断是否达到了检测时间间隔  
  8.     if (timeInterval < UPTATE_INTERVAL_TIME)  
  9.         return;  
  10.     // 现在的时间变成last时间  
  11.     lastUpdateTime = currentUpdateTime;  
  12.   
  13.     // 获得x,y,z坐标  
  14.     float x = event.values[0];  
  15.     float y = event.values[1];  
  16.     float z = event.values[2];  
  17.   
  18.     // 获得x,y,z的变化值  
  19.     float deltaX = x - lastX;  
  20.     float deltaY = y - lastY;  
  21.     float deltaZ = z - lastZ;  
  22.   
  23.     // 将现在的坐标变成last坐标  
  24.     lastX = x;  
  25.     lastY = y;  
  26.     lastZ = z;  
  27.   
  28.     double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
  29.             * deltaZ)  
  30.             / timeInterval * 10000;  
  31.     //Log.v("thelog", "===========log===================");  
  32.     // 达到速度阀值,发出提示  
  33.     if (speed >= SPEED_SHRESHOLD) {  
  34.         onShakeListener.onShake();  
  35.     }  
  36. }  
坐标对应的关系看下图可知

这里计算速度的公式是高中学过的知识v=s/t=(a^2+b^2+c^2)/t

  1. double speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ  
  2.                 * deltaZ)  
  3.                 / timeInterval * 10000;  

在Activity中创建摇动监听实例并设置监听

  1. mShakeListener = new ShakeListener(this);  
  2.        mShakeListener.setOnShakeListener(new OnShakeListener() {  
  3.         public void onShake() {  
  4.             //Toast.makeText(getApplicationContext(), "抱歉,暂时没有找到在同一时刻摇一摇的人。\n再试一次吧!", Toast.LENGTH_SHORT).show();  
  5.             startAnim();  //开始 摇一摇手掌动画  
  6.             mShakeListener.stop();  
  7.             startVibrato(); //开始 震动  
  8.             new Handler().postDelayed(new Runnable(){  
  9.                 @Override  
  10.                 public void run(){  
  11.                     //Toast.makeText(getApplicationContext(), "抱歉,暂时没有找到\n在同一时刻摇一摇的人。\n再试一次吧!", 500).setGravity(Gravity.CENTER,0,0).show();  
  12.                     Toast mtoast;  
  13.                     mtoast = Toast.makeText(getApplicationContext(),  
  14.                              "抱歉,暂时没有找到\n在同一时刻摇一摇的人。\n再试一次吧!"10);  
  15.                            //mtoast.setGravity(Gravity.CENTER, 0, 0);  
  16.                            mtoast.show();  
  17.                            mVibrator.cancel();  
  18.                            mShakeListener.start();  
  19.                 }  
  20.             }, 2000);  
  21.         }  
  22.     });  

在设置监听之前,在Activity的onCreate方法中需呀获得系统提供的振动服务对象

  1. Vibrator mVibrator = (Vibrator)getApplication().getSystemService(VIBRATOR_SERVICE);  
有关Vibrator的使用请看我的另一篇博文:http://blog.csdn.net/dawanganban/article/details/17531697

  1. public void startVibrato(){     //定义震动  
  2.         mVibrator.vibrate( new long[]{500,200,500,200}, -1); //第一个{}里面是节奏数组, 第二个参数是重复次数,-1为不重复,非-1俄日从pattern的指定下标开始重复  
  3.     }  
摇一摇的时候还有一个图片移动的动画,设置动画代码如下:

  1. public void startAnim () {   //定义摇一摇动画动画  
  2.     AnimationSet animup = new AnimationSet(true);  
  3.     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);  
  4.     mytranslateanimup0.setDuration(1000);  
  5.     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);  
  6.     mytranslateanimup1.setDuration(1000);  
  7.     mytranslateanimup1.setStartOffset(1000);  
  8.     animup.addAnimation(mytranslateanimup0);  
  9.     animup.addAnimation(mytranslateanimup1);  
  10.     mImgUp.startAnimation(animup);  
  11.       
  12.     AnimationSet animdn = new AnimationSet(true);  
  13.     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);  
  14.     mytranslateanimdn0.setDuration(1000);  
  15.     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);  
  16.     mytranslateanimdn1.setDuration(1000);  
  17.     mytranslateanimdn1.setStartOffset(1000);  
  18.     animdn.addAnimation(mytranslateanimdn0);  
  19.     animdn.addAnimation(mytranslateanimdn1);  
  20.     mImgDn.startAnimation(animdn);    
  21. }  
运行效果如下:



源代码下载:http://download.csdn.net/detail/lxq_xsyu/6990129

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值