悬浮窗的实现(如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); 
    } 
    
    

}

 

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

 

 

 

 

 

 

 

 

 

 

posted @ 2013-08-22 11:44  WorldKiller  阅读(1961)  评论(1编辑  收藏  举报