Android实现APP内悬浮框效果

2020年上班第一篇:实现在APP内悬浮框效果。可以打开,可以关闭,可以拖动,当然可以实现悬浮框点击事件。直接上代码:

  1. 主界面
public class FloatingActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_floating);
        ButterKnife.bind(this);
    }

    @OnClick({R.id.open_floating, R.id.close_floating})
    public void buttonClick(View view) {
        switch (view.getId()) {
            case R.id.open_floating:
                showFloatingDialog();
                break;
            case R.id.close_floating:
                FloatingDialogManager.getInstance(this).hideFloatingWindow();
                break;
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void showFloatingDialog() {
        //判断悬浮框权限
        if (!Settings.canDrawOverlays(this)) {
            Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT);
            //跳转到系统授权页面
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 0);
        } else {
            FloatingDialogManager.getInstance(this).showFloatingWindow();
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
            } else {
                FloatingDialogManager.getInstance(this).showFloatingWindow();
            }
        }
    }
}

2.主界面布局:

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

    <TextView
        android:id="@+id/open_floating"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_margin="10dp"
        android:gravity="center"
        android:text="开启悬浮"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/close_floating"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_margin="10dp"
        android:gravity="center"
        android:text="关闭悬浮"
        android:textSize="16sp"
        android:textStyle="bold" />
</LinearLayout>

3.悬浮框工具类:

import static android.content.Context.WINDOW_SERVICE;


public class FloatWindowManager {
    private volatile static FloatWindowManager instance = null;
    private Activity mAct;
    private WindowManager windowManager;
    private WindowManager.LayoutParams layoutParams;
    private TextView button;


    private FloatWindowManager(Activity activity) {
        this.mAct = activity;
        init(mAct);
    }

    private void init(Activity activity) {
        windowManager = (WindowManager) activity.getSystemService(WINDOW_SERVICE);
        layoutParams = new WindowManager.LayoutParams();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        layoutParams.format = PixelFormat.RGBA_8888;
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        layoutParams.width = 150;
        layoutParams.height = 150;
        layoutParams.x = AppInfoUitl.getScreenWidth(mAct) - 100;
        layoutParams.y = AppInfoUitl.getScreenHeight(mAct) - 350;
    }

    public static FloatWindowManager getInstance(Activity mAct) {
        if (instance == null) {
            synchronized (FloatWindowManager.class) {
                if (instance == null) {
                    instance = new FloatWindowManager(mAct);
                }
            }
        }
        return instance;

    }


    @TargetApi(Build.VERSION_CODES.M)
    public void showFloatingWindow() {
        if (Settings.canDrawOverlays(mAct)) {
            button = new TextView(mAct);
//            button.setText("意见反馈");
//            button.setWidth(64);
//            button.setHeight(64);
            Drawable drawable = mAct.getResources().getDrawable(R.drawable.feed_back_float);
            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
            button.setCompoundDrawables(null, drawable, null, null);
            button.setText("反馈");
            button.setGravity(Gravity.CENTER);
            button.setPadding(5, 5, 5, 5);
//            button.setBackgroundResource(R.drawable.blue_rect);
            button.setTextColor(mAct.getResources().getColor(R.color.blue_text_color));
            windowManager.addView(button, layoutParams);

            button.setOnTouchListener(new FloatingOnTouchListener());
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(mAct.getApplicationContext(), AccountFeedbackActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    mAct.startActivity(intent);
                }
            });
        }
        EsnopApplication.getApplication().setFloatingShown(true);
    }

    public void hideFloatingWindow() {
        if (null != button && windowManager != null) {
            windowManager.removeViewImmediate(button);
        }
        EsnopApplication.getApplication().setFloatingShown(false);
    }

    private class FloatingOnTouchListener implements View.OnTouchListener {
        private int x;
        private int y;
        private long startTime = 0;
        private long endTime = 0;

        private boolean isclick;

        @Override
        public boolean onTouch(View view, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    x = (int) event.getRawX();
                    y = (int) event.getRawY();
                    isclick = false;//当按下的时候设置isclick为false,具体原因看后边的讲解
                    startTime = System.currentTimeMillis();
                    break;
                case MotionEvent.ACTION_MOVE:
                    isclick = true;
                    int nowX = (int) event.getRawX();
                    int nowY = (int) event.getRawY();
                    int movedX = nowX - x;
                    int movedY = nowY - y;
                    x = nowX;
                    y = nowY;
                    layoutParams.x = layoutParams.x + movedX;
                    layoutParams.y = layoutParams.y + movedY;
                    windowManager.updateViewLayout(view, layoutParams);
                    break;
                case MotionEvent.ACTION_UP:
                    endTime = System.currentTimeMillis();
                    //当从点击到弹起小于200毫秒的时候,则判断为点击,如果超过则不响应点击事件
                    if ((endTime - startTime) > 0.2 * 1000L) {
                        isclick = true;
                    } else {
                        isclick = false;
                    }
                    break;
                default:
                    break;
            }
            return isclick;
        }
    }

}

4.添加权限

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

5.效果图
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值