Android 全局悬浮按钮,悬浮按钮点击事件,mWindowManager.addView

 1、申请悬浮与其他应用上的权限

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

 2、调用WindowManager.addView(view,params) 显示悬浮view。实现如微信视频通话,悬浮于所有应用之上

隐藏悬浮view   mWindowManager.removeView(mview);

 实现demo https://download.csdn.net/download/meixi_android/89447589

实现效果:

实现方法:

 在自定义baseActivity里面添加viwe即可。在子activity里刷新悬浮View即可

public abstract class BaseActivity extends BaseCommonActivity {

    LinearLayout saoli,ewmli;
    ImageView imageView;

    private QrCodeDialog mMQrCodeDialog;

    public static final int SECURITY_ACTIVITY_REQUEST_DD = 30008;

    //需要处理全屏逻辑之类的操作,在子类重写beforeSetContentView方法做处理
    @Override
    protected void beforeSetContentView() {
        super.beforeSetContentView();
        setTranslucentStatus();
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    //需要在每个Activity处理逻辑,直接在onCreate方法处理
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        createFloatActionButtons();
        ObServernotice.getInstance().addObserver(observer);

    }

    MyObserver observer = new MyObserver() {
        @Override
        public void update(int id, int intparameter, final String string, Bitmap bitmap) {
            if (id==999){

                if (intparameter==0){
                    saoli.setVisibility(View.GONE);
                    ewmli.setVisibility(View.GONE);
                }else if (intparameter==1){
                    saoli.setVisibility(View.VISIBLE);
                    ewmli.setVisibility(View.VISIBLE);

                    mMQrCodeDialog = new QrCodeDialog(BaseActivity.this) {
                        @Override
                        public String setIvQrCode() {
                            return QrActivity.QR_TAG_ORDER + string;
                        }
                    };
                    imageView.setImageBitmap(bitmap);

                }
            }
        }
    };

    private void createFloatActionButtons() {
        View v = getWindow().getLayoutInflater().inflate(R.layout.layout_float_action_buttons, null);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
        addContentView(v, layoutParams);
        saoli = findViewById(R.id.saoli);
        ewmli = findViewById(R.id.ewmli);
        imageView = findViewById(R.id.ddmaimg);
        initShowfloat();
        saoli.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                scan();
            }
        });
        ewmli.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mMQrCodeDialog != null) {
                    mMQrCodeDialog.show();
                }
            }
        });
    }

    public void initShowfloat(){
        int ss = ShareUtil.getSharedInt("floatint");
        if (ss==1){
            saoli.setVisibility(View.VISIBLE);
            ewmli.setVisibility(View.VISIBLE);
        }else {
            saoli.setVisibility(View.GONE);
            ewmli.setVisibility(View.GONE);
        }
        final String ewmstring =ShareUtil.getSharedString("ewmss");
        if (!TextUtils.isEmpty(ewmstring)){
            Bitmap bitmap = QRCodeEncoder.syncEncodeQRCode(QrActivity.QR_TAG_ORDER+ewmstring,
                    BGAQRCodeUtil.dp2px(BaseActivity.this, ResUtil.getPx(R.dimen.normal_340dp)),
                    ContextCompat.getColor(BaseActivity.this, R.color.black), null);
            mMQrCodeDialog = new QrCodeDialog(BaseActivity.this) {
                @Override
                public String setIvQrCode() {
                    return QrActivity.QR_TAG_ORDER + ewmstring;
                }
            };
            imageView.setImageBitmap(bitmap);

        }

    }

    private void scan() {
        startActivity(QrActivity.newIntent(this, 0));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
        @NonNull int[] grantResults) {
        PermissionUtil.getInstance(getApplicationContext())
            .onRequestPermissionsResult(requestCode, permissions, grantResults);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ObServernotice.getInstance().removeObserver(observer);
        observer = null;
    }
}

方法二:

machine_state_view文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <FrameLayout
        android:background="@mipmap/ic_jxz"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:layout_gravity="right|top"
            android:text="2"
           >

        </TextView>
    </FrameLayout>
</RelativeLayout>

AbstractDragFloatActionButton文件

/**
 *meixi
 */
public abstract class AbstractDragFloatActionButton extends RelativeLayout {
    private int parentHeight;//悬浮的父布局高度
    private int parentWidth;

    public AbstractDragFloatActionButton(Context context) {
        this(context, null, 0);
    }

