Android實現可隨意拖動的懸浮窗體

jopen 10年前發布 | 50K 次閱讀 Android Android開發 移動開發

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);  
    }  
}  </pre><strong><span style="color:#3333ff;font-size:14px;">2、添加權限<pre class="brush:java; toolbar: true; auto-links: false;">    <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  </pre></span></strong>來自:http://blog.csdn.net/top_code/article/details/12906171
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!