zoukankan      html  css  js  c++  java
  • android编程之悬浮窗体

    用过手机360和QQ手机管家等一些软件的朋友,会发现,在这些应用中,会出现一个悬浮窗体,例如QQ手机管家中打电话的场景:


    这种窗体除了会显示外,还可以移动它的位置,并且一直显示。除了关闭当前程序外,窗口不会主动消失。其实,它的使用原理也很简单,就是借用了WindowManager这个管理类来实现的。
    注意:要在AndroidManifest.xml中添加使用权限:

    [html] view plaincopy
     
    1. <uses-permission  
    2.         android:name="android.permission.SYSTEM_ALERT_WINDOW" />  


    这里,我采用代码布局的方式,模仿了一下QQ这个界面效果:

    [java] view plaincopy
     
    1. import android.content.Context;  
    2. import android.widget.ImageView;  
    3. import android.widget.LinearLayout;  
    4. import android.widget.TextView;  
    5.   
    6. public class DesktopLayout extends LinearLayout {  
    7.   
    8.     public DesktopLayout(Context context) {  
    9.         super(context);  
    10.         setOrientation(LinearLayout.HORIZONTAL);  
    11.         LayoutParams mLayoutParams = new LayoutParams(  
    12.                 LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
    13.         setLayoutParams(mLayoutParams);  
    14.   
    15.         // 显示的ICON  
    16.         ImageView mImageView = new ImageView(context);  
    17.         mImageView.setImageResource(R.drawable.icon);  
    18.         addView(mImageView, mLayoutParams);  
    19.   
    20.         // 显示的文字  
    21.         TextView mTextView = new TextView(context);  
    22.         mTextView.setText("Hello");  
    23.         mTextView.setTextSize(30);  
    24.         addView(mTextView, mLayoutParams);  
    25.     }  
    26. }  


    接下来,在activity中让它显示出来。首先要设置一下WindowManager.LayoutParams:

    [java] view plaincopy
     
    1. // 取得系统窗体  
    2. mWindowManager = (WindowManager) getApplicationContext()  
    3.         .getSystemService("window");  
    4.   
    5. // 窗体的布局样式  
    6. mLayoutParams = new WindowManager.LayoutParams();  
    7.   
    8. // 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)  
    9. mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;  
    10.   
    11. // 设置窗体焦点及触摸:  
    12. // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)  
    13. mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
    14.   
    15. // 设置显示的模式  
    16. mLayoutParams.format = PixelFormat.RGBA_8888;  
    17.   
    18. // 设置对齐的方法  
    19. mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;  
    20.   
    21. // 设置窗体宽度和高度  
    22. mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
    23. mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
    24.   
    25. // 设置窗体显示的位置,否则在屏幕中心显示  
    26. mLayoutParams.x = 50;  
    27. mLayoutParams.y = 50;  


    显示窗体与关闭窗体的方法:

    [java] view plaincopy
     
    1. mWindowManager.addView(mDesktopLayout, mLayoutParams);  
    2.   
    3. mWindowManager.removeView(mDesktopLayout);  


    以下是activity的原代码,这里设计了一个双击关闭窗体的效果:

    [java] view plaincopy
     
    1. import android.app.Activity;  
    2. import android.graphics.PixelFormat;  
    3. import android.os.Bundle;  
    4. import android.view.Gravity;  
    5. import android.view.MotionEvent;  
    6. import android.view.View;  
    7. import android.view.View.OnClickListener;  
    8. import android.view.View.OnTouchListener;  
    9. import android.view.WindowManager;  
    10. import android.widget.Button;  
    11.   
    12. public class DeskTip extends Activity {  
    13.   
    14.     private WindowManager mWindowManager;  
    15.   
    16.     private WindowManager.LayoutParams mLayoutParams;  
    17.   
    18.     private DesktopLayout mDesktopLayout;  
    19.   
    20.     private long starttime;  
    21.   
    22.     /** 
    23.      * 创建悬浮窗体 
    24.      */  
    25.     private void createDesktopLayout() {  
    26.         mDesktopLayout = new DesktopLayout(this);  
    27.         mDesktopLayout.setOnTouchListener(new OnTouchListener() {  
    28.             public boolean onTouch(View v, MotionEvent event) {  
    29.                 onActionMove(event);  
    30.                 return true;  
    31.             }  
    32.         });  
    33.     }  
    34.   
    35.     /** 
    36.      * 设置WindowManager 
    37.      */  
    38.     private void createWindowManager() {  
    39.         // 取得系统窗体  
    40.         mWindowManager = (WindowManager) getApplicationContext()  
    41.                 .getSystemService("window");  
    42.   
    43.         // 窗体的布局样式  
    44.         mLayoutParams = new WindowManager.LayoutParams();  
    45.   
    46.         // 设置窗体显示类型——TYPE_SYSTEM_ALERT(系统提示)  
    47.         mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;  
    48.   
    49.         // 设置窗体焦点及触摸:  
    50.         // FLAG_NOT_FOCUSABLE(不能获得按键输入焦点)  
    51.         mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
    52.   
    53.         // 设置显示的模式  
    54.         mLayoutParams.format = PixelFormat.RGBA_8888;  
    55.   
    56.         // 设置对齐的方法  
    57.         mLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;  
    58.   
    59.         // 设置窗体宽度和高度  
    60.         mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
    61.         mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
    62.   
    63.         // 设置窗体显示的位置,否则在屏幕中心显示  
    64.         mLayoutParams.x = 50;  
    65.         mLayoutParams.y = 50;  
    66.     }  
    67.   
    68.     private void onActionMove(MotionEvent event) {  
    69.   
    70.         if (event.getAction() == MotionEvent.ACTION_DOWN) {  
    71.             long end = System.currentTimeMillis() - starttime;  
    72.             // 双击的间隔在 200ms 到 500ms 之间  
    73.             if (end > 200 && end < 500) {  
    74.                 closeDesk();  
    75.                 return;  
    76.             }  
    77.             starttime = System.currentTimeMillis();  
    78.         }  
    79.   
    80.         mLayoutParams.x = (int) (event.getRawX() - (mDesktopLayout.getWidth()));  
    81.         mLayoutParams.y = (int) (event.getRawY() - (mDesktopLayout.getHeight()));  
    82.   
    83.         mWindowManager.updateViewLayout(mDesktopLayout, mLayoutParams);  
    84.     }  
    85.   
    86.     /** 
    87.      * 显示DesktopLayout 
    88.      */  
    89.     private void showDesk() {  
    90.         mWindowManager.addView(mDesktopLayout, mLayoutParams);  
    91.         finish();  
    92.     }  
    93.   
    94.     /** 
    95.      * 关闭DesktopLayout 
    96.      */  
    97.     private void closeDesk() {  
    98.         mWindowManager.removeView(mDesktopLayout);  
    99.         finish();  
    100.     }  
    101.   
    102.     public void onCreate(Bundle savedInstanceState) {  
    103.         super.onCreate(savedInstanceState);  
    104.         setContentView(R.layout.main);  
    105.         createWindowManager();  
    106.         createDesktopLayout();  
    107.   
    108.         Button btn = (Button) findViewById(R.id.btn);  
    109.         btn.setOnClickListener(new OnClickListener() {  
    110.             public void onClick(View v) {  
    111.                 showDesk();  
    112.             }  
    113.         });  
    114.     }  
    115. }  


    显示的效果:



    悬浮窗体例子

    http://blog.csdn.net/xyz_fly/article/details/7546096

  • 相关阅读:
    在某个点上弹出层
    根据表名、过程名、视图名查找对应的数据库
    js时间转换nan问题 兼容浏览器
    过滤html标记 以及 返回顶部
    自定义控件 加入include 报错 问题
    在有索引视图的表上新增、修改、删除 报错 set ARITHABORT 选项不对
    访微博代码
    兼容问题 链接不跳转
    js上下滚动代码
    onload问题
  • 原文地址:https://www.cnblogs.com/daishuguang/p/3873701.html
Copyright © 2011-2022 走看看