Android悬浮窗拖动

此代码只能应用于 版本号19以上的手机

悬浮窗的关键是 :WindowManager  以下列出了 button ,Imageview,SurfaceView(视频) 三种悬浮窗 

要想悬浮窗不影响到其他应用的使用 需要将 WindowManager 的 LayoutParams flag  参数设置成以下的模式

// 设置LayoutParam
            mLayoutParams = new WindowManager.LayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            mLayoutParams.flags = mLayoutParams.FLAG_NOT_TOUCH_MODAL | mLayoutParams.FLAG_NOT_FOCUSABLE | mLayoutParams.FLAG_FULLSCREEN
                    | mLayoutParams.FLAG_LAYOUT_IN_SCREEN;

设置权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

检查是否设置了权限,因为可以再其他应用之上使用 所以需要通过服务来控制悬浮窗

@RequiresApi(api = Build.VERSION_CODES.M)
    public void startFloatingService(View view) {
        if(!Settings.canDrawOverlays(this)){
            Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT).show();
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName())),0);
        } else {
            startService(new Intent(FloatActivity.this, FloatServices.class));
        }
    }

 

具体代码如下   Activity

package com.example.android.recycleautocarousel;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.example.android.recycleautocarousel.services.FloatServices;

public class FloatActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_float);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public void startFloatingService(View view) {
        if(!Settings.canDrawOverlays(this)){
            Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT).show();
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName())),0);
        } else {
            startService(new Intent(FloatActivity.this, FloatServices.class));
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 0) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
                startService(new Intent(FloatActivity.this, FloatServices.class));
            }
        }
    }


}

 

Service

package com.example.android.recycleautocarousel.services;

import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.android.recycleautocarousel.R;

import java.io.IOException;

/**
 * Created by android on 2018/6/22.
 */

public class FloatServices extends Service {

    private Button mButton;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mLayoutParams;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        showFloatingWindow();

