仿iPhone的AssistiveTouch 悬浮辅助球工具

用过iphone的朋友都知道,iPhone有个圆球辅助工具,它漂浮在你的手机屏幕(在任何APP之上),你可以将它移动到任何地方,它叫做AssistiveTouch,本篇模拟该软件实现一个小案例,主要是实现它的界面,首先来看看实现的效果吧:

仿iPhone的AssistiveTouch 悬浮辅助球工具_第1张图片


拖动小圆球:

仿iPhone的AssistiveTouch 悬浮辅助球工具_第2张图片


点击弹出pop窗口:

仿iPhone的AssistiveTouch 悬浮辅助球工具_第3张图片


为了让辅助工具一直悬浮在窗口之上,这里使用的机制是通过在程序初始化是,启动一个service,在service的onCreate() 函数中使用LayoutInflater来加载一个view,而这个view就是辅助球的布局文件:floatball.xml,然后对它进行onclick事件的监听,setOnClickListener监听到辅助球点击事件之后,就创建一个PopupWindow,弹出如上的菜单界面,大体的实现就是这样。

其实,实现窗口悬浮于最前面的一个重要属性是:WindowManager.LayoutParams.TYPE_PHONE

我们只要将WindowManager.LayoutParams的type属性设置为 WindowManager.LayoutParams.TYPE_PHONE就可以实现悬浮最前面。


工程目录结构:

仿iPhone的AssistiveTouch 悬浮辅助球工具_第4张图片


部分代码解析:

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:



	
    

窗口菜单的布局文件floatmenu.xml:




    

        

            

            

            

            

            
        
    


AndroidManifest.xml:



    

    
        
            
                

                
            
        
        
    
    
	
	


该实例我已经将源码整理打包,进行了上传,下面是资源的下载地址:

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


你可能感兴趣的:(小项目)