天天看點

仿iphone快速導航懸浮球

用過iphone的朋友都知道,iphone有個圓球輔助工具,它漂浮在你的手機螢幕(在任何app之上),你可以将它移動到任何地方,它叫做assistivetouch,本篇模拟該軟體實作一個小案例,主要是實作它的界面,首先來看看實作的效果吧:

仿iphone快速導航懸浮球

拖動小圓球:

仿iphone快速導航懸浮球

點選彈出pop視窗:

仿iphone快速導航懸浮球

為了讓輔助工具一直懸浮在視窗之上,這裡使用的機制是通過在程式初始化是,啟動一個service,在service的oncreate() 函數中使用layoutinflater來加載一個view,而這個view就是輔助球的布局檔案:floatball.xml,然後對它進行onclick事件的監聽,setonclicklistener監聽到輔助球點選事件之後,就建立一個popupwindow,彈出如上的菜單界面,大體的實作就是這樣。

其實,實作視窗懸浮于最前面的一個重要屬性是:windowmanager.layoutparams.type_phone

我們隻要将windowmanager.layoutparams的type屬性設定為 windowmanager.layoutparams.type_phone就可以實作懸浮最前面。

工程目錄結構:

仿iphone快速導航懸浮球

部分代碼解析:

myapplication.java:

package com.tyd.floatball.util;  

import android.app.application;  

import android.view.windowmanager;  

public class myapplication extends application {  

    private windowmanager.layoutparams wmparams = new windowmanager.layoutparams();  

    public windowmanager.layoutparams getmywmparams() {  

        return wmparams;  

    }  

}  

mainactivity.java:

package com.tyd.floatball.ui;  

import com.tyd.floatball.r;  

import com.tyd.floatball.r.layout;  

import com.tyd.floatball.service.topfloatservice;  

import android.app.activity;  

import android.content.intent;  

import android.os.bundle;  

public class mainactivity extends activity {  

    @override  

    public void oncreate(bundle savedinstancestate) {  

        super.oncreate(savedinstancestate);  

        setcontentview(r.layout.main);  

        intent service = new intent();  

        service.setclass(this, topfloatservice.class);  

        //啟動服務  

        startservice(service);  

topfloatservice.java:

package com.tyd.floatball.service;  

import android.app.service;  

import android.graphics.pixelformat;  

import android.graphics.rect;  

import android.graphics.drawable.bitmapdrawable;  

import android.os.ibinder;  

import android.util.displaymetrics;  

import android.view.gravity;  

import android.view.keyevent;  

import android.view.layoutinflater;  

import android.view.motionevent;  

import android.view.view;  

import android.view.view.onclicklistener;  

import android.view.view.onkeylistener;  

import android.view.view.ontouchlistener;  

import android.widget.button;  

import android.widget.linearlayout;  

import android.widget.popupwindow;  

import android.widget.relativelayout;  

import android.widget.toast;  

import com.tyd.floatball.util.myapplication;  

public class topfloatservice extends service implements onclicklistener,onkeylistener{  

    windowmanager wm = null;  

    windowmanager.layoutparams ballwmparams = null;  

    private view ballview;  

    private view menuview;  

    private float mtouchstartx;  

    private float mtouchstarty;  

    private float x;  

    private float y;  

    private relativelayout menulayout;  

    private button floatimage;  

    private popupwindow pop;  

    private relativelayout menutop;  

    private boolean ismoving = false;  

    public void oncreate() {  

        super.oncreate();  

        //加載輔助球布局  

        ballview = layoutinflater.from(this).inflate(r.layout.floatball, null);  

        floatimage = (button)ballview.findviewbyid(r.id.float_image);  

        setupfloatmenuview();  

        createview();  

    /**  

     * 視窗菜單初始化  

     */  

    private void setupfloatmenuview(){  

        menuview = layoutinflater.from(this).inflate(r.layout.floatmenu, null);  

        menulayout = (relativelayout)menuview.findviewbyid(r.id.menu);  

        menutop = (relativelayout)menuview.findviewbyid(r.id.lay_main);  

        menulayout.setonclicklistener(this);  

        menulayout.setonkeylistener(this);  

        menutop.setonclicklistener(this);  

     * 通過myapplication建立view,并初始化顯示參數  

    private void createview() {  

        wm = (windowmanager) getapplicationcontext().getsystemservice("window");  

        ballwmparams =  ((myapplication) getapplication()).getmywmparams();  

        ballwmparams.type = windowmanager.layoutparams.type_phone;  

        ballwmparams.flags |= windowmanager.layoutparams.flag_not_focusable;  

        ballwmparams.gravity = gravity.left | gravity.top;  

        ballwmparams.x = 0;  

        ballwmparams.y = 0;  

        ballwmparams.width = windowmanager.layoutparams.wrap_content;  

        ballwmparams.height = windowmanager.layoutparams.wrap_content;  

        ballwmparams.format = pixelformat.rgba_8888;  

        //添加顯示層  

        wm.addview(ballview, ballwmparams);  

        //注冊觸碰事件監聽器  

        floatimage.setontouchlistener(new ontouchlistener() {  

            public boolean ontouch(view v, motionevent event) {  

                x = event.getrawx();  

                y = event.getrawy();   

                switch (event.getaction()) {  

                case motionevent.action_down:  

                    ismoving = false;  

                    mtouchstartx = (int)event.getx();  

                    mtouchstarty = (int)event.gety();  

                    break;  

                case motionevent.action_move:  

                    ismoving = true;  

                    updateviewposition();  

                case motionevent.action_up:  

                    mtouchstartx = mtouchstarty = 0;  

                }  

                //如果拖動則傳回false,否則傳回true  

                if(ismoving == false){  

                    return false;  

                }else{  

                    return true;  

            }  

        });  

        //注冊點選事件監聽器  

        floatimage.setonclicklistener(new view.onclicklistener() {  

            @override  

            public void onclick(view v) {  

                displaymetrics dm = getresources().getdisplaymetrics();  

                pop = new popupwindow(menuview, dm.widthpixels, dm.heightpixels);  

                pop.showatlocation(ballview, gravity.center, 0, 0);  

                pop.update();  

     * 更新view的顯示位置  

    private void updateviewposition() {  

        ballwmparams.x = (int) (x - mtouchstartx);  

        ballwmparams.y = (int) (y - mtouchstarty);  

        wm.updateviewlayout(ballview, ballwmparams);  

    public ibinder onbind(intent intent) {  

        return null;  

    public void onclick(view v) {  

        switch (v.getid()) {  

        case r.id.lay_main:  

            toast.maketext(getapplicationcontext(), "111", 1000).show();  

            break;  

        default:  

            if(pop!=null && pop.isshowing()){  

                pop.dismiss();  

        }  

    public boolean onkey(view v, int keycode, keyevent event) {  

        toast.maketext(getapplicationcontext(), "keycode:"+keycode, 1000).show();  

        switch (keycode) {  

        case keyevent.keycode_home:  

            pop.dismiss();  

        return true;  

輔助球的布局檔案 floatball.xml:

<?xml version="1.0" encoding="utf-8"?>  

<framelayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:layout_width="match_parent"  

    android:layout_height="wrap_content"  

    android:orientation="vertical"  

    android:layout_gravity="center_vertical">  

    <button  

        android:id="@+id/float_image"  

        android:layout_width="50dp"  

        android:layout_height="50dp"  

        android:background="@drawable/selector_btn_assistive"   

        />  

</framelayout>  

視窗菜單的布局檔案floatmenu.xml:

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:id="@+id/menu"  

    android:layout_width="fill_parent"  

    android:layout_height="fill_parent"  

    android:background="@drawable/transparent" >  

    <linearlayout  

        android:layout_width="@dimen/size_dialog"  

        android:layout_height="@dimen/size_dialog"  

        android:layout_centerinparent="true"  

        android:background="@drawable/shape_background_assistivetouch"  

        android:orientation="vertical" >  

        <relativelayout  

            android:id="@+id/lay_main"  

            android:layout_width="fill_parent"  

            android:layout_height="fill_parent"  

            android:orientation="vertical"  

            android:padding="4.0px"  

            android:visibility="visible" >  

            <textview  

                android:id="@+id/btn_apps"  

                style="@style/icon"  

                android:layout_centerinparent="true"  

                android:drawabletop="@drawable/selector_ic_apps"  

                android:text="@string/apps" />  

                android:id="@+id/btn_home_screen"  

                android:layout_alignparentbottom="true"  

                android:layout_centerhorizontal="true"  

                android:drawabletop="@drawable/selector_ic_home"  

                android:text="@string/home_screen" />  

                android:id="@+id/btn_setting"  

                android:layout_alignparentright="true"  

                android:layout_centervertical="true"  

                android:drawabletop="@drawable/selector_ic_phone"  

                android:text="@string/setting" />  

                android:id="@+id/btn_lock_screen"  

                android:drawabletop="@drawable/selector_ic_power_down"  

                android:text="@string/lock_screen" />  

                android:id="@+id/btn_favor"  

                android:layout_alignparentleft="true"  

                android:drawabletop="@drawable/selector_ic_star"  

                android:text="@string/favor" />  

        </relativelayout>  

    </linearlayout>  

</relativelayout>  

androidmanifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  

    package="com.tyd.floatball"  

    android:versioncode="1"  

    android:versionname="1.0" >  

    <uses-sdk android:minsdkversion="14" />  

    <application  

        android:icon="@drawable/ic_launcher"  

        android:label="@string/app_name"   

        android:name=".util.myapplication">  

        <activity  

            android:label="@string/app_name"  

            android:name=".ui.mainactivity" >  

            <intent-filter >  

                <action android:name="android.intent.action.main" />  

                <category android:name="android.intent.category.launcher" />  

            </intent-filter>  

        </activity>  

        <service   

                android:name=".service.topfloatservice"    

                android:enabled="true"  

                android:exported="true"  

            />  

    </application>  

    <uses-permission android:name="android.permission.system_alert_window" />  

    <uses-permission android:name="android.permission.disable_keyguard"/>  

</manifest>  

該執行個體我已經将源碼整理打包,進行了上傳,下面是資源的下載下傳位址:

http://download.csdn.net/detail/wulianghuan/5364129

繼續閱讀