android 顶层浮动窗口

来源:互联网 发布:新手程序员必看书籍 编辑:程序博客网 时间:2024/04/28 00:32

先看效果

未扩展


扩展后


代码说明

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;@Overrideprotected 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());// 获取WindowManagerwm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);// 设置LayoutParams(全局变量)相关参数wmParams = ((FloatApplication) getApplication()).getWmParams();/** * 以下都是WindowManager.LayoutParams的相关属性 具体用途可参考SDK文档 */wmParams.type =  2003;//LayoutParams.TYPE_PHONE; // 设置window typewmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明// 设置Window flagwmParams.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 类

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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubclickView(v.getId());}};final static int MESSAGE_MOVE = 0x1001;final static int MESSAGE_DOWN = 0x1002;final static int MESSAGE_UP = 0x1003;Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MESSAGE_MOVE:updateViewPosition();break;case MESSAGE_DOWN:break;case MESSAGE_UP:break;default:}}};// 点击ListenerOnTouchListener 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() {@Overridepublic boolean onDown(MotionEvent e) {// TODO Auto-generated method stubLog.d("OnGestureListener", "onDown");mTouchRawX = e.getX();mTouchRawY = e.getY();return false;}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {return true;}@Overridepublic void onLongPress(MotionEvent e) {// TODO Auto-generated method stub// Log.d("OnGestureListener", "onLongPress");}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {mTouchRawX = e2.getRawX();mTouchRawY = e2.getRawY();mHandler.sendEmptyMessage(MESSAGE_MOVE);return true;}@Overridepublic void onShowPress(MotionEvent e) {//Log.d("OnGestureListener", "onShowPress");}@Overridepublic 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>