Android实现可随意拖动的悬浮窗体

jopen 10年前

1、在Service中监听电话状态

    package com.example.incomingcall.service;                import android.app.Service;        import android.content.Intent;        import android.graphics.PixelFormat;        import android.os.IBinder;        import android.telephony.PhoneStateListener;        import android.telephony.TelephonyManager;        import android.util.Log;        import android.view.Gravity;        import android.view.MotionEvent;        import android.view.View;        import android.view.View.OnClickListener;        import android.view.View.OnTouchListener;        import android.view.WindowManager;        import android.view.WindowManager.LayoutParams;        import android.widget.Button;        import android.widget.TextView;        import com.example.incomingcall.R;                public class ShowAddressService extends Service {            private static final String TAG = ShowAddressService.class.getSimpleName();            private TelephonyManager tm;            private MyPhoneListener listener;            private WindowManager wm;            private float x;            private float y;                    @Override            public IBinder onBind(Intent intent) {                // TODO Auto-generated method stub                return null;            }                    // 在服务第一次被创建的时候 执行的方法            @Override            public void onCreate() {                super.onCreate();                        Log.e(TAG, "onCreate");                        wm = (WindowManager) getSystemService(WINDOW_SERVICE);                tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);                listener = new MyPhoneListener();                tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);            }                    private class MyPhoneListener extends PhoneStateListener {                private View v;                private String incomingNumber; // 来电号码                private WindowManager.LayoutParams params;                        /**                * 当手机的电话状态发生改变的时候 调用的方法                */                @Override                public void onCallStateChanged(int state, String incomingNumber) {                    switch (state) {                    case TelephonyManager.CALL_STATE_IDLE: // 没有通话,静止状态                                Log.i(TAG, "CALL_STATE_IDLE");                                if (v != null) {                            wm.removeView(v);                            v = null;                        }                                if (this.incomingNumber != null) {                            // 模仿土司 利用窗体的管理服务 把一个布局展现到界面上                            v = View.inflate(getApplicationContext(),                                    R.layout.show_marknumber, null);                                    TextView tv = (TextView) v                                    .findViewById(R.id.tv_mark_number);                            tv.setText("电话:" + this.incomingNumber);                                    Button bt_mark_cancel = (Button) v                                    .findViewById(R.id.bt_mark_cancel);                            bt_mark_cancel.setOnClickListener(new OnClickListener() {                                        @Override                                public void onClick(View view) {                                            Log.i(TAG, "onClick dismiss");                                            if (v != null) {                                        wm.removeView(v);                                        v = null;                                    }                                }                            });                                    params = new LayoutParams();                            params.gravity = Gravity.CENTER;                                    params.height = WindowManager.LayoutParams.WRAP_CONTENT;                            params.width = WindowManager.LayoutParams.WRAP_CONTENT;                            params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL                                    | LayoutParams.FLAG_NOT_FOCUSABLE                                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;                            params.format = PixelFormat.TRANSLUCENT;                            params.type = WindowManager.LayoutParams.TYPE_PHONE;                            params.setTitle("号码标记");                            wm.addView(v, params);                        }                                break;                    case TelephonyManager.CALL_STATE_OFFHOOK: // 电话接通 或者挂断                                Log.i(TAG, "CALL_STATE_OFFHOOK");                                if (v != null) {                            wm.removeView(v);                            v = null;                        }                                break;                    case TelephonyManager.CALL_STATE_RINGING: // 响铃状态                                this.incomingNumber = incomingNumber;                                Log.e(TAG, "CALL_STATE_RINGING incomingNumber:"                                + incomingNumber);                                // 模仿土司 利用窗体的管理服务 把一个布局展现到界面上                        v = View.inflate(getApplicationContext(),                                R.layout.show_address, null);                                TextView tv = (TextView) v.findViewById(R.id.tv_show_address);                        tv.setText("来电:" + incomingNumber);                                params = new LayoutParams();                        params.gravity = Gravity.TOP | Gravity.LEFT;                        params.x = 0;                        params.y = 0;                                params.height = WindowManager.LayoutParams.WRAP_CONTENT;                        params.width = WindowManager.LayoutParams.WRAP_CONTENT;                        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                                |WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;                        params.format = PixelFormat.TRANSLUCENT;                        params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;                        params.setTitle("电话帮");                                v.setOnTouchListener(new OnTouchListener() {                            float mTouchStartX;                            float mTouchStartY;                                    @Override                            public boolean onTouch(View v, MotionEvent event) {                                // 获取相对屏幕的坐标,即以屏幕左上角为原点                                x = event.getRawX();                                y = event.getRawY() - 25; // 25是系统状态栏的高度                                Log.i(TAG, "currX" + x + "====currY" + y);                                switch (event.getAction()) {                                case MotionEvent.ACTION_DOWN:                                    // 获取相对View的坐标,即以此View左上角为原点                                    mTouchStartX = event.getX();                                    mTouchStartY = event.getY();                                            Log.i("startP", "startX" + mTouchStartX                                            + "====startY" + mTouchStartY);                                            break;                                case MotionEvent.ACTION_MOVE:                                    //更新浮动窗口位置参数                                      params.x=(int)( x-mTouchStartX);                                      params.y=(int) (y-mTouchStartY);                                      wm.updateViewLayout(v, params);                                      break;                                        case MotionEvent.ACTION_UP:                                                                        //更新浮动窗口位置参数                                      params.x=(int)( x-mTouchStartX);                                      params.y=(int) (y-mTouchStartY);                                      wm.updateViewLayout(v, params);                                                                          //可以在此记录最后一次的位置                                                                        mTouchStartX = mTouchStartY = 0;                                    break;                                }                                return true;                            }                                });                                                wm.addView(v, params);                                break;                    }                }            }                                /**            * 服务在被停止的时候 调用的方法            */            @Override            public void onDestroy() {                // TODO Auto-generated method stub                super.onDestroy();                // 停止 电话状态的监听.                tm.listen(listener, PhoneStateListener.LISTEN_NONE);            }        }  
2、添加权限
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />            <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  
来自:http://blog.csdn.net/top_code/article/details/12906171