您的位置:首页 > 移动开发 > Android开发

Android仿IOS的AssistiveTouch的控件EasyTouch实现

2016-12-08 14:49 369 查看


概述:

之前我听到过一则新闻,就是说Ipone中的AssistiveTouch的设计初衷是给残疾人使用的。而这一功能在亚洲(中国)的使用最为频繁。

虽不知道这新闻的可靠性,但无庸置疑的是它的确给我们操作手机带来了很大的便捷。在这个设计之前,可能比较容易想到的就是建立快捷方式,而快捷方式的操作结果还是要去加载界面(有时可能是繁重的界面)。一旦走上了这条路,那距离快捷操作的方向可能就渐行渐远了。

AssistiveTouch的设计的确很赞。Android也是值得拥有这一棒棒的功能,下面我就来简单说明一下在Android上要如何实现这一功能。


思路整理:

一眼看到这样的功能,我们可能困惑的是在Android中要怎么在系统桌面的上方添加控件。是的,这是一个难点。从大小上,可能你想到了Dialog,不过Android中的Dialog可不能在系统的桌面上显示。那你可能又会说不是一种是针对Activity的Dialog主题的模式吗?是的,这样的确是解决了在系统桌面的上方弹出窗口了。可是,我们又要对控件进行随意拖拽,这一点可能对于Android而言并非易事。

但是,Android中允许我们在WindowManager上添加View。Android中的窗口机制就是基于WindowManager实现的。WindowManager的作用就是添加View到屏幕,或是从屏幕中移除View。它是显示View的最底层。

好了,的确是这样的。WindowManger就是实现的关键。下面就来实现它吧。

不过还有一点需要注意,就我们的EasyTouchView是要基于一个常在的Context来创建,如果EasyTouchView基于了像Activity这样的短生命周期的Context创建,那么EasyTouchView就会很快随着Activity的暂停或是销毁而消失。


实现过程:

EasyTouchView:

[java] view
plain copy

print?

package com.bumblebee.remindeasy.widgets;

import java.util.Timer;

import java.util.TimerTask;

import com.bumblebee.remindeasy.R;

import android.content.Context;

import android.graphics.Color;

import android.graphics.drawable.BitmapDrawable;

import android.os.Handler;

import android.os.Message;

import android.view.Gravity;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.WindowManager;

import android.view.WindowManager.LayoutParams;

import android.widget.Button;

import android.widget.ImageView;

import android.widget.PopupWindow;

import android.widget.Toast;

public class EasyTouchView extends View {

private Context mContext;

private WindowManager mWManager;

private WindowManager.LayoutParams mWMParams;

private View mTouchView;

private ImageView mIconImageView = null;

private PopupWindow mPopuWin;

private ServiceListener mSerLisrener;

private View mSettingTable;

private int mTag = 0;

private int midX;

private int midY;

private int mOldOffsetX;

private int mOldOffsetY;

private Toast mToast;

private Timer mTimer = null;

private TimerTask mTask = null;

public EasyTouchView(Context context, ServiceListener listener) {

super(context);

mContext = context;

mSerLisrener = listener;

}

public void initTouchViewEvent() {

initEasyTouchViewEvent();

initSettingTableView();

}

private void initEasyTouchViewEvent() {

// 设置载入view WindowManager参数

mWManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

midX = mWManager.getDefaultDisplay().getWidth() / 2 - 25;

midY = mWManager.getDefaultDisplay().getHeight() / 2 - 44;

mTouchView = LayoutInflater.from(mContext).inflate(R.layout.easy_touch_view, null);

mIconImageView = (ImageView) mTouchView.findViewById(R.id.easy_touch_view_imageview);

mTouchView.setBackgroundColor(Color.TRANSPARENT);

mTouchView.setOnTouchListener(mTouchListener);

WindowManager wm = mWManager;

WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();

mWMParams = wmParams;

wmParams.type = 2003; // 这里的2002表示系统级窗口,你也可以试试2003。

wmParams.flags = 40; // 设置桌面可控

wmParams.width = 100;

wmParams.height = 100;

wmParams.format = -3; // 透明

wm.addView(mTouchView, wmParams);

}

private void initSettingTableView() {

mSettingTable = LayoutInflater.from(mContext).inflate(R.layout.show_setting_table, null);

Button commonUseButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_common_use_button);

Button screenLockButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_screen_lock_button);

