天天看點

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

繼續閱讀