今天我们接着昨天的继续

1、实现控制球的点击拖动

2、点击控制球后弹出菜单选择界面

3、菜单选择功能

其实这几个都不难,思路如下:

1、要实现我们的控制球悬浮在所有App界面之上:通过WindowManager来设置App的显示方式

2、控制球的拖动:重写onTouchListener即可,这个相信很多人都做过了

3、弹出菜单界面和菜单选择功能:这个就是一个比较好看的PopupWindow

通过这几条分析,我们可以发现,这个项目其实还是比较简单的哈,所以说,我一直坚信的,思路很重要

下面我们一点点来实现吧:so easy

程序核心必然是一个Service,相信我不要多说了:

MainService:

package com.xys.xtouchassistant.service;

import com.xys.xtouchassistant.R;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

public class MainService extends Service implements OnClickListener, OnTouchListener {

    // 控制球View
    private View touchBallView;
    // 弹出菜单View
    private View menuView;
    // 控制球
    private Button touchBall;
    // WindowManager
    WindowManager wm;
    // WindowManagerParams
    WindowManager.LayoutParams params;
    private PopupWindow popup;
    // 点击坐标
    private float x, y;
    private float touchX, touchY;
    // 移动Flag
    private boolean isMoving;
    // Menu上的组件
    private TextView tvApps;
    private TextView tvHomeScreen;
    private TextView tvSetting;
    private TextView tvLockScreen;
    private TextView tvFavor;

    @Override
    public void onCreate() {
	super.onCreate();
	// 初始化Views
	initView();
	// 显示TouchBall
	createTouchBallView();
	// 监听事件
	regListener();
    }

    /**
     * 监听事件
     */
    private void regListener() {
	touchBall.setOnTouchListener(this);
	touchBall.setOnClickListener(this);
	tvApps.setOnClickListener(this);
	tvHomeScreen.setOnClickListener(this);
	tvSetting.setOnClickListener(this);
	tvLockScreen.setOnClickListener(this);
	tvFavor.setOnClickListener(this);
    }

    /**
     * 初始化Views
     */
    private void initView() {
	// 加载控制球View
	touchBallView = LayoutInflater.from(this).inflate(R.layout.touch_ball, null);
	touchBall = (Button) touchBallView.findViewById(R.id.touch_ball);
	// 初始化MenuView
	menuView = LayoutInflater.from(this).inflate(R.layout.shown_menu, null);
	tvApps = (TextView) menuView.findViewById(R.id.tv_apps);
	tvHomeScreen = (TextView) menuView.findViewById(R.id.tv_home_screen);
	tvSetting = (TextView) menuView.findViewById(R.id.tv_setting);
	tvLockScreen = (TextView) menuView.findViewById(R.id.tv_lock_screen);
	tvFavor = (TextView) menuView.findViewById(R.id.tv_favor);
    }

    /**
     * 显示TouchBall
     */
    private void createTouchBallView() {
	wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
	params = new WindowManager.LayoutParams();
	params.type = WindowManager.LayoutParams.TYPE_PHONE;
	params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
	params.gravity = Gravity.LEFT | Gravity.TOP;
	params.x = 0;
	params.y = 0;
	params.width = WindowManager.LayoutParams.WRAP_CONTENT;
	params.height = WindowManager.LayoutParams.WRAP_CONTENT;
	params.format = PixelFormat.RGBA_8888;
	wm.addView(touchBallView, params);
    }

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

    @Override
    public void onClick(View v) {
	switch (v.getId()) {
	case R.id.touch_ball:
	    // 显示Popup菜单
	    showMenuWindow();
	    break;
	case R.id.tv_apps:
	    // 显示Apps菜单
	    Toast.makeText(this, "APPS", Toast.LENGTH_SHORT).show();
	    popup.dismiss();
	    break;
	case R.id.tv_favor:
	    Toast.makeText(this, "FAVOR", Toast.LENGTH_SHORT).show();
	    popup.dismiss();
	    break;
	case R.id.tv_home_screen:
	    // 显示主菜单
	    Toast.makeText(this, "HOME", Toast.LENGTH_SHORT).show();
	    popup.dismiss();
	    break;
	case R.id.tv_lock_screen:
	    // 锁屏
	    Toast.makeText(this, "LOCK", Toast.LENGTH_SHORT).show();
	    popup.dismiss();
	    break;
	case R.id.tv_setting:
	    // 显示Setting界面
	    Toast.makeText(this, "SETTING", Toast.LENGTH_SHORT).show();
	    popup.dismiss();
	    break;
	default:
	    popup.dismiss();
	    break;
	}
    }

    /**
     * 显示Popup菜单
     */
    private void showMenuWindow() {
	DisplayMetrics dm = getResources().getDisplayMetrics();
	popup = new PopupWindow(menuView, (int) (dm.widthPixels * 0.7), (int) (dm.heightPixels * 0.5));
	Drawable transpent = new ColorDrawable(Color.TRANSPARENT);
	popup.setBackgroundDrawable(transpent);
	popup.setFocusable(true);
	popup.setOutsideTouchable(true);
	popup.showAtLocation(touchBallView, Gravity.CENTER, 0, 0);
	popup.update();
    }

    /**
     * Touch监听事件
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
	x = event.getRawX();
	y = event.getRawY();
	// 触摸事件
	switch (event.getAction()) {
	case MotionEvent.ACTION_DOWN:
	    isMoving = false;
	    // 触摸坐标赋值
	    touchX = event.getX();
	    touchY = event.getY();
	    break;
	case MotionEvent.ACTION_MOVE:
	    isMoving = true;
	    // 触摸坐标赋值
	    params.x = (int) (x - touchX);
	    params.y = (int) (y - touchY);
	    wm.updateViewLayout(touchBallView, params);
	    break;
	case MotionEvent.ACTION_UP:
	    // 触摸坐标赋值
	    touchX = touchY = 0;
	    break;
	default:
	    break;
	}
	if (isMoving) {
	    return true;
	} else {
	    return false;
	}
    }
}

开启Service的主程序:

MainActivity:

package com.xys.xtouchassistant.activity;

import com.xys.xtouchassistant.R;
import com.xys.xtouchassistant.service.MainService;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	Intent service = new Intent();
	service.setClass(this, MainService.class);
	startService(service);
    }
}

这里只是简单的用一个Activity去开启这个服务,后面我们会重新实现开启服务的方法:

1、通过注册一个开机广播事件去开启我们的服务

2、通过进程守护来实现我们的Service不被kill(也可以通过在通知面板显式显示服务的方式来防止被kill)

3、实现菜单界面功能的可配置化


ps:需要源码的请留意哦