    public AbstractDragFloatActionButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);

    }

    public abstract int getLayoutId();

    public abstract void renderView(View view);

    public AbstractDragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view= LayoutInflater.from(context).inflate(getLayoutId(), this);
        renderView(view);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }



    @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        View view = getChildAt(0);
        view.layout(0,0,view.getMeasuredWidth(),view.getMeasuredHeight());
    }

    private int lastX;
    private int lastY;

    private boolean isDrag;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                setPressed(true);//默认是点击事件
                isDrag=false;//默认是非拖动而是点击事件
                getParent().requestDisallowInterceptTouchEvent(true);//父布局不要拦截子布局的监听
                lastX=rawX;
                lastY=rawY;
                ViewGroup parent;
                if(getParent()!=null){
                    parent= (ViewGroup) getParent();
                    parentHeight=parent.getHeight();
                    parentWidth=parent.getWidth();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                isDrag = (parentHeight > 0 && parentWidth > 0);//只有父布局存在你才可以拖动
                if(!isDrag) break;

                int dx=rawX-lastX;
                int dy=rawY-lastY;
                //这里修复一些华为手机无法触发点击事件
                int distance= (int) Math.sqrt(dx*dx+dy*dy);
                isDrag = distance>0;//只有位移大于0说明拖动了
                if(!isDrag) break;

                float x=getX()+dx;
                float y=getY()+dy;
                //检测是否到达边缘 左上右下
                x=x<0?0:x>parentWidth-getWidth()?parentWidth-getWidth():x;
                y=y<0?0:y>parentHeight-getHeight()?parentHeight-getHeight():y;
                setX(x);
                setY(y);
                lastX=rawX;
                lastY=rawY;
                break;
            case MotionEvent.ACTION_UP:
                //如果是拖动状态下即非点击按压事件
                setPressed(!isDrag);
                break;
        }

        //如果不是拖拽,那么就不消费这个事件,以免影响点击事件的处理
        //拖拽事件要自己消费
        return isDrag || super.onTouchEvent(event);
    }

}

MachineStateView文件:

public class MachineStateView extends AbstractDragFloatActionButton {
    public static final String TAG = MachineStateView.class.getSimpleName();
    public MachineStateView(Context context) {
        super(context);
    }

    public MachineStateView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MachineStateView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public int getLayoutId() {
        return R.layout.machine_state_view;//拿到你自己定义的悬浮布局
    }

    @Override
    public void renderView(View view) {
        //初始化那些布局
        Log.e(TAG,"MachineStateView" + view.getId());

    }
}

引用MachineStateView即可

实现demo:https://download.csdn.net/download/meixi_android/12568936

在线bug交流:扣1085220040

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现可自由移动、监听点击事件悬浮窗,可以通过以下步骤来实现: 1. 在 AndroidManifest.xml 文件中添加悬浮窗权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. 创建一个浮动窗口布局的 xml 文件,在其中添加一个可移动的 View 控件和必要的监听事件。 3. 在 Service 中创建 WindowManager 对象,并使用 addView() 方法将浮动窗口布局添加到 WindowManager 中。 4. 在浮动窗口布局的 View 控件中实现 onTouchEvent() 方法,监听触摸事件,并根据触摸事件的坐标改变浮动窗口的位置。 5. 在浮动窗口布局的 View 控件中实现 OnClickListener() 方法,监听点击事件,并执行相应的操作。 6. 在 Service 的 onDestroy() 方法中使用 removeView() 方法将浮动窗口布局从 WindowManager 中移除,释放资源。 下面是一个简单的实现代码示例: ```java public class FloatWindowService extends Service { private WindowManager mWindowManager; private View mFloatView; private WindowManager.LayoutParams mParams; @Override public void onCreate() { super.onCreate(); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mFloatView = LayoutInflater.from(this).inflate(R.layout.float_window_layout, null); mParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mParams.gravity = Gravity.TOP | Gravity.LEFT; mParams.x = 0; mParams.y = 0; mWindowManager.addView(mFloatView, mParams); // 监听触摸事件,改变浮动窗口位置 mFloatView.setOnTouchListener(new View.OnTouchListener() { private int mLastX; private int mLastY; private int mDownX; private int mDownY; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = mParams.x; mLastY = mParams.y; mDownX = (int) event.getRawX(); mDownY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveX = (int) event.getRawX(); int moveY = (int) event.getRawY(); int dx = moveX - mDownX; int dy = moveY - mDownY; mParams.x = mLastX + dx; mParams.y = mLastY + dy; mWindowManager.updateViewLayout(mFloatView, mParams); break; } return false; } }); // 监听点击事件 mFloatView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 执行相应的操作 } }); } @Override public void onDestroy() { super.onDestroy(); mWindowManager.removeView(mFloatView); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值