All Projects → YeXiaoChao → Yc_suspendingform

YeXiaoChao / Yc_suspendingform

悬浮窗口

Programming Languages

java
68154 projects - #9 most used programming language

悬浮窗体实现

突然对悬浮窗体感兴趣,查资料做了个小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;"> 设置窗体显示类型&mdash;&mdash;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;
@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 &lt; 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>
mTouchStartX = mTouchStartY = 0; break; } return true; } }); }
@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;"> 设置窗体显示类型&mdash;&mdash;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;

}

}

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].