android 中上层浮动窗口

android 顶层浮动窗口

先看效果

未扩展

android 中上层浮动窗口

扩展后

android 中上层浮动窗口

代码说明

AndroidManifest..xml

<?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 类

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 类

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;// 以屏幕左上角为原点,设置x、y初始值
//		wmParams.y = 0;
		wmParams.x = windowSize.x;// 以屏幕右边, 距中
		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 类

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);

	}

 
}

悬浮窗口布局文件:

<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>