Button notificationButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_notification_button);

Button phoneButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_phone_button);

Button pageButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_page_button);

Button cameraButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_camera_button);

Button backButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_back_button);

Button homeButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_home_button);

Button exitTouchButton = (Button) mSettingTable.findViewById(R.id.show_setting_table_item_exit_touch_button);

commonUseButton.setOnClickListener(mClickListener);

screenLockButton.setOnClickListener(mClickListener);

notificationButton.setOnClickListener(mClickListener);

phoneButton.setOnClickListener(mClickListener);

pageButton.setOnClickListener(mClickListener);

cameraButton.setOnClickListener(mClickListener);

backButton.setOnClickListener(mClickListener);

homeButton.setOnClickListener(mClickListener);

exitTouchButton.setOnClickListener(mClickListener);

}

private OnClickListener mClickListener = new OnClickListener() {

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.show_setting_table_item_common_use_button:

hideSettingTable("常用");

break;

case R.id.show_setting_table_item_screen_lock_button:

hideSettingTable("锁屏");

break;

case R.id.show_setting_table_item_notification_button:

hideSettingTable("通知");

break;

case R.id.show_setting_table_item_phone_button:

hideSettingTable("电话");

break;

case R.id.show_setting_table_item_page_button:

hideSettingTable("1");

break;

case R.id.show_setting_table_item_camera_button:

hideSettingTable("相机");

break;

case R.id.show_setting_table_item_back_button:

hideSettingTable("返回");

break;

case R.id.show_setting_table_item_home_button:

hideSettingTable("主页");

break;

case R.id.show_setting_table_item_exit_touch_button:

quitTouchView();

break;

}

}

};

private void quitTouchView() {

hideSettingTable("退出");

mWManager.removeView(mTouchView);

mSerLisrener.OnCloseService(true);

clearTimerThead();

}

