仿iPhone的AssistiveTouch 懸浮輔助球工具

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



拖動小圓球:



點擊彈出pop窗口:



爲了讓輔助工具一直懸浮在窗口之上,這裏使用的機制是通過在程序初始化是,啓動一個service,在service的onCreate() 函數中使用LayoutInflater來加載一個view,而這個view就是輔助球的佈局文件:floatball.xml,然後對它進行onclick事件的監聽,setOnClickListener監聽到輔助球點擊事件之後,就創建一個PopupWindow,彈出如上的菜單界面,大體的實現就是這樣。

其實,實現窗口懸浮於最前面的一個重要屬性是:WindowManager.LayoutParams.TYPE_PHONE

我們只要將WindowManager.LayoutParams的type屬性設置爲 WindowManager.LayoutParams.TYPE_PHONE就可以實現懸浮最前面。


工程目錄結構:



部分代碼解析:

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.content.Intent;
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.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.tyd.floatball.R;
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;
	
	@Override
	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();
					break;
				case MotionEvent.ACTION_UP:
					mTouchStartX = mTouchStartY = 0;
					break;
				}
				//如果拖動則返回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);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	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();
			}
			break;
		}
		
	}

	@Override
	public boolean onKey(View v, int keyCode, KeyEvent event) {
		Toast.makeText(getApplicationContext(), "keyCode:"+keyCode, 1000).show();
		switch (keyCode) {
		case KeyEvent.KEYCODE_HOME:
			pop.dismiss();
			break;
		default:
			break;
		}
		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:

<?xml version="1.0" encoding="utf-8"?>
<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" />

            <TextView
                android:id="@+id/btn_home_screen"
                style="@style/Icon"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:drawableTop="@drawable/selector_ic_home"
                android:text="@string/home_screen" />

            <TextView
                android:id="@+id/btn_setting"
                style="@style/Icon"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:drawableTop="@drawable/selector_ic_phone"
                android:text="@string/setting" />

            <TextView
                android:id="@+id/btn_lock_screen"
                style="@style/Icon"
                android:layout_centerHorizontal="true"
                android:drawableTop="@drawable/selector_ic_power_down"
                android:text="@string/lock_screen" />

            <TextView
                android:id="@+id/btn_favor"
                style="@style/Icon"
                android:layout_alignParentLeft="true"
                android:layout_centerVertical="true"
                android:drawableTop="@drawable/selector_ic_star"
                android:text="@string/favor" />
        </RelativeLayout>
    </LinearLayout>

</RelativeLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章