Android悬浮球和悬浮条的开发

一般做sdk都需要我们做一个可拖拽的悬浮球,点击悬浮球展示悬浮条 (无需任何权限!!!)

调用代码

public class MainActivity extends AppCompatActivity {


    private MyFloatView myFloatView;

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

    @Override
    protected void onResume() {
        super.onResume();
    }

    public void dismiss(View view) {
        if (myFloatView != null)
            myFloatView.dismiss();
    }

    public void show(View view) {
        if (myFloatView == null){
            myFloatView = new MyFloatView(this,true);
        }
        myFloatView.show();
    }
}

布局代码 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity">

    <View
        android:onClick="show"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />
    <View
        android:background="@color/black"
        android:layout_width="3dp"
        android:layout_height="match_parent"/>

    <View
        android:onClick="dismiss"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

layout_left_menu.xml

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@android:drawable/ic_input_get" />

    <ImageView
        android:id="@+id/iv_left_one"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@android:drawable/ic_menu_compass" />
</LinearLayout>

layout_right_menu.xml

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

    <ImageView
        android:id="@+id/iv_right_one"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@android:drawable/ic_menu_compass" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:src="@android:drawable/ic_input_get" />
</LinearLayout>

> MyFloatView.java
```java
package com.example.myapplication;

import android.app.Service;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;

public class MyFloatView extends LinearLayout {

    private WindowManager wm;
    private WindowManager.LayoutParams floatParams;
    private boolean isShowFloatBar;
    private boolean isFloatShow;
    private float downX;
    private float downY;
    private int screenW;
    private int screenH;
    private LinearLayout leftMenu;
    private LinearLayout rightMenu;
    private int floatW;
    private int floatH;
    private float downRawX;
    private float downRawY;
    private float menuW;

    public MyFloatView(@NonNull Context context,boolean isShowFloatBar) {
        super(context);
        this.isShowFloatBar = isShowFloatBar;
        getScreenInfo(context);
        createContentView(context);
        createWindowManager(context);
        setOrientation(LinearLayout.HORIZONTAL);
    }

    /**
     * 创建悬浮窗
     * @param context
     */
    private void createContentView(Context context) {
        ImageView floatView = new ImageView(context);
        floatView.setImageResource(android.R.drawable.ic_menu_add);
        addView(floatView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        measureChild(floatView,MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
        floatW = floatView.getMeasuredWidth();
        floatH = floatView.getMeasuredHeight();
        if (isShowFloatBar){
            createFloatBarView(context);
        }
    }

    /**
     * 创建悬浮条
     * @param context
     */
    private void createFloatBarView(Context context){
        leftMenu = (LinearLayout) View.inflate(context,R.layout.layout_left_menu,null);
        rightMenu = (LinearLayout) View.inflate(context,R.layout.layout_right_menu,null);
        leftMenu.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
        menuW = leftMenu.getMeasuredWidth();

        leftMenu.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                dismissMenu();
            }
        });
        rightMenu.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                dismissMenu();
            }
        });
    }

    /**
     * 初始化windowmanager,我们用它来加载悬浮窗
     * @param context
     */
    private void createWindowManager(Context context) {
        wm = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
        floatParams = new WindowManager.LayoutParams();
        floatParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        floatParams.height = floatH;
        floatParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
        floatParams.gravity = Gravity.LEFT | Gravity.TOP;
        floatParams.x = 0;
        floatParams.y = screenH / 2;
        floatParams.format = PixelFormat.RGBA_8888;
    }

    /**
     * 获取屏幕宽高信息
     * @param context
     */
    private void getScreenInfo(Context context){
        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        screenW = displayMetrics.widthPixels;
        screenH = displayMetrics.heightPixels;
    }

    /**
     * 悬浮条是否展示当中
     * @return
     */
    private boolean isMenuDisplay(){
        return getChildCount() > 1;
    }

    /**
     * 此时悬浮窗的位置是否在左边
     * @return
     */
    private boolean isFloatSlideLeft(){
        return floatParams.x + floatW /2 <= screenW /2;
    }

    /**
     * 展示悬浮条
     */
    private void showMenu() {
        if (isFloatSlideLeft()){
            addView(rightMenu,1);
        }else{
            addView(leftMenu,0);
            floatParams.x = (int) (floatParams.x - menuW);
            wm.updateViewLayout(MyFloatView.this,floatParams);
        }
    }

    /**
     * 隐藏悬浮条
     */
    private void dismissMenu() {
        if (isFloatSlideLeft()){
            removeView(rightMenu);
        }else{
            floatParams.x = (int) (floatParams.x + menuW);
            wm.updateViewLayout(this,floatParams);
            removeView(leftMenu);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                downRawX = event.getRawX();
                downRawY = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isMenuDisplay()){
                    float rawX = event.getRawX();
                    float rawY = event.getRawY();
                    floatParams.x = (int) (rawX - downX);
                    floatParams.y = (int) (rawY - downY);
                    wm.updateViewLayout(this,floatParams);//通过手指拖动改变悬浮球的位置
                }
                break;
            case MotionEvent.ACTION_UP:
                float upRawX = event.getRawX();
                float upRawY = event.getRawY();
                float absX = Math.abs(upRawX - downRawX);
                float absY = Math.abs(upRawY - downRawY);
                if (isShowFloatBar && (absX < 0.2f || absY < 0.2f)){//单机悬浮球
                    if (isMenuDisplay()){
                        dismissMenu();
                    }else{
                        showMenu();
                    }
                }else{
                    if (!isShowFloatBar || !isMenuDisplay()){//悬浮球自动靠边
                        floatParams.x = isFloatSlideLeft() ? 0 : screenW - floatW;
                        if (upRawY < floatH) floatParams.y = 0;
                        if (upRawY > screenH - floatH) floatParams.y = screenH - floatH;
                        wm.updateViewLayout(this,floatParams);
                    }
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    public void show(){
        if (!isFloatShow){
            isFloatShow = true;
            floatParams.x = 0;
            floatParams.y = screenH / 2;
            wm.addView(this,floatParams);
        }
    }

    public void dismiss(){
        if (isFloatShow){
            if (isMenuDisplay()){
                if (isFloatSlideLeft()){
                    removeView(rightMenu);
                }else{
                    removeView(leftMenu);
                }
            }
            isFloatShow = false;
            wm.removeView(this);
        }
    }

}

posted @ 2022-08-18 15:51  呢哇哦比较  阅读(735)  评论(0)    收藏  举报