Android实现APP内悬浮框效果

Posted 事在人为,幸福从不抱怨开始!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.效果图

以上是关于Android实现APP内悬浮框效果的主要内容,如果未能解决你的问题,请参考以下文章

Android音视频通话过程中最小化成悬浮框的实现(类似Android8.0画中画效果)

Android——自由拖动并显示文字的悬浮框实现

Android中的WindowWindowManager以及悬浮框视频播放的实现

Android中的WindowWindowManager以及悬浮框视频播放的实现

Android activity内实现可拖拽悬浮控件

Android activity内实现可拖拽悬浮控件