天天看點

Android 懸浮窗的實作源碼

Android 懸浮窗的實作源碼

轉載請标明出處:http://blog.csdn.net/pcaxb/article/details/48048529

懸浮窗的實作用到了一個Service、自定義View、Activity

效果圖

Android 懸浮窗的實作源碼

懸浮窗的實作用到的權限:

<!-- 仿360浮動插件需要的權限 -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="com.android.vending.BILLING" />
           

在清單檔案中注冊服務

<service android:name="com.pca.nettraffic.MserServes" />
           

代碼的實作

1.Activity的源碼

package com.pca.nettraffic;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class WidgetMainActivity extends Activity {
	// 一個有隻有一個按鈕的activity

	private Button btn;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.activity_imitate_widget_main);
		btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				funClick();
			}
		});
	}
	
	public void funClick() {
		// 按鈕被點選
		this.startService(new Intent(getApplicationContext(), MserServes.class));
		// new TableShowView(this).fun(); 如果隻是在activity中啟動
		// 當activity跑去背景的時候[暫停态,或者銷毀态] 我們設定的顯示到桌面的view也會消失
		// 是以這裡采用的是啟動一個服務,服務中建立我們需要顯示到table上的view,并将其注冊到windowManager上
		this.finish();
	}

}
           

2.Service源碼

package com.pca.nettraffic;


import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MserServes extends Service {  
	 //服務  
    //這個類純蛋疼用 隻是為了在activity點選button後 在開啟一個service   
      
    @Override  
    public IBinder onBind(Intent intent) {  
        // TODO Auto-generated method stub  
        return null;  
    }  
  
    public void onCreate() {  
    	//建立service時一個 執行個體化一個TableShowView對象并且調用他的fun()方法把它注冊到windowManager上  
        super.onCreate();  
        new TableShowView(getApplicationContext()).fun();  
        System.out.println("開啟Mser服務......");
    }  
  
  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        // TODO Auto-generated method stub  
        return super.onStartCommand(intent, flags, startId);  
    }  
}  
           

3.自定義View源碼(TableShowView extends View)

package com.pca.nettraffic;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

public class TableShowView extends View {
		// 如果是想顯示歌詞則繼承TextView并複寫ondraw方法。
		// 開啟一個線程不斷的調用ondraw方法去更改你所寫的繼承自TextView的内容
		// 這裡随便寫了個內建自view的= =這個不是重點

		Context						c;
		WindowManager				mWM;		// WindowManager
		WindowManager.LayoutParams	mWMParams;	// WindowManager參數
		View						win;
		int tag = 0;
		int oldOffsetX;
		int oldOffsetY;

		public TableShowView(Context context) {
			// TODO Auto-generated constructor stub
			super(context);
			c = context;
		}

		public void fun() {
			// 設定載入view WindowManager參數
			mWM = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
			win = LayoutInflater.from(c).inflate(R.layout.activity_imitate_widget_ctrl_window, null);
			win.setBackgroundColor(Color.TRANSPARENT);
			// 這裡是随便載入的一個布局檔案
			
			win.setOnTouchListener(new OnTouchListener() {
				// 觸屏監聽
				float	lastX, lastY;

				public boolean onTouch(View v, MotionEvent event) {
					final int action = event.getAction();

					float x = event.getX();
					float y = event.getY();
					
					if(tag == 0){
					   oldOffsetX= mWMParams.x; // 偏移量
					   oldOffsetY = mWMParams.y; // 偏移量
					}
					
				    
					if (action == MotionEvent.ACTION_DOWN) {
						lastX = x;
						lastY = y;

					}
					else if (action == MotionEvent.ACTION_MOVE) {
						mWMParams.x += (int) (x - lastX); // 偏移量
						mWMParams.y += (int) (y - lastY); // 偏移量
						
						tag = 1;
						mWM.updateViewLayout(win, mWMParams);
					}

					else if (action ==  MotionEvent.ACTION_UP){
						int newOffsetX = mWMParams.x;
						int newOffsetY = mWMParams.y;					
						if(oldOffsetX == newOffsetX && oldOffsetY == newOffsetY){
							Toast.makeText(c, "你點到我了……疼!!!!", 1).show();
						}else {
							tag = 0;
						}
					}
					return true;
				}
			});
			


			WindowManager wm = mWM;
			WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
			mWMParams = wmParams;
			wmParams.type = 2002; // type是關鍵,這裡的2002表示系統級視窗,你也可以試試2003。
			wmParams.flags = 40;// 這句設定桌面可控

			wmParams.width = 50;
			wmParams.height = 50;
			wmParams.format = -3; // 透明

			wm.addView(win, wmParams);// 這句是重點 給WindowManager中丢入剛才設定的值
										// 隻有addview後才能顯示到頁面上去。
			// 注冊到WindowManager win是要剛才随便載入的layout,wmParams是剛才設定的WindowManager參數集
			// 效果是将win注冊到WindowManager中并且它的參數是wmParams中設定餓

		}

}
           

源碼下載下傳位址:http://download.csdn.net/detail/pcaxb/9057047