private OnTouchListener mTouchListener = new OnTouchListener() {

float lastX, lastY;

int paramX, paramY;

public boolean onTouch(View v, MotionEvent event) {

final int action = event.getAction();

float x = event.getRawX();

float y = event.getRawY();

if (mTag == 0) {

mOldOffsetX = mWMParams.x; // 偏移量

mOldOffsetY = mWMParams.y; // 偏移量

}

switch (action) {

case MotionEvent.ACTION_DOWN:

motionActionDownEvent(x, y);

break;

case MotionEvent.ACTION_MOVE:

motionActionMoveEvent(x, y);

break;

case MotionEvent.ACTION_UP:

motionActionUpEvent(x, y);

break;

default:

break;

}

return true;

}

private void motionActionDownEvent(float x, float y) {

lastX = x;

lastY = y;

paramX = mWMParams.x;

paramY = mWMParams.y;

}

private void motionActionMoveEvent(float x, float y) {

int dx = (int) (x - lastX);

int dy = (int) (y - lastY);

mWMParams.x = paramX + dx;

mWMParams.y = paramY + dy;

mTag = 1;

// 更新悬浮窗位置

mWManager.updateViewLayout(mTouchView, mWMParams);

}

private void motionActionUpEvent(float x, float y) {

int newOffsetX = mWMParams.x;

int newOffsetY = mWMParams.y;

if (mOldOffsetX == newOffsetX && mOldOffsetY == newOffsetY) {

mPopuWin = new PopupWindow(mSettingTable, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

mPopuWin.setTouchInterceptor(new OnTouchListener() {

public boolean onTouch(View v, MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {

hideSettingTable();

return true;

}

return false;

}

});

mPopuWin.setBackgroundDrawable(new BitmapDrawable());

mPopuWin.setTouchable(true);

mPopuWin.setFocusable(true);

mPopuWin.setOutsideTouchable(true);

mPopuWin.setContentView(mSettingTable);

if (Math.abs(mOldOffsetX) > midX) {

if (mOldOffsetX > 0) {

mOldOffsetX = midX;

} else {

mOldOffsetX = -midX;

}

}

if (Math.abs(mOldOffsetY) > midY) {

if (mOldOffsetY > 0) {

mOldOffsetY = midY;

} else {

mOldOffsetY = -midY;

}

}

mPopuWin.setAnimationStyle(R.style.AnimationPreview);

mPopuWin.setFocusable(true);

mPopuWin.update();

mPopuWin.showAtLocation(mTouchView, Gravity.CENTER, -mOldOffsetX, -mOldOffsetY);

if (mTimer == null) {

catchSettingTableDismiss();

}

} else {

mTag = 0;

}

}

};

private void catchSettingTableDismiss() {

mTimer = new Timer();

mTask = new TimerTask() {

@Override

public void run() {

if (mPopuWin == null || !mPopuWin.isShowing()) {

handler.sendEmptyMessage(0x0);

} else {

handler.sendEmptyMessage(0x1);

}

}

};

mTimer.schedule(mTask, 0, 100);

}

private void clearTimerThead() {

if (mTask != null) {

mTask.cancel();

mTask = null;

}

if (mTimer != null) {

mTimer.cancel();

mTimer = null;

}

}

Handler handler = new Handler() {

public void handleMessage(Message msg) {

if (msg.what == 0x0) {

mIconImageView.setBackgroundDrawable(getResources().getDrawable(R.drawable.touch_ic));

} else if (msg.what == 0x1) {

mIconImageView.setBackgroundDrawable(getResources().getDrawable(R.drawable.transparent));

}

};

};

public void showToast(Context context, String text) {

if (mToast == null) {

mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT);

} else {

mToast.setText(text);

mToast.setDuration(Toast.LENGTH_SHORT);

}

mToast.show();

}

private void hideSettingTable(String content) {

hideSettingTable();

showToast(mContext, content);

}

private void hideSettingTable() {

if (null != mPopuWin) {

mPopuWin.dismiss();

}

}

public interface ServiceListener {

public void OnCloseService(boolean isClose);

}

}

AuxiliaryService:

[java] view
plain copy

print?

public class AuxiliaryService extends Service implements ServiceListener {

private Intent mIntent;

@Override

public IBinder onBind(Intent intent) {

return null;

}

public void onCreate() {

super.onCreate();

new EasyTouchView(this, this).initTouchViewEvent();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

mIntent = intent;

return super.onStartCommand(intent, flags, startId);

}

@Override

public void OnCloseService(boolean isClose) {

stopService(mIntent);

}

}

这里有一点需要注意一下。大家可以通过上面的代码看出,我们启动EasyTouchView是通过Service来启动的。一般的EasyTouch都会提供一个锁屏的功能。要使用一键锁屏就需要激活设备管理器,就要去跳转到系统的一些界面,而这些界面的启动不可以是基于Service的,需要基于Activity来做处理。基于Service启动的过程是闪烁一下后就消失了。

这里我们可以在Service中启动一个我们自己的Activity,然后在这个Activity中启动这个设置设备管理器的界面。

代码如下:

[java] view
plain copy

print?

public class AuxiliaryActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

lockScreen();

}

private void lockScreen() {

DevicePolicyManager mDevicePolicyManager;

ComponentName mComponentName;

mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

mComponentName = new ComponentName(this, LockReceiver.class);

// 判断是否有权限

if (mDevicePolicyManager.isAdminActive(mComponentName)) {

mDevicePolicyManager.lockNow();

finish();

} else {

activeManager(mComponentName);

}

}

/**

* 激活设备管理器获取权限

*/

private void activeManager(ComponentName componentName) {

Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);

intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);

intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "One key lock the screen");

startActivity(intent);

finish();

}

}


效果图:



TouchView



ShowTableView


代码下载:

http://download.csdn.NET/detail/u013761665/8894583
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: