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