        return super.onStartCommand(intent, flags, startId);
    }




    private  class FloatingOnTouchListener implements View.OnTouchListener{
        private int x;
        private int y;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
           switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = (int) event.getRawX();
                    y = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int nowX = (int) event.getRawX();
                    int nowY = (int) event.getRawY();
                    int movedX = nowX - x;
                    int movedY = nowY - y;
                    x = nowX;
                    y = nowY;
                    mLayoutParams.x = mLayoutParams.x + movedX;
                    mLayoutParams.y = mLayoutParams.y + movedY;

                    // 更新悬浮窗控件布局
                    mWindowManager.updateViewLayout(v, mLayoutParams);
                    break;
                default:
                    break;
            }
            return false;
        }
    }






    /**
     * 悬浮窗口 视屏
     */
    private void showFloatingWindow() {
        if (Settings.canDrawOverlays(this)) {

            mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
            LayoutInflater layoutInflater = LayoutInflater.from(this);
            View displayView = layoutInflater.inflate(R.layout.image_display, null);
            displayView.setOnTouchListener(new  FloatingOnTouchListener());

            // 获取WindowManager服务
            final MediaPlayer mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            SurfaceView surfaceView = displayView.findViewById(R.id.video_display_surfaceview);
            final SurfaceHolder surfaceHolder = surfaceView.getHolder();



            surfaceHolder.addCallback(new SurfaceHolder.Callback() {
                  @Override
                  public void surfaceCreated(SurfaceHolder holder) {
                      mediaPlayer.setDisplay(surfaceHolder);
                  }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

                }

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {

                }

            });
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mediaPlayer.start();
                }
            });


            try {
                mediaPlayer.setDataSource(this, Uri.parse("https://raw.githubusercontent.com/dongzhong/ImageAndVideoStore/master/Bruno%20Mars%20-%20Treasure.mp4"));
                mediaPlayer.prepareAsync();
            }
            catch (IOException e) {
                Toast.makeText(this, "无法打开视频源", Toast.LENGTH_LONG).show();
            }


            // 设置LayoutParam
            mLayoutParams = new WindowManager.LayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            // flag参数必须设置 不然有悬浮窗 但其他应用也无法使用
            mLayoutParams.flags = mLayoutParams.FLAG_NOT_TOUCH_MODAL | mLayoutParams.FLAG_NOT_FOCUSABLE | mLayoutParams.FLAG_FULLSCREEN
                    | mLayoutParams.FLAG_LAYOUT_IN_SCREEN;
            mLayoutParams.format = PixelFormat.RGBA_8888;
            mLayoutParams.width = 300;
            mLayoutParams.height = 300;
            mLayoutParams.x = 300;
            mLayoutParams.y = 300;

            // 将悬浮窗控件添加到WindowManager
            mWindowManager.addView(displayView, mLayoutParams);
        }
    }



    /**
     * 悬浮窗口Imageview
     */
    private void showFloatingWindow2() {
        if (Settings.canDrawOverlays(this)) {
            // 获取WindowManager服务
            mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

            LayoutInflater layoutInflater = LayoutInflater.from(this);
            View displayView = layoutInflater.inflate(R.layout.image_display, null);
            displayView.setOnTouchListener(new  FloatingOnTouchListener());

            ImageView imageView = displayView.findViewById(R.id.image_display_imageview);
            imageView.setImageResource(R.drawable.item1);



            // 设置LayoutParam
            mLayoutParams = new WindowManager.LayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            // flag参数必须设置 不然有悬浮窗 但其他应用也无法使用
            mLayoutParams.flags = mLayoutParams.FLAG_NOT_TOUCH_MODAL | mLayoutParams.FLAG_NOT_FOCUSABLE | mLayoutParams.FLAG_FULLSCREEN
                    | mLayoutParams.FLAG_LAYOUT_IN_SCREEN;
            mLayoutParams.format = PixelFormat.RGBA_8888;
            mLayoutParams.width = 100;
            mLayoutParams.height = 100;
            mLayoutParams.x = 300;
            mLayoutParams.y = 300;

            // 将悬浮窗控件添加到WindowManager
            mWindowManager.addView(displayView, mLayoutParams);
        }
    }

    /**
     * 悬浮窗口button
     */
    private void showFloatingWindow1() {
        if (Settings.canDrawOverlays(this)) {
            // 获取WindowManager服务
            mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

            // 新建悬浮窗控件
            mButton = new Button(getApplicationContext());
            mButton.setText("Floating Window");
            mButton.setBackgroundColor(Color.BLUE);

            // 设置LayoutParam
            mLayoutParams = new WindowManager.LayoutParams();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            // flag参数必须设置 不然有悬浮窗 但其他应用也无法使用
            mLayoutParams.flags = mLayoutParams.FLAG_NOT_TOUCH_MODAL | mLayoutParams.FLAG_NOT_FOCUSABLE | mLayoutParams.FLAG_FULLSCREEN
                    | mLayoutParams.FLAG_LAYOUT_IN_SCREEN;
            mLayoutParams.format = PixelFormat.RGBA_8888;
            mLayoutParams.width = 500;
            mLayoutParams.height = 100;
            mLayoutParams.x = 300;
            mLayoutParams.y = 300;

            // 将悬浮窗控件添加到WindowManager
            mWindowManager.addView(mButton, mLayoutParams);
        }
    }
}

activity_float.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_float"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.android.recycleautocarousel.FloatActivity"
    >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="nihao "
        android:onClick="startFloatingService"
        />


</RelativeLayout>

image_display.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">

    <ImageView
        android:visibility="gone"
        android:id="@+id/image_display_imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <SurfaceView
        android:id="@+id/video_display_surfaceview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />


</LinearLayout>

 打完收工

posted on 2018-06-22 17:15  LKit  阅读(1872)  评论(0编辑  收藏  举报