天天看点

Android 高仿微信界面

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

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

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

Android 高仿微信界面

布局文件如下:

<?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();  

坐标对应的关系看下图可知

Android 高仿微信界面

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

double speed = math.sqrt(deltax * deltax + deltay * deltay + deltaz  

Android 高仿微信界面

在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);    

运行效果如下:

Android 高仿微信界面

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

继续阅读