android 悬浮窗使用surfaceview的问题

在程序中定义一个悬浮窗,并在布局中加入一个surfaceView时,

在屏幕中会生成一个盲点,悬浮窗的其他控件移到这个盲点时会被遮盖。如下图:(中间红色部分是一个surfaceview)


附代码:

XuanFuChuangActivity.java

  1. package com.felix.xuanfuchuang; 
  2.  
  3. import android.app.Activity; 
  4. import android.content.Intent; 
  5. import android.os.Bundle; 
  6. import android.view.WindowManager; 
  7. import android.view.ViewDebug.FlagToString; 
  8. import android.widget.Button; 
  9.  
  10. public class XuanFuChuangActivity extends Activity { 
  11.     /** Called when the activity is first created. */ 
  12.     @Override 
  13.     public void onCreate(Bundle savedInstanceState) { 
  14.         super.onCreate(savedInstanceState); 
  15.         setContentView(R.layout.main); 
  16.          
  17.         Intent it = new Intent(this, XuanFuChuangService.class); 
  18.         startService(it); 
  19.     } 
package com.felix.xuanfuchuang;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.WindowManager;
import android.view.ViewDebug.FlagToString;
import android.widget.Button;

public class XuanFuChuangActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Intent it = new Intent(this, XuanFuChuangService.class);
        startService(it);
    }
}


 XuanFuChuangService.java 

  1. package com.felix.xuanfuchuang; 
  2.  
  3. import android.app.Service; 
  4. import android.content.Intent; 
  5. import android.graphics.Canvas; 
  6. import android.graphics.Color; 
  7. import android.graphics.Paint; 
  8. import android.graphics.PixelFormat; 
  9. import android.graphics.Rect; 
  10. import android.os.IBinder; 
  11. import android.util.Log; 
  12. import android.view.Gravity; 
  13. import android.view.LayoutInflater; 
  14. import android.view.MotionEvent; 
  15. import android.view.SurfaceHolder; 
  16. import android.view.SurfaceHolder.Callback; 
  17. import android.view.SurfaceView; 
  18. import android.view.View; 
  19. import android.view.View.OnClickListener; 
  20. import android.view.View.OnTouchListener; 
  21. import android.view.WindowManager; 
  22. import android.view.WindowManager.LayoutParams; 
  23. import android.widget.Button; 
  24. import android.widget.TextView; 
  25.  
  26. public class XuanFuChuangService extends Service { 
  27.  
  28.     private int statusBarHeight; 
  29.     private View view; 
  30.     private TextView tv; 
  31.     private Button btn; 
  32.     private SurfaceView sv; 
  33.     private boolean viewAdded = false
  34.     private WindowManager wm; 
  35.     private WindowManager.LayoutParams params; 
  36.     private int x,y; 
  37.     @Override 
  38.     public IBinder onBind(Intent it) { 
  39.         // TODO Auto-generated method stub 
  40.         return null
  41.     } 
  42.     @Override 
  43.     public void onCreate() { 
  44.         // TODO Auto-generated method stub 
  45.         super.onCreate(); 
  46.          
  47.         view = LayoutInflater.from(this).inflate(R.layout.floating, null); 
  48.         tv = (TextView)view.findViewById(R.id.text_view); 
  49.         tv.bringToFront(); 
  50.         btn = (Button)view.findViewById(R.id.floating_button_hide); 
  51.         btn.setOnClickListener(new OnClickListener() { 
  52.              
  53.             @Override 
  54.             public void onClick(View v) { 
  55.                 // TODO Auto-generated method stub 
  56.                 Log.v("floating window", "btn clicked"); 
  57.             } 
  58.         }); 
  59.         sv = (SurfaceView)view.findViewById(R.id.surface_view); 
  60.         sv.setMinimumWidth(100); 
  61.         sv.setMinimumHeight(200); 
  62.         sv.setOnTouchListener(new OnTouchListener() { 
  63.              
  64.             @Override 
  65.             public boolean onTouch(View v, MotionEvent event) { 
  66.                 int eventAction = event.getAction(); 
  67.                 switch(eventAction) 
  68.                 { 
  69.                 case MotionEvent.ACTION_DOWN: 
  70.                     x = (int)event.getX(); 
  71.                     y = (int)event.getY(); 
  72.                     break
  73.                 } 
  74.                 return true
  75.             } 
  76.         }); 
  77.         sv.getHolder().addCallback(new Callback() { 
  78.             private DrawThread dt ; 
  79.             @Override 
  80.             public void surfaceDestroyed(SurfaceHolder holder) { 
  81.                 // TODO Auto-generated method stub 
  82.                 dt.isRun = false
  83.             } 
  84.              
  85.             @Override 
  86.             public void surfaceCreated(SurfaceHolder holder) { 
  87.                 // TODO Auto-generated method stub 
  88.                 dt = new DrawThread(holder); 
  89.                 dt.isRun = true
  90.                 dt.start(); 
  91.                  
  92.             } 
  93.              
  94.             @Override 
  95.             public void surfaceChanged(SurfaceHolder holder, int format, int width, 
  96.                     int height) { 
  97.                 // TODO Auto-generated method stub 
  98.                  
  99.             } 
  100.              
  101.             class DrawThread extends Thread 
  102.             { 
  103.                 private SurfaceHolder holder; 
  104.                 private boolean isRun; 
  105.                 public DrawThread(SurfaceHolder h) 
  106.                 { 
  107.                     holder = h; 
  108.                     isRun = true
  109.                 } 
  110.                 @Override 
  111.                 public void run() 
  112.                 { 
  113.                     int count = 0
  114.                     while(isRun) 
  115.                     { 
  116.                         Canvas c = null
  117.                         try 
  118.                         { 
  119.                             synchronized(holder) 
  120.                             { 
  121.                                 count %= 10
  122.                                 c = holder.lockCanvas(); 
  123.                                 c.drawColor(Color.RED); 
  124.                                 Paint p = new Paint(); 
  125.                                 p.setColor(Color.CYAN); 
  126.                                 Log.v("floating window","x="+x+" y="+y); 
  127.                                 Rect r = new Rect(x,y,x+10+count,y+50); 
  128.                                 c.drawRect(r, p); 
  129.                                 count += 2
  130.                                 Thread.sleep(1000); 
  131.                             } 
  132.                         }catch (Exception e) { 
  133.                             // TODO: handle exception 
  134.                             e.printStackTrace(); 
  135.                         }finally 
  136.                         { 
  137.                             if(c != null
  138.                             { 
  139.                                 holder.unlockCanvasAndPost(c); 
  140.                             } 
  141.                         } 
  142.                     } 
  143.                 } 
  144.             } 
  145.         }); 
  146.          
  147.         wm = (WindowManager)this.getSystemService(WINDOW_SERVICE); 
  148.          
  149.         params = new LayoutParams(); 
  150.         params.width = LayoutParams.WRAP_CONTENT; 
  151.         params.height = LayoutParams.WRAP_CONTENT; 
  152.         params.type = LayoutParams.TYPE_SYSTEM_ALERT|LayoutParams.TYPE_SYSTEM_OVERLAY; 
  153.         params.flags = LayoutParams.FLAG_NOT_FOCUSABLE|LayoutParams.FLAG_NOT_TOUCH_MODAL; 
  154.          
  155.         params.gravity= Gravity.LEFT|Gravity.TOP; 
  156.          
  157.         view.setOnTouchListener(new OnTouchListener() { 
  158.             float[] tmp = new float[]{0f, 0f}; 
  159.             @Override 
  160.             public boolean onTouch(View v, MotionEvent event) { 
  161.                 // TODO Auto-generated method stub 
  162.                 //params.gravity 
  163.                 int eventAction = event.getAction(); 
  164.                 switch(eventAction) 
  165.                 { 
  166.                 case MotionEvent.ACTION_DOWN: 
  167.                     tmp[0] = event.getX(); 
  168.                     tmp[1] = event.getY(); 
  169.                     break
  170.                 case MotionEvent.ACTION_MOVE: 
  171.                     refreshView((int)(event.getRawX() - tmp[0]),(int)(event.getRawY() - tmp[1])); 
  172.                     break
  173.                 } 
  174.                 return true
  175.             } 
  176.         }); 
  177.     } 
  178.     protected void refreshView(int x, int y) { 
  179.         // TODO Auto-generated method stub 
  180.         if(statusBarHeight == 0
  181.         { 
  182.             View rootView = view.getRootView(); 
  183.             Rect r = new Rect(); 
  184.             rootView.getWindowVisibleDisplayFrame(r); 
  185.             statusBarHeight = r.top; 
  186.         } 
  187.         tv.setText("x="+x+" y="+y); 
  188.         params.x = x; 
  189.         params.y = y-statusBarHeight; 
  190.         refresh(); 
  191.     } 
  192.     private void refresh() { 
  193.         // TODO Auto-generated method stub 
  194.         if(viewAdded) 
  195.         { 
  196.             wm.updateViewLayout(view, params); 
  197.         } 
  198.         else 
  199.         { 
  200.             wm.addView(view, params); 
  201.             viewAdded = true
  202.         } 
  203.     } 
  204.     private void removeView() 
  205.     { 
  206.         if(viewAdded) 
  207.         { 
  208.             wm.removeView(view); 
  209.             viewAdded = false
  210.         } 
  211.     } 
  212.     @Override 
  213.     public void onDestroy() { 
  214.         super.onDestroy(); 
  215.         Log.v("floating window","on destroy"); 
  216.         removeView(); 
  217.     } 
  218.     @Override 
  219.     public void onStart(Intent intent, int startId) { 
  220.         super.onStart(intent, startId); 
  221.         Log.v("floating window", "onstart"); 
  222.         refresh(); 
  223.     } 
  224.  
package com.felix.xuanfuchuang;

import android.app.Service;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.TextView;

public class XuanFuChuangService extends Service {

	private int statusBarHeight;
	private View view;
	private TextView tv;
	private Button btn;
	private SurfaceView sv;
	private boolean viewAdded = false;
	private WindowManager wm;
	private WindowManager.LayoutParams params;
	private int x,y;
	@Override
	public IBinder onBind(Intent it) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		view = LayoutInflater.from(this).inflate(R.layout.floating, null);
		tv = (TextView)view.findViewById(R.id.text_view);
		tv.bringToFront();
		btn = (Button)view.findViewById(R.id.floating_button_hide);
		btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Log.v("floating window", "btn clicked");
			}
		});
		sv = (SurfaceView)view.findViewById(R.id.surface_view);
		sv.setMinimumWidth(100);
		sv.setMinimumHeight(200);
		sv.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				int eventAction = event.getAction();
				switch(eventAction)
				{
				case MotionEvent.ACTION_DOWN:
					x = (int)event.getX();
					y = (int)event.getY();
					break;
				}
				return true;
			}
		});
		sv.getHolder().addCallback(new Callback() {
			private DrawThread dt ;
			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
				// TODO Auto-generated method stub
				dt.isRun = false;
			}
			
			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				// TODO Auto-generated method stub
				dt = new DrawThread(holder);
				dt.isRun = true;
				dt.start();
				
			}
			
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int width,
					int height) {
				// TODO Auto-generated method stub
				
			}
			
			class DrawThread extends Thread
			{
				private SurfaceHolder holder;
				private boolean isRun;
				public DrawThread(SurfaceHolder h)
				{
					holder = h;
					isRun = true;
				}
				@Override
				public void run()
				{
					int count = 0;
					while(isRun)
					{
						Canvas c = null;
						try
						{
							synchronized(holder)
							{
								count %= 10;
								c = holder.lockCanvas();
								c.drawColor(Color.RED);
								Paint p = new Paint();
								p.setColor(Color.CYAN);
								Log.v("floating window","x="+x+" y="+y);
								Rect r = new Rect(x,y,x+10+count,y+50);
								c.drawRect(r, p);
								count += 2;
								Thread.sleep(1000);
							}
						}catch (Exception e) {
							// TODO: handle exception
							e.printStackTrace();
						}finally
						{
							if(c != null)
							{
								holder.unlockCanvasAndPost(c);
							}
						}
					}
				}
			}
		});
		
		wm = (WindowManager)this.getSystemService(WINDOW_SERVICE);
		
		params = new LayoutParams();
		params.width = LayoutParams.WRAP_CONTENT;
		params.height = LayoutParams.WRAP_CONTENT;
		params.type = LayoutParams.TYPE_SYSTEM_ALERT|LayoutParams.TYPE_SYSTEM_OVERLAY;
		params.flags = LayoutParams.FLAG_NOT_FOCUSABLE|LayoutParams.FLAG_NOT_TOUCH_MODAL;
		
		params.gravity= Gravity.LEFT|Gravity.TOP;
		
		view.setOnTouchListener(new OnTouchListener() {
			float[] tmp = new float[]{0f, 0f};
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				//params.gravity
				int eventAction = event.getAction();
				switch(eventAction)
				{
				case MotionEvent.ACTION_DOWN:
					tmp[0] = event.getX();
					tmp[1] = event.getY();
					break;
				case MotionEvent.ACTION_MOVE:
					refreshView((int)(event.getRawX() - tmp[0]),(int)(event.getRawY() - tmp[1]));
					break;
				}
				return true;
			}
		});
	}
	protected void refreshView(int x, int y) {
		// TODO Auto-generated method stub
		if(statusBarHeight == 0)
		{
			View rootView = view.getRootView();
			Rect r = new Rect();
			rootView.getWindowVisibleDisplayFrame(r);
			statusBarHeight = r.top;
		}
		tv.setText("x="+x+" y="+y);
		params.x = x;
		params.y = y-statusBarHeight;
		refresh();
	}
	private void refresh() {
		// TODO Auto-generated method stub
		if(viewAdded)
		{
			wm.updateViewLayout(view, params);
		}
		else
		{
			wm.addView(view, params);
			viewAdded = true;
		}
	}
	private void removeView()
	{
		if(viewAdded)
		{
			wm.removeView(view);
			viewAdded = false;
		}
	}
	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.v("floating window","on destroy");
		removeView();
	}
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		Log.v("floating window", "onstart");
		refresh();
	}

}


