1. 程式人生 > >android程式設計之懸浮窗體

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

顯示的效果:



懸浮窗體例子

相關推薦

android程式設計懸浮窗體

用過手機360和QQ手機管家等一些軟體的朋友,會發現,在這些應用中,會出現一個懸浮窗體,例如QQ手機管家中打電話的場景: 這種窗體除了會顯示外,還可以移動它的位置,並且一直顯示。除了關閉當前程式外,視窗不會主動消失。其實,它的使用原理也很簡單,就是借用了WindowMana

Android程式設計指定ListView的item位置

很多情況,我們需要指定ListView中顯示Item的位置,如:當前已經滾動到後面,然後響應某個事件,要ListView回到頭部。 程式碼如下,其中mListView為ListView的物件: private void setListViewPos(int pos

Android程式設計Listener偵聽的N種寫法及實現原理

寫下這個題目時突然想起魯迅筆下的孔乙已,茴香豆的幾種寫法,頗有些咬文嚼字的味道。雖然從事手機程式設計多年,但一直使用的是C和C++程式設計,由於安卓早期只支援JAVA開發,所以對於時下如火如荼的安卓系統,我一直觀之而未入之。現在由於工作需要開始研究安卓程式設計,由於以前主要使

Android程式設計懸浮選單按鈕FloatingActionButton例項

Android程式設計:懸浮選單按鈕FloatingActionButton例項環境:主機:WIN10開發環境:Android Studio 2.2 Preview 3說明:用第三方庫FloatingActionButton實現懸浮選單按鈕效果圖:佈局:<?xml ve

android程式設計圖形繪製

android課堂作業要求做個五子棋遊戲,想想如果直接用控制元件可能速度會比較慢,因此就想用比較常規的遊戲程式設計方法,螢幕繪製.今天查了些資料,並做個整理. 跟其他的螢幕繪製機制一樣,android

Android程式設計DialogFragment原始碼詳解(一)

DialogFragment是Fragment家族成員之一,如果你把它簡單的理解成Dialog,那就錯了。它的確可以做作dialog顯示,還可以顯示出自己定義的Dialog或者AlertDialog,但它同時也是一個Fragment。 按照官方的話來理解就是,你既可以把它當

Android程式設計Fragment使用動畫造成Unknown animation name: objectAnimator異常

在為Fragment做切換動畫,啟動後遇到了一個異常: Caused by: java.lang.RuntimeException: Unknown animation name: objectAnimator 截圖如下: 我的程式碼如下: fragment

Android程式設計仿微信顯示更多文字的View

微信朋友圈中,如果好友發表的文字過長,會自動收縮起來,底下有提示,當點選“顯示更多”時才會展開。 首先定義佈局檔案(很簡單,不解釋): <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:

體驗Android程式設計

因為公司業務是做行情的,一般的短連線達不到這種頻繁更新資料的需求,所以長連線是必不可少的。 當下比較流行的三方框架我覺得就屬Mars了,多平臺都可以使用,而且最主要的是微信官方開源,瞬間逼格就上去了,在網路質量、日誌列印這些方面表現相對比較突出,所以就決定用M

Android 程式設計天氣預報下來重新整理資料及城市容器配置--3

前面已經把活動和服務講了講,要注意的是服務的用法,我們在這裡是 extends IntentService implements LocationListener ,下面看下 IntentService IntentService是一個通過Context.startSer

Android開發仿手機衛士懸浮窗效果

wrap 使用 indexof handle post ani refresh stat gen 基本的實現原理,這種桌面懸浮窗的效果很類似與Widget,但是它比Widget要靈活的多。主要是通過WindowManager這個類來實現的,調用這個類的addView方法用於

Android 學習Android程式設計權威指南》第二版 程式碼+筆記整理(四)

(程式碼)GeoQuiz最終開發 GeoQuiz應用初步開發 GeoQuiz應用升級開發 解決GeoQuiz應用旋轉恢復第一題的BUG 不展示編譯器自動完成的程式碼,僅提供手動修改或者編寫的程式碼。 省略了先前一些程式碼,可參照上方連結。 升級內容: 增加作弊按鈕,給使用者提

Android響應式程式設計RxJava2.0

前言 優點: 1、鏈式操作 2、非同步優化 實戰 先來個簡單的使用示例 Observable .create(new ObservableOnSubscribe<String>() {

android程式設計3 socket程式設計udp傳送

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

如何實現android中監聽來電並生成懸浮窗體提示

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android 學習Android程式設計權威指南》第二版 程式碼+筆記整理(三)

(程式碼)解決GeoQuiz應用旋轉恢復第一題的BUG 一、產生BUG的原因 1. 裝置旋轉時,系統會銷燬當前的QuizActivity例項,然後建立一個新的例項,這時陣列索引(mCurrentIndex)會初始化為0,因此使用者看到的還是第一道題目。 2.

安全程式設計Android APK打包程式碼混淆

第一步:在專案工程目錄下的proguard-rules.pro檔案中配置自定義的混淆規則 #注意: #1.引用外部的jar包 如果不是自己寫的最好不混淆它們,因為外部jar包有可能已經混淆過 #2.不要混淆XML佈局中使用的自定義控制元件類,混淆後加載佈局會報找不到該控制

Android 多執行緒程式設計 HandlerThread 詳解

    HandlerThread有那些特點: HandlerThread本質上是一個執行緒類,它繼承了Thread; HandlerThread有自己的內部Looper物件,可以進行looper迴圈; 通過獲取HandlerThread的looper物件傳

Android網路程式設計socket和http程式設計的區別

HTTP為短連線         Http協議是建立在TCP協議之上的一種應用。它與TCP連線不同之處在於,客戶端每次請求都需要伺服器返回響應,在請求結束後,會主動釋放連線,從建立連線到關閉連線的過程稱為“一次連線”。由於HTTP每次請求都會釋放連線,因為

Android網路程式設計傳遞資料給伺服器(二)

        我曾在《Android網路程式設計之傳遞資料給伺服器(一) 》一文中介紹瞭如何通過GET方式傳遞資料給伺服器,通過GET方式傳遞資料主要適用於資料大小不超過2KB,且對安全性要求不高的情況下。下面就介紹通過POST方式傳遞資料主到伺服器。 一、通過P