突然对悬浮窗体感兴趣,查资料做了个小Demo,效果是点击按钮后,关闭当前Activity,显示悬浮窗口,窗口可以拖动,双击后消失。效果图如下:
它的使用原理很简单,就是借用了WindowManager这个管理类来实现的。
1.首先在AndroidManifest.xml中添加使用权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
2.悬浮窗口布局实现
public class DesktopLayout extends LinearLayout {</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> DesktopLayout(Context context) { </span><span style="color: #0000ff;">super</span><span style="color: #000000;">(context); setOrientation(LinearLayout.VERTICAL);</span><span style="color: #008000;">//</span><span style="color: #008000;"> 水平排列 </span><span style="color: #008000;">//</span><span style="color: #008000;">设置宽高</span> <span style="color: #0000ff;">this</span>.setLayoutParams( <span style="color: #0000ff;">new</span><span style="color: #000000;"> LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); View view </span>=<span style="color: #000000;"> LayoutInflater.from(context).inflate( R.layout.desklayout, </span><span style="color: #0000ff;">null</span><span style="color: #000000;">); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.addView(view); }</span></pre>
3.在activity中让它显示出来。
// 取得系统窗体 mWindowManager = (WindowManager) getApplicationContext() .getSystemService("window");</span><span style="color: #008000;">//</span><span style="color: #008000;"> 窗体的布局样式</span> mLayout = <span style="color: #0000ff;">new</span><span style="color: #000000;"> WindowManager.LayoutParams(); </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)</span> mLayout.type =<span style="color: #000000;"> WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体焦点及触摸: </span><span style="color: #008000;">//</span><span style="color: #008000;"> FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)</span> mLayout.flags =<span style="color: #000000;"> WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置显示的模式</span> mLayout.format =<span style="color: #000000;"> PixelFormat.RGBA_8888; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置对齐的方法</span> mLayout.gravity = Gravity.TOP |<span style="color: #000000;"> Gravity.LEFT; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体宽度和高度</span> mLayout.width =<span style="color: #000000;"> WindowManager.LayoutParams.WRAP_CONTENT; mLayout.height </span>= WindowManager.LayoutParams.WRAP_CONTENT;</pre>
详细 MainActivity 代码如下:
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;
mTouchStartX = mTouchStartY = 0; break; } return true; } }); }@Override </span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onCreate(Bundle savedInstanceState) { </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.onCreate(savedInstanceState); setContentView(R.layout.activity_main); createWindowManager(); createDesktopLayout(); Button btn </span>=<span style="color: #000000;"> (Button) findViewById(R.id.btn); btn.setOnClickListener(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> OnClickListener() { </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onClick(View v) { showDesk(); } }); } </span><span style="color: #008000;">/**</span><span style="color: #008000;"> * 创建悬浮窗体 </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> createDesktopLayout() { mDesktopLayout </span>= <span style="color: #0000ff;">new</span> DesktopLayout(<span style="color: #0000ff;">this</span><span style="color: #000000;">); mDesktopLayout.setOnTouchListener(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> OnTouchListener() { </span><span style="color: #0000ff;">float</span><span style="color: #000000;"> mTouchStartX; </span><span style="color: #0000ff;">float</span><span style="color: #000000;"> mTouchStartY; @Override </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> onTouch(View v, MotionEvent event) { </span><span style="color: #008000;">//</span><span style="color: #008000;"> 获取相对屏幕的坐标,即以屏幕左上角为原点</span> x =<span style="color: #000000;"> event.getRawX(); y </span>= event.getRawY() - top; <span style="color: #008000;">//</span><span style="color: #008000;"> 25是系统状态栏的高度</span> Log.i("startP", "startX" + mTouchStartX + "====startY" +<span style="color: #000000;"> mTouchStartY); </span><span style="color: #0000ff;">switch</span><span style="color: #000000;"> (event.getAction()) { </span><span style="color: #0000ff;">case</span><span style="color: #000000;"> MotionEvent.ACTION_DOWN: </span><span style="color: #008000;">//</span><span style="color: #008000;"> 获取相对View的坐标,即以此View左上角为原点</span> mTouchStartX =<span style="color: #000000;"> event.getX(); mTouchStartY </span>=<span style="color: #000000;"> event.getY(); Log.i(</span>"startP", "startX" + mTouchStartX + "====startY" +<span style="color: #000000;"> mTouchStartY); </span><span style="color: #0000ff;">long</span> end = System.currentTimeMillis() -<span style="color: #000000;"> startTime; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 双击的间隔在 300ms以下</span> <span style="color: #0000ff;">if</span> (end < 300<span style="color: #000000;">) { closeDesk(); } startTime </span>=<span style="color: #000000;"> System.currentTimeMillis(); </span><span style="color: #0000ff;">break</span><span style="color: #000000;">; </span><span style="color: #0000ff;">case</span><span style="color: #000000;"> MotionEvent.ACTION_MOVE: </span><span style="color: #008000;">//</span><span style="color: #008000;"> 更新浮动窗口位置参数</span> mLayout.x = (<span style="color: #0000ff;">int</span>) (x -<span style="color: #000000;"> mTouchStartX); mLayout.y </span>= (<span style="color: #0000ff;">int</span>) (y -<span style="color: #000000;"> mTouchStartY); mWindowManager.updateViewLayout(v, mLayout); </span><span style="color: #0000ff;">break</span><span style="color: #000000;">; </span><span style="color: #0000ff;">case</span><span style="color: #000000;"> MotionEvent.ACTION_UP: </span><span style="color: #008000;">//</span><span style="color: #008000;"> 更新浮动窗口位置参数</span> mLayout.x = (<span style="color: #0000ff;">int</span>) (x -<span style="color: #000000;"> mTouchStartX); mLayout.y </span>= (<span style="color: #0000ff;">int</span>) (y -<span style="color: #000000;"> mTouchStartY); mWindowManager.updateViewLayout(v, mLayout); </span><span style="color: #008000;">//</span><span style="color: #008000;"> 可以在此记录最后一次的位置</span>
@Override </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> onWindowFocusChanged(<span style="color: #0000ff;">boolean</span><span style="color: #000000;"> hasFocus) { </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.onWindowFocusChanged(hasFocus); Rect rect </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Rect(); </span><span style="color: #008000;">//</span><span style="color: #008000;"> /取得整个视图部分,注意,如果你要设置标题样式,这个必须出现在标题样式之后,否则会出错</span>
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); top = rect.top;//状态栏的高度,所以rect.height,rect.width分别是系统的高度的宽度 Log.i("top",""+top); }
</span><span style="color: #008000;">/**</span><span style="color: #008000;"> * 显示DesktopLayout </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> showDesk() { mWindowManager.addView(mDesktopLayout, mLayout); finish(); } </span><span style="color: #008000;">/**</span><span style="color: #008000;"> * 关闭DesktopLayout </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> closeDesk() { mWindowManager.removeView(mDesktopLayout); finish(); } </span><span style="color: #008000;">/**</span><span style="color: #008000;"> * 设置WindowManager </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> createWindowManager() { </span><span style="color: #008000;">//</span><span style="color: #008000;"> 取得系统窗体</span> mWindowManager =<span style="color: #000000;"> (WindowManager) getApplicationContext() .getSystemService(</span>"window"<span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;"> 窗体的布局样式</span> mLayout = <span style="color: #0000ff;">new</span><span style="color: #000000;"> WindowManager.LayoutParams(); </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)</span> mLayout.type =<span style="color: #000000;"> WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体焦点及触摸: </span><span style="color: #008000;">//</span><span style="color: #008000;"> FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)</span> mLayout.flags =<span style="color: #000000;"> WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置显示的模式</span> mLayout.format =<span style="color: #000000;"> PixelFormat.RGBA_8888; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置对齐的方法</span> mLayout.gravity = Gravity.TOP |<span style="color: #000000;"> Gravity.LEFT; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置窗体宽度和高度</span> mLayout.width =<span style="color: #000000;"> WindowManager.LayoutParams.WRAP_CONTENT; mLayout.height </span>=<span style="color: #000000;"> WindowManager.LayoutParams.WRAP_CONTENT; }
}
yc_suspendingform's People
Recommend Projects
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
TensorFlow
An Open Source Machine Learning Framework for Everyone
Django
The Web framework for perfectionists with deadlines.
Laravel
A PHP framework for web artisans
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
Recommend Topics
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
web
Some thing interesting about web. New door for the world.
server
A server is a program made to process requests and deliver data to clients.
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Visualization
Some thing interesting about visualization, use data art
Game
Some thing interesting about game, make everyone happy.
Recommend Org
We are working to build community through open source technology. NB: members must have two-factor auth.
Microsoft
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba
Alibaba Open Source for everyone
D3
Data-Driven Documents codes.
Tencent
China tencent open source team.