布局文件floating.xml

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="wrap_content" 
  4.     android:layout_height="wrap_content" 
  5.     android:orientation="horizontal" 
  6.     android:background="#00ff00" 
  7. > 
  8.     <LinearLayout android:orientation="vertical" 
  9.         android:layout_width="wrap_content" 
  10.         android:layout_height="wrap_content" 
  11.         android:gravity="center_vertical" 
  12.         android:background="#0000ff" 
  13.         > 
  14.         <TextView android:id="@+id/text_view" 
  15.             android:layout_width="80px" 
  16.             android:layout_height="20px" 
  17.             android:text="null" 
  18.             android:editable="false"/> 
  19.         <SurfaceView android:id="@+id/surface_view" 
  20.             android:layout_width="150px" 
  21.             android:layout_height="100px" 
  22.             /> 
  23.     </LinearLayout> 
  24.     <Button android:id="@+id/floating_button_hide" 
  25.         android:layout_width="wrap_content" 
  26.         android:layout_height="wrap_content" 
  27.         android:text="hide" 
  28.         /> 
  29.  
  30. </LinearLayout> 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SurfaceView 实现为悬浮窗口的步骤如下: 1. 创建一个继承自 Service 的服务,在服务中创建一个 WindowManager 对象,并创建一个 SurfaceView。 2. 在 onCreate() 方法中,设置 SurfaceView 的参数,并将 SurfaceView 添加到 WindowManager 上。 3. 在 onDestroy() 方法中,将 SurfaceView 从 WindowManager 上移除。 下面是一个示例代码: ``` public class MyService extends Service { private WindowManager mWindowManager; private SurfaceView mSurfaceView; @Override public void onCreate() { super.onCreate(); // 创建 WindowManager mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建 SurfaceView mSurfaceView = new SurfaceView(this); // 设置 SurfaceView 的参数 WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); // 将 SurfaceView 添加到 WindowManager 上 mWindowManager.addView(mSurfaceView, params); } @Override public void onDestroy() { super.onDestroy(); // 将 SurfaceView 从 WindowManager 上移除 mWindowManager.removeView(mSurfaceView); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ``` 需要注意的是,由于 Android 8.0 以上版本的限制,需要在 AndroidManifest.xml 文件中添加如下权限: ``` <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 同时,在运行时需要动态申请权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值