Android仿IOS的AssistiveTouch的控件EasyTouch实现

来源:互联网 发布:淘宝上如何交电费 编辑:程序博客网 时间:2024/05/22 09:03

概述:

  之前我听到过一则新闻,就是说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:

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:

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中启动这个设置设备管理器的界面。


代码如下:

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

0 0
原创粉丝点击