zoukankan      html  css  js  c++  java
  • 悬浮窗的实现(如360悬浮窗效果)

    悬浮窗实现

      相信大家,都知晓360的悬浮窗口,非常潇洒。。。

    如图:

     

    现在,我也实现了具有吸附效果的悬浮窗。有图有真相...

    看图: 吸附屏幕两侧的效果

    废话少说,看代码。代码中,有详细注释...

    布局文件:floating.xml(悬浮窗的布局)

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:context=".MainActivity" 
        android:orientation="horizontal"
        >
    
        <ImageView 
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/rekoo"
            />
        
        <LinearLayout 
            android:id="@+id/floats"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:background="@drawable/settings_bg_right"
            android:layout_marginTop="2dp"
            android:visibility="gone"
            >
    
            <LinearLayout
                android:id="@+id/btn1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical" 
                android:layout_marginLeft="2dp"
                >
                <ImageButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/settings_bbs_pressed" />
                <TextView 
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="论坛"
                    android:textColor="@android:color/white"
                    />
            </LinearLayout>
    
            <LinearLayout
                android:id="@+id/btn2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:orientation="vertical" >
    
                <ImageButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/settings_bind_phone_pressed" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="电话"
                    android:textColor="@android:color/white" />
            </LinearLayout>
           
            <LinearLayout
                android:id="@+id/btn3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:orientation="vertical" >
                <ImageButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/settings_service_pressed" />
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="关闭"
                    android:textColor="@android:color/white" />
            </LinearLayout>
            
        </LinearLayout>
    
    </LinearLayout>

    源码:

    package org.lqh.floatDemo;
    
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.PixelFormat;
    import android.graphics.Rect;
    import android.os.Bundle;
    import android.view.Display;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.Window;
    import android.view.WindowManager;
    import android.view.WindowManager.LayoutParams;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener
    {
        private WindowManager windowManager = null; 
        private WindowManager.LayoutParams windowManagerParams = null; 
    
        private float mTouchX; 
        private float mTouchY; 
        private float x; 
        private float y; 
        private float mStartX; 
        private float mStartY; 
        
        private View view;
        private ImageView icon;
        private LinearLayout floats;
        private LinearLayout btn1;
        private LinearLayout btn2;
        private LinearLayout btn3;
        @Override
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏 
            getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , 
                    WindowManager.LayoutParams. FLAG_FULLSCREEN);//全屏 
            setContentView(R.layout.activity_main); 
            
            view = LayoutInflater.from(this).inflate(R.layout.floating, null);
            icon = (ImageView) view.findViewById(R.id.icon);
            floats = (LinearLayout) view.findViewById(R.id.floats);
            btn1 = (LinearLayout) floats.findViewById(R.id.btn1);
            btn2 = (LinearLayout) floats.findViewById(R.id.btn2);
            btn3 = (LinearLayout) floats.findViewById(R.id.btn3);
            btn1.setOnClickListener(this);
            btn2.setOnClickListener(this);
            btn3.setOnClickListener(this);
            createView();  
        } 
    
        private void createView() { 
            
            // 1、获取WindowManager对象 
            windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); 
            // 2、设置LayoutParams(全局变量)相关参数 
            windowManagerParams = new WindowManager.LayoutParams();
    //        windowManagerParams = ((FloatApplication) getApplication()).getWindowParams(); 
            //3、设置相关的窗口布局参数 (悬浮窗口效果)
            windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type 
            windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明 
            //4、设置Window flag == 不影响后面的事件  和  不可聚焦
            windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL 
                    | LayoutParams.FLAG_NOT_FOCUSABLE; 
            /* 
             * 注意,flag的值可以为: 
             * LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件 
             * LayoutParams.FLAG_NOT_FOCUSABLE  不可聚焦 
             * LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸 
             */
            //5、 调整悬浮窗口至左上角,便于调整坐标 
            windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;  
            // 以屏幕左上角为原点,设置x、y初始值 
            windowManagerParams.x = 0; 
            windowManagerParams.y = 80; 
            //6、设置悬浮窗口长宽数据 
            windowManagerParams.width = LayoutParams.WRAP_CONTENT; 
            windowManagerParams.height = LayoutParams.WRAP_CONTENT; 
            
            //获得屏幕的宽高
                    Display display = windowManager.getDefaultDisplay();
                    final int screenWith = display.getWidth();
                    int screenHeight = display.getHeight();
                    System.out.println("screenWith="+screenWith+",screenHeight="+screenHeight);
            
            icon.setOnTouchListener(new View.OnTouchListener()
            {
                @Override
                public boolean onTouch(View v, MotionEvent event)
                {
                    //1、获取到状态栏的高度 
                    Rect frame =  new  Rect();   
                    icon.getWindowVisibleDisplayFrame(frame); 
                    int  statusBarHeight = frame.top; 
                    System.out.println("状态栏高度:"+statusBarHeight); 
                    //2、获取相对屏幕的坐标,即以屏幕左上角为原点 。y轴坐标= y(获取到屏幕原点的距离)-状态栏的高度
                    x = event.getRawX(); 
                    y = event.getRawY() - statusBarHeight; // statusBarHeight是系统状态栏的高度 
                    
                    System.out.println("x="+x+",y="+y);
                    //3、处理触摸移动
                    switch (event.getAction()) { 
                    case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作 
                            // 获取相对View的坐标,即以此View左上角为原点 
                            mTouchX = event.getX(); 
                            mTouchY = event.getY(); 
                            mStartX = x; 
                            mStartY = y; 
                            
                            System.out.println(",mTouchX=" + mTouchX + ",mTouchY="
                                            + mTouchY);
                            break; 
    
                    case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作 
                            updateViewPosition(); 
                            break; 
    
                    case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作 
                        float left = x-mTouchX;   
                        if(left <= screenWith/2){//图标icon吸附在左边
                               x = mTouchX;
                           }else {//图标icon吸附在右边
                            x = mTouchX + screenWith;
                        }
                            
                            updateViewPosition(); 
                            //移动终点的坐标,重置为0
                            mTouchX = mTouchY = 0; 
                            //移动距离少于5 ,则视为点击,触发点击的回调
                            if ((x - mStartX) < 5 && (y - mStartY) < 5) { 
                                    onClick(v); 
                            }
                            break; 
                    } 
                    return true; 
                }
            });
            
            windowManager.addView(view, windowManagerParams); // 显示myFloatView图像 
        } 
    
        /**
         * 用于更新 悬浮窗位置参数
         * */
        private void updateViewPosition() { 
                windowManagerParams.x = (int) (x - mTouchX); 
                windowManagerParams.y = (int) (y - mTouchY); 
                
                System.out.println("wp.x="+windowManagerParams.x+",wp.y="+windowManagerParams.y);
                // 刷新屏幕显示 
                windowManager.updateViewLayout(view, windowManagerParams); 
        } 
    
        @Override
        public void onClick(View v)
        {
            switch (v.getId())
            {
            case R.id.icon:
                if (floats.getVisibility() == View.VISIBLE)
                {
                    floats.setVisibility(View.GONE);
                } else {
                    floats.setVisibility(View.VISIBLE);
                }
                break;
            case R.id.btn1:
                Toast.makeText(this,"亲,我是论坛!", 2).show();
                break;
            case R.id.btn2:
                Toast.makeText(this,"亲,我是手机验证!", 2).show();
                break;
            case R.id.btn3:
                windowManager.removeView(view); 
                android.os.Process.killProcess(android.os.Process.myPid());
                break;
            default:
                break;
            }
            
        } 
        
        public void onDestroy() { 
            super.onDestroy(); 
            // 在程序退出(Activity销毁)时销毁悬浮窗口 
    //        windowManager.removeView(view); 
        } 
        
        
    
    }

    如有大家,不明白之处,尽情留言评价。。。

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    电脑hosts文件、hosts文件说明、hosts文件域名和ip
    java复制对象属性值、复制值
    查找替换、idea全局搜索、全局替换、全局搜索替换
    谷歌浏览器问题、
    http请求类、RestTemplate、请求工具类
    easypoi导入
    vue下载本地文件、vue下载本地文件报错、vue下载本地文件找不到
    arm汇编指令的条件码
    GNU内嵌汇编
    shell脚本错误:syntax error near unexpected token '$' ''
  • 原文地址:https://www.cnblogs.com/codeAnimal/p/3274508.html
Copyright © 2011-2022 走看看