先看效果 未擴充 擴充後 代碼說明 AndroidManifest..xml [html] <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.hpc.assistant" android:versionCode="1" android:versionName="1.0" > <!--需要下面的許可權--> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" /> <uses-permission android:name="android.permission.GET_TASKS" /> <application android:name=".FloatApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="cn.hpc.assistant.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> App 類 [java] package cn.hpc.assistant; import android.app.Application; import android.view.WindowManager; public class FloatApplication extends Application { private WindowManager.LayoutParams wmParams=new WindowManager.LayoutParams(); public WindowManager.LayoutParams getWmParams(){ return wmParams; } } MainActivity 類 [java] package cn.hpc.assistant; import android.app.Activity; import android.content.Context; import android.graphics.PixelFormat; import android.graphics.Point; import android.os.Bundle; import android.view.Gravity; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; public class MainActivity extends Activity { private WindowManager wm = null; private WindowManager.LayoutParams wmParams = null; private FloatFrame myFV = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 建立懸浮視窗 createFloatView(); this.finish(); // 顯示懸浮視窗後,Activity自動結束 } private void createFloatView() { Point windowSize = new Point(); this.getWindowManager().getDefaultDisplay().getSize(windowSize); myFV = new FloatFrame(getApplicationContext()); // 擷取WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); // 設定LayoutParams(全域變數)相關參數 wmParams = ((FloatApplication) getApplication()).getWmParams(); /** * 以下都是WindowManager.LayoutParams的相關屬性 具體用途可參考SDK文檔 */ wmParams.type = 2003;//LayoutParams.TYPE_PHONE; // 設定window type wmParams.format = PixelFormat.RGBA_8888; // 設定圖片格式,效果為背景透明 // 設定Window flag wmParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; /* * 下面的flags屬性的效果形同“鎖定”。 懸浮窗不可觸摸,不接受任何事件,同時不影響後面的事件響應。 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE; */ wmParams.gravity = Gravity.LEFT | Gravity.TOP; // 調整懸浮視窗至左上方 // wmParams.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT; // 調整懸浮視窗至左上方 //設定預設顯示位置 // wmParams.x = 0;<span style="font-family: Arial, Helvetica, sans-serif;">// 以螢幕左上方為原點,設定x、y初始值</span> // wmParams.y = 0; wmParams.x = windowSize.x;<span style="font-family: Arial, Helvetica, sans-serif;">// 以螢幕右邊, 距中</span> wmParams.y = windowSize.y / 2; // 設定懸浮視窗長寬資料 wmParams.width = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;// 40; wmParams.height = android.app.ActionBar.LayoutParams.WRAP_CONTENT;// 40; // 顯示myFloatView映像 wm.addView(myFV, wmParams); } } FloatFrame 類[java] package cn.hpc.assistant; import java.util.ArrayList; import java.util.List; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; public class FloatFrame extends LinearLayout { private float mTouchRawX; private float mTouchRawY; private WindowManager wm = (WindowManager) getContext() .getApplicationContext().getSystemService(Context.WINDOW_SERVICE); // 此wmParams為擷取的全域變數,用以儲存懸浮視窗的屬性 private WindowManager.LayoutParams wmParams = ((FloatApplication) getContext() .getApplicationContext()).getWmParams(); private Context mContext; View viewExtFrame; Button btnExt; public FloatFrame(Context context) { super(context); mContext = context; gestureDetector = new GestureDetector(context, gestureListener); View view = View.inflate(context, R.layout.float_layout_main, null); viewExtFrame = view.findViewById(R.id.id_float_ext_frame); btnExt = (Button)view.findViewById(R.id.id_btn_ext); int ids[] = { R.id.id_btn_ext, R.id.id_btn_exit }; for (int id : ids) { view.findViewById(id).setOnClickListener(onClick); } view.findViewById(R.id.id_btn_exit).setOnTouchListener(frameOnTouchListener); this.addView(view); } private void clickView(int id) { switch (id) { case R.id.id_btn_ext: int visible = viewExtFrame.getVisibility(); if (visible == View.VISIBLE) { viewExtFrame.setVisibility(View.INVISIBLE); btnExt.setText("<<"); } else { viewExtFrame.setVisibility(View.VISIBLE); btnExt.setText(">>"); } break; case R.id.id_btn_exit: wm.removeView(FloatFrame.this);// 點擊退出,銷毀懸浮視窗 Log.e("float view", "exit"); break; default: } } // 響應懸浮視窗中的Button點擊 View.OnClickListener onClick = new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub clickView(v.getId()); } }; final static int MESSAGE_MOVE = 0x1001; final static int MESSAGE_DOWN = 0x1002; final static int MESSAGE_UP = 0x1003; Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_MOVE: updateViewPosition(); break; case MESSAGE_DOWN: break; case MESSAGE_UP: break; default: } } }; // 點擊Listener OnTouchListener frameOnTouchListener = new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (null == gestureDetector || null == event) { return false; } return gestureDetector.onTouchEvent(event); } }; // 手勢識別 GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() { @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub Log.d("OnGestureListener", "onDown"); mTouchRawX = e.getX(); mTouchRawY = e.getY(); return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return true; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub // Log.d("OnGestureListener", "onLongPress"); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { mTouchRawX = e2.getRawX(); mTouchRawY = e2.getRawY(); mHandler.sendEmptyMessage(MESSAGE_MOVE); return true; } @Override public void onShowPress(MotionEvent e) { // Log.d("OnGestureListener", "onShowPress"); } @Override public boolean onSingleTapUp(MotionEvent e) { // Log.d("OnGestureListener", "onSingleTapUp"); return false; } }; private GestureDetector gestureDetector; private void updateViewPosition() { // 更新浮動視窗位置參數 wmParams.x = (int) mTouchRawX; wmParams.y = (int) mTouchRawY; wm.updateViewLayout(this, wmParams); } } 懸浮視窗布局檔案:[html] <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <!-- 顯示、隱藏的擴充容器 --> <LinearLayout android:id="@+id/id_float_ext_frame" android:layout_width="wrap_content" android:layout_height="600dip" android:background="@android:drawable/alert_dark_frame" android:orientation="vertical" android:visibility="gone" > <ImageView android:layout_width="wrap_content" android:layout_height="fill_parent" android:src="@drawable/ic_launcher" /> </LinearLayout> <Button android:id="@+id/id_btn_ext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="..." android:background="@android:drawable/ic_dialog_dialer" android:textColor="#FF00FF00" /> <Button android:id="@+id/id_btn_exit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="exit" android:textColor="#FF0000FF" /> </LinearLayout>