自定义可拖动土司

来源:互联网 发布:鲸鱼死后爆炸知乎 编辑:程序博客网 时间:2024/04/30 02:06

一、自定义可拖动土司代码如下:

总的来说:显示Toast就是把一个view添加到window中,去掉Toast就是把一个view从window中移除,因为window不是Activity,所以程序存不存在都不影响Toast的显示。

1、成员变量

private WindowManager.LayoutParams params;private WindowManager wm;private View view;

2、参数及成员初始化

@Overridepublic void onCreate() {    // 初始化窗体管理器    wm = (WindowManager) getSystemService(WINDOW_SERVICE);    // 初始化土司的参数    initToastParams();    super.onCreate();}

3、初始化土司的参数

private void initToastParams() {    // TODO Auto-generated method stub    // XXX This should be changed to use a Dialog, with a Theme.Toast    // defined that sets up the layout params appropriately.    // 土司的初始化参数    params = new WindowManager.LayoutParams();    params.height = WindowManager.LayoutParams.WRAP_CONTENT;    params.width = WindowManager.LayoutParams.WRAP_CONTENT;    //对齐方式左上角     params.gravity = Gravity.LEFT | Gravity.TOP;    params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE    /* | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE */    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;    params.format = PixelFormat.TRANSLUCENT;    //初始化土司的位置(从sp中取)    //params.x = (int) Float.parseFloat(SpTools.getString(getApplicationContext(), MyConstants.TOASTX, "0"));    //params.y = (int) Float.parseFloat(SpTools.getString(getApplicationContext(), MyConstants.TOASTY, "0"));    params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;// 土司天生不相应事件,改变类型    params.setTitle("Toast");}

4、显示土司

/** * 显示土司 *  * @param incomingNumber *            电话号码 */protected void showLocationToast(String incomingNumber) {    // 土司显示的view    view = View.inflate(getApplicationContext(), R.layout.sys_toast, null);    TextView tv_location = (TextView) view            .findViewById(R.id.tv_toast_location);    tv_location.setText(PhoneLocationEngine.locationQuery(incomingNumber,            getApplicationContext()));    // 初始化view的触摸事件    view.setOnTouchListener(new OnTouchListener() {        private float startX;        private float startY;        @Override        public boolean onTouch(View v, MotionEvent event) {            System.out.println(event.getX() + ":" + event.getRawX());            // 拖动土司            switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:// 按下                startX = event.getRawX();                startY = event.getRawY();                break;            case MotionEvent.ACTION_MOVE:// 按下移动,拖动                //新的 x  y坐标                float moveX = event.getRawX();//移动后的x坐标                float moveY = event.getRawY();//移动后的x坐标                //dx x方向的位置变化值 dy y方向的位置变化值                float dx = moveX - startX;                float dy = moveY - startY;                //改变土司的坐标                params.x += dx;                params.y += dy;                //重新获取新的x y坐标                startX = moveX;                startY = moveY;                //更新土司的位置                wm.updateViewLayout(view, params);                break;            case MotionEvent.ACTION_UP:// 松开                //解决左右边界滑出多次后,要拉多次才能拖动的问题                if (params.x < 0) {                    params.x = 0;                } else if (params.x + view.getWidth() > wm.getDefaultDisplay().getWidth()) {                    params.x =  wm.getDefaultDisplay().getWidth() - view.getWidth();                }                if (params.y < 0) {                    params.y = 0;                } else if (params.y + view.getHeight() > wm.getDefaultDisplay().getHeight()) {                    params.y = wm.getDefaultDisplay().getHeight() - view.getHeight();                }                //记录当前土司位置,把x y坐标值保存到sp中                //SpTools.putString(getApplicationContext(), MyConstants.TOASTX, params.x + "");                //SpTools.putString(getApplicationContext(), MyConstants.TOASTY, params.y + "");            default:                break;            }            return false;        }    });    wm.addView(view, params);}

5、关闭土司

/** * 关闭土司 */protected void closeLocationToast() {    // TODO Auto-generated method stub    // 初始先执行一次    if (view != null) {        wm.removeView(view);        view = null;// 删除完 置为null    }}

6、清单文件中添加权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

二、Toast源码及分析如下:

自定义土司

分析:看系统的Toast是怎么做出来

1,看Toast的源码

   a, makeText方法        //构造土司对象,创建TN的实例 mTN = new TN();        Toast result = new Toast(context);        LayoutInflater inflate = (LayoutInflater)                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);        //土司显示的文本框        TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);        tv.setText(text);        result.mNextView = v;//把当前土司的view给mNextView属性        result.mDuration = duration;//土司显示的时长        return result;   b,show方法        if (mNextView == null) {            throw new RuntimeException("setView must have been called");        }        INotificationManager service = getService();        String pkg = mContext.getPackageName();        TN tn = mTN;        tn.mNextView = mNextView;        try {            service.enqueueToast(pkg, tn, mDuration);        } catch (RemoteException e) {            // Empty        }   c, TN的源代码    TN的构造函数: 初始化LayoutParams    TN() {          // XXX This should be changed to use a Dialog, with a Theme.Toast          // defined that sets up the layout params appropriately.          final WindowManager.LayoutParams params = mParams;          params.height = WindowManager.LayoutParams.WRAP_CONTENT;          params.width = WindowManager.LayoutParams.WRAP_CONTENT;          params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                  | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE                  | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;          params.format = PixelFormat.TRANSLUCENT;          params.windowAnimations = com.android.internal.R.style.Animation_Toast;          params.type = WindowManager.LayoutParams.TYPE_TOAST;          params.setTitle("Toast");        }    显示土司的代码:     public void handleShow() {        if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView                + " mNextView=" + mNextView);        if (mView != mNextView) {            // remove the old view if necessary            handleHide();            mView = mNextView;            mWM = WindowManagerImpl.getDefault();            final int gravity = mGravity;            mParams.gravity = gravity;            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {                mParams.horizontalWeight = 1.0f;            }            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {                mParams.verticalWeight = 1.0f;            }            mParams.x = mX;            mParams.y = mY;            mParams.verticalMargin = mVerticalMargin;            mParams.horizontalMargin = mHorizontalMargin;            if (mView.getParent() != null) {                if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);                mWM.removeView(mView);            }            if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);            //土司显示的真正代码            mWM.addView(mView, mParams);            trySendAccessibilityEvent();        }    }

2,分析结果(怎么添加toast):

 土司是加载到WindowManager中  mView 土司显示的View  mParams 土司在windowmanager中显示的参数配置  mWM.addView(mView, mParams);

3,拖动土司

 前提:      去掉 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE      改变Toast类型,params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;//土司天生不相应事件,改变类型 给Toast加触摸事件      view.setOnTouchLi......
自定义toast的参数
// 土司的初始化参数    params = new WindowManager.LayoutParams();    ;    params.height = WindowManager.LayoutParams.WRAP_CONTENT;    params.width = WindowManager.LayoutParams.WRAP_CONTENT;    //对齐方式左上角     params.gravity = Gravity.LEFT | Gravity.TOP;    params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE    /* | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE */    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;    params.format = PixelFormat.TRANSLUCENT;    //初始化土司的位置    params.x = (int) Float.parseFloat(SpTools.getString(getApplicationContext(), MyConstants.TOASTX, "0"));    params.y = (int) Float.parseFloat(SpTools.getString(getApplicationContext(), MyConstants.TOASTY, "0"));    params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;// 土司天生不相应时间,改变类型    params.setTitle("Toast");
0 0
原创粉丝点击