android编程之悬浮窗体

用过手机360和QQ手机管家等一些软件的朋友,会发现,在这些应用中,会出现一个悬浮窗体,例如QQ手机管家中打电话的场景:


这种窗体除了会显示外,还可以移动它的位置,并且一直显示。除了关闭当前程序外,窗口不会主动消失。其实,它的使用原理也很简单,就是借用了WindowManager这个管理类来实现的。
注意:要在AndroidManifest.xml中添加使用权限:

<uses-permission
		android:name="android.permission.SYSTEM_ALERT_WINDOW" />

这里,我采用代码布局的方式,模仿了一下QQ这个界面效果:
import android.content.Context;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class DesktopLayout extends LinearLayout {

	public DesktopLayout(Context context) {
		super(context);
		setOrientation(LinearLayout.HORIZONTAL);
		LayoutParams mLayoutParams = new LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		setLayoutParams(mLayoutParams);

		// 显示的ICON
		ImageView mImageView = new ImageView(context);
		mImageView.setImageResource(R.drawable.icon);
		addView(mImageView, mLayoutParams);

		// 显示的文字
		TextView mTextView = new TextView(context);
		mTextView.setText("Hello");
		mTextView.setTextSize(30);
		addView(mTextView, mLayoutParams);
	}
}

接下来,在activity中让它显示出来。首先要设置一下WindowManager.LayoutParams:
		// 取得系统窗体
		mWindowManager = (WindowManager) getApplicationContext()
				.getSystemService("window");

		// 窗体的布局样式
		mLayoutParams = new WindowManager.LayoutParams();

		// 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)
		mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

		// 设置窗体焦点及触摸:
		// FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)
		mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

		// 设置显示的模式
		mLayoutParams.format = PixelFormat.RGBA_8888;

		// 设置对齐的方法
		mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;

		// 设置窗体宽度和高度
		mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

		// 设置窗体显示的位置,否则在屏幕中心显示
		mLayoutParams.x = 50;
		mLayoutParams.y = 50;

显示窗体与关闭窗体的方法:
mWindowManager.addView(mDesktopLayout, mLayoutParams);

mWindowManager.removeView(mDesktopLayout);

以下是activity的原代码,这里设计了一个双击关闭窗体的效果:
import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
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.widget.Button;

public class DeskTip extends Activity {

	private WindowManager mWindowManager;

	private WindowManager.LayoutParams mLayoutParams;

	private DesktopLayout mDesktopLayout;

	private long starttime;

	/**
	 * 创建悬浮窗体
	 */
	private void createDesktopLayout() {
		mDesktopLayout = new DesktopLayout(this);
		mDesktopLayout.setOnTouchListener(new OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				onActionMove(event);
				return true;
			}
		});
	}

	/**
	 * 设置WindowManager
	 */
	private void createWindowManager() {
		// 取得系统窗体
		mWindowManager = (WindowManager) getApplicationContext()
				.getSystemService("window");

		// 窗体的布局样式
		mLayoutParams = new WindowManager.LayoutParams();

		// 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)
		mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

		// 设置窗体焦点及触摸:
		// FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)
		mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

		// 设置显示的模式
		mLayoutParams.format = PixelFormat.RGBA_8888;

		// 设置对齐的方法
		mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;

		// 设置窗体宽度和高度
		mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

		// 设置窗体显示的位置,否则在屏幕中心显示
		mLayoutParams.x = 50;
		mLayoutParams.y = 50;
	}

	private void onActionMove(MotionEvent event) {

		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			long end = System.currentTimeMillis() - starttime;
			// 双击的间隔在 200ms 到 500ms 之间
			if (end > 200 && end < 500) {
				closeDesk();
				return;
			}
			starttime = System.currentTimeMillis();
		}

		mLayoutParams.x = (int) (event.getRawX() - (mDesktopLayout.getWidth()));
		mLayoutParams.y = (int) (event.getRawY() - (mDesktopLayout.getHeight()));

		mWindowManager.updateViewLayout(mDesktopLayout, mLayoutParams);
	}

	/**
	 * 显示DesktopLayout
	 */
	private void showDesk() {
		mWindowManager.addView(mDesktopLayout, mLayoutParams);
		finish();
	}

	/**
	 * 关闭DesktopLayout
	 */
	private void closeDesk() {
		mWindowManager.removeView(mDesktopLayout);
		finish();
	}

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		createWindowManager();
		createDesktopLayout();

		Button btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				showDesk();
			}
		});
	}
}

显示的效果:



悬浮窗体例子

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值