突然对悬浮窗体感兴趣,查资料做了个小Demo,效果是点击按钮后,关闭当前Activity,显示悬浮窗口,窗口可以拖动,双击后消失。效果图如下:
它的使用原理很简单,就是借用了WindowManager这个管理类来实现的。
1.首先在AndroidManifest.xml中添加使用权限:
1
|
<uses-permission android:name= "android.permission.SYSTEM_ALERT_WINDOW" /> |
2.悬浮窗口布局实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class DesktopLayout extends LinearLayout { public DesktopLayout(Context context) { super (context); setOrientation(LinearLayout.VERTICAL); // 水平排列 //设置宽高 this .setLayoutParams( new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); View view = LayoutInflater.from(context).inflate( R.layout.desklayout, null ); this .addView(view); } |
3.在activity中让它显示出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 取得系统窗体 mWindowManager = (WindowManager) getApplicationContext() .getSystemService( "window" ); // 窗体的布局样式 mLayout = new WindowManager.LayoutParams(); // 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示) mLayout.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 设置窗体焦点及触摸: // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点) mLayout.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 设置显示的模式 mLayout.format = PixelFormat.RGBA_8888; // 设置对齐的方法 mLayout.gravity = Gravity.TOP | Gravity.LEFT; // 设置窗体宽度和高度 mLayout.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayout.height = WindowManager.LayoutParams.WRAP_CONTENT; |
详细 MainActivity 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
package com.yc.yc_suspendingform; import android.app.Activity; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; 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; import com.yc.yc_floatingform.R; public class MainActivity extends Activity { private WindowManager mWindowManager; private WindowManager.LayoutParams mLayout; private DesktopLayout mDesktopLayout; private long startTime; // 声明屏幕的宽高 float x, y; int top; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); createWindowManager(); createDesktopLayout(); Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener( new OnClickListener() { public void onClick(View v) { showDesk(); } }); } /** * 创建悬浮窗体 */ private void createDesktopLayout() { mDesktopLayout = new DesktopLayout( this ); mDesktopLayout.setOnTouchListener( new OnTouchListener() { float mTouchStartX; float mTouchStartY; @Override public boolean onTouch(View v, MotionEvent event) { // 获取相对屏幕的坐标,即以屏幕左上角为原点 x = event.getRawX(); y = event.getRawY() - top; // 25是系统状态栏的高度 Log.i( "startP" , "startX" + mTouchStartX + "====startY" + mTouchStartY); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 获取相对View的坐标,即以此View左上角为原点 mTouchStartX = event.getX(); mTouchStartY = event.getY(); Log.i( "startP" , "startX" + mTouchStartX + "====startY" + mTouchStartY); long end = System.currentTimeMillis() - startTime; // 双击的间隔在 300ms以下 if (end < 300 ) { closeDesk(); } startTime = System.currentTimeMillis(); break ; case MotionEvent.ACTION_MOVE: // 更新浮动窗口位置参数 mLayout.x = ( int ) (x - mTouchStartX); mLayout.y = ( int ) (y - mTouchStartY); mWindowManager.updateViewLayout(v, mLayout); break ; case MotionEvent.ACTION_UP: // 更新浮动窗口位置参数 mLayout.x = ( int ) (x - mTouchStartX); mLayout.y = ( int ) (y - mTouchStartY); mWindowManager.updateViewLayout(v, mLayout); // 可以在此记录最后一次的位置 mTouchStartX = mTouchStartY = 0 ; break ; } return true ; } }); } @Override public void onWindowFocusChanged( boolean hasFocus) { super .onWindowFocusChanged(hasFocus); Rect rect = new Rect(); // /取得整个视图部分,注意,如果你要设置标题样式,这个必须出现在标题样式之后,否则会出错 getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); top = rect.top; //状态栏的高度,所以rect.height,rect.width分别是系统的高度的宽度 Log.i( "top" , "" +top); } /** * 显示DesktopLayout */ private void showDesk() { mWindowManager.addView(mDesktopLayout, mLayout); finish(); } /** * 关闭DesktopLayout */ private void closeDesk() { mWindowManager.removeView(mDesktopLayout); finish(); } /** * 设置WindowManager */ private void createWindowManager() { // 取得系统窗体 mWindowManager = (WindowManager) getApplicationContext() .getSystemService( "window" ); // 窗体的布局样式 mLayout = new WindowManager.LayoutParams(); // 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示) mLayout.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 设置窗体焦点及触摸: // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点) mLayout.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 设置显示的模式 mLayout.format = PixelFormat.RGBA_8888; // 设置对齐的方法 mLayout.gravity = Gravity.TOP | Gravity.LEFT; // 设置窗体宽度和高度 mLayout.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayout.height = WindowManager.LayoutParams.WRAP_CONTENT; } } |
源代码地址:Android实现悬浮窗体效果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/yc-755909659/p/4281214.html