仿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


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