千家信息网

Android如何仿IOS系统实现悬浮窗效果

发表于:2025-01-17 作者:千家信息网编辑
千家信息网最后更新 2025年01月17日,这篇文章主要介绍Android如何仿IOS系统实现悬浮窗效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!代码如下:在这之前,我们需要在manifest中申请权限:并且,悬浮窗
千家信息网最后更新 2025年01月17日Android如何仿IOS系统实现悬浮窗效果

这篇文章主要介绍Android如何仿IOS系统实现悬浮窗效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

代码如下:

在这之前,我们需要在manifest中申请权限:

并且,悬浮窗这个权限我们需要手动在手机找到应用权限管理,允许这个权限才行

小悬浮窗的界面代码float_normal_view.xml:

        

大悬浮窗的界面代码float_control_view:

                                    

入口activity(FloatActivity ):

public class FloatActivity extends Activity {    MyWindowManager myWindowManager;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        myWindowManager = MyWindowManager.getInstance();        myWindowManager.createNormalView(this.getApplicationContext());    }}

悬浮窗管理器MyWindowManager:

/** * Created by shiweixian on 2017/3/7. * 悬浮窗管理器 * 创建,移除 * 单例模式 */public class MyWindowManager {    private FloatNormalView normalView;    private FloatControlView controlView;    private static MyWindowManager instance;    private WindowManager windowManager;    private MyWindowManager() {    }    public static MyWindowManager getInstance() {        if (instance == null)            instance = new MyWindowManager();        return instance;    }    private WindowManager getWindowManager(Context context) {        if (windowManager == null)            windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        return windowManager;    }    /**     * 判断小悬浮窗是否存在     *     * @return     */    public boolean isNormalViewExists() {        return normalView != null;    }    /**     * 判断播放器这个大悬浮窗是否存在     *     * @return     */    public boolean isControlViewExists() {        return controlView != null;    }    /**     * 创建小型悬浮窗     */    public void createNormalView(Context context) {        if (normalView == null) {            normalView = new FloatNormalView(context);        }    }    /**     * 移除悬浮窗     *     * @param context     */    public void removeNormalView(Context context) {        if (normalView != null) {            windowManager.removeView(normalView);            normalView = null;        }    }    /**     * 创建小型悬浮窗     */    public void createControlView(Context context) {        if (controlView == null)            controlView = new FloatControlView(context);    }    /**     * 移除悬浮窗     *     * @param context     */    public void removeControlView(Context context) {        if (controlView != null) {            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);            windowManager.removeView(controlView);            controlView = null;        }    }}

小悬浮窗FloatNormalView:

/** * Created by shiwe on 2017/3/7. * 缩小的悬浮窗 */public class FloatNormalView extends LinearLayout {    /**     * 记录小悬浮窗的宽度     */    public static int viewWidth;    /**     * 记录小悬浮窗的高度     */    public static int viewHeight;    /**     * 记录系统状态栏的高度     */    private static int statusBarHeight;    /**     * 用于更新小悬浮窗的位置     */    private WindowManager windowManager;    /**     * 小悬浮窗的参数     */    private WindowManager.LayoutParams mParams;    /**     * 记录当前手指位置在屏幕上的横坐标值     */    private float xInScreen;    /**     * 记录当前手指位置在屏幕上的纵坐标值     */    private float yInScreen;    /**     * 记录手指按下时在屏幕上的横坐标的值     */    private float xDownInScreen;    /**     * 记录手指按下时在屏幕上的纵坐标的值     */    private float yDownInScreen;    /**     * 记录手指按下时在小悬浮窗的View上的横坐标的值     */    private float xInView;    /**     * 记录手指按下时在小悬浮窗的View上的纵坐标的值     */    private float yInView;    public FloatNormalView(Context context) {        super(context);        windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        LayoutInflater.from(context).inflate(R.layout.float_normal_view, this);        View view = findViewById(R.id.ll_float_normal);        viewWidth = view.getLayoutParams().width;        viewHeight = view.getLayoutParams().height;        initLayoutParams();    }    /**     * 初始化参数     */    private void initLayoutParams() {        //屏幕宽高        int screenWidth = windowManager.getDefaultDisplay().getWidth();        int screenHeight = windowManager.getDefaultDisplay().getHeight();        mParams = new WindowManager.LayoutParams();        //总是出现在应用程序窗口之上。        mParams.type = WindowManager.LayoutParams.TYPE_PHONE;        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口        // FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;        //悬浮窗默认显示的位置        mParams.gravity = Gravity.START | Gravity.TOP;        //指定位置        mParams.x = screenWidth - viewWidth * 2;        mParams.y = screenHeight / 2 + viewHeight * 2;        //悬浮窗的宽高        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;        mParams.format = PixelFormat.TRANSPARENT;        windowManager.addView(this, mParams);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度                xInView = event.getX();                yInView = event.getY();                xDownInScreen = event.getRawX();                yDownInScreen = event.getRawY() - getStatusBarHeight();                xInScreen = event.getRawX();                yInScreen = event.getRawY() - getStatusBarHeight();                break;            case MotionEvent.ACTION_MOVE:                xInScreen = event.getRawX();                yInScreen = event.getRawY() - getStatusBarHeight();                // 手指移动的时候更新小悬浮窗的位置                updateViewPosition();                break;            case MotionEvent.ACTION_UP:                // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。                if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {                    openOrCloseControlView();                }                break;            default:                break;        }        return true;    }    /**     * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。     *     * @param params 小悬浮窗的参数     */    public void setParams(WindowManager.LayoutParams params) {        mParams = params;    }    /**     * 更新小悬浮窗在屏幕中的位置。     */    private void updateViewPosition() {        mParams.x = (int) (xInScreen - xInView);        mParams.y = (int) (yInScreen - yInView);        windowManager.updateViewLayout(this, mParams);    }    /**     * 打开或关闭大悬浮窗。     */    private void openOrCloseControlView() {        MyWindowManager manager = MyWindowManager.getInstance();        if (!manager.isControlViewExists())            manager.createControlView(getContext());        else            manager.removeControlView(getContext());    }    /**     * 用于获取状态栏的高度。     *     * @return 返回状态栏高度的像素值。     */    private int getStatusBarHeight() {        if (statusBarHeight == 0) {            try {                Class c = Class.forName("com.android.internal.R$dimen");                Object o = c.newInstance();                Field field = c.getField("status_bar_height");                int x = (Integer) field.get(o);                statusBarHeight = getResources().getDimensionPixelSize(x);            } catch (Exception e) {                e.printStackTrace();            }        }        return statusBarHeight;    }}

大悬浮窗FloatControlView:

/** * Created by shiwe on 2017/3/7. * 缩小的悬浮窗 */public class FloatNormalView extends LinearLayout {    /**     * 记录小悬浮窗的宽度     */    public static int viewWidth;    /**     * 记录小悬浮窗的高度     */    public static int viewHeight;    /**     * 记录系统状态栏的高度     */    private static int statusBarHeight;    /**     * 用于更新小悬浮窗的位置     */    private WindowManager windowManager;    /**     * 小悬浮窗的参数     */    private WindowManager.LayoutParams mParams;    /**     * 记录当前手指位置在屏幕上的横坐标值     */    private float xInScreen;    /**     * 记录当前手指位置在屏幕上的纵坐标值     */    private float yInScreen;    /**     * 记录手指按下时在屏幕上的横坐标的值     */    private float xDownInScreen;    /**     * 记录手指按下时在屏幕上的纵坐标的值     */    private float yDownInScreen;    /**     * 记录手指按下时在小悬浮窗的View上的横坐标的值     */    private float xInView;    /**     * 记录手指按下时在小悬浮窗的View上的纵坐标的值     */    private float yInView;    public FloatNormalView(Context context) {        super(context);        windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        LayoutInflater.from(context).inflate(R.layout.float_normal_view, this);        View view = findViewById(R.id.ll_float_normal);        viewWidth = view.getLayoutParams().width;        viewHeight = view.getLayoutParams().height;        initLayoutParams();    }    /**     * 初始化参数     */    private void initLayoutParams() {        //屏幕宽高        int screenWidth = windowManager.getDefaultDisplay().getWidth();        int screenHeight = windowManager.getDefaultDisplay().getHeight();        mParams = new WindowManager.LayoutParams();        //总是出现在应用程序窗口之上。        mParams.type = WindowManager.LayoutParams.TYPE_PHONE;        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口        // FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;        //悬浮窗默认显示的位置        mParams.gravity = Gravity.START | Gravity.TOP;        //指定位置        mParams.x = screenWidth - viewWidth * 2;        mParams.y = screenHeight / 2 + viewHeight * 2;        //悬浮窗的宽高        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;        mParams.format = PixelFormat.TRANSPARENT;        windowManager.addView(this, mParams);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度                xInView = event.getX();                yInView = event.getY();                xDownInScreen = event.getRawX();                yDownInScreen = event.getRawY() - getStatusBarHeight();                xInScreen = event.getRawX();                yInScreen = event.getRawY() - getStatusBarHeight();                break;            case MotionEvent.ACTION_MOVE:                xInScreen = event.getRawX();                yInScreen = event.getRawY() - getStatusBarHeight();                // 手指移动的时候更新小悬浮窗的位置                updateViewPosition();                break;            case MotionEvent.ACTION_UP:                // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。                if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {                    openOrCloseControlView();                }                break;            default:                break;        }        return true;    }    /**     * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。     *     * @param params 小悬浮窗的参数     */    public void setParams(WindowManager.LayoutParams params) {        mParams = params;    }    /**     * 更新小悬浮窗在屏幕中的位置。     */    private void updateViewPosition() {        mParams.x = (int) (xInScreen - xInView);        mParams.y = (int) (yInScreen - yInView);        windowManager.updateViewLayout(this, mParams);    }    /**     * 打开或关闭大悬浮窗。     */    private void openOrCloseControlView() {        MyWindowManager manager = MyWindowManager.getInstance();        if (!manager.isControlViewExists())            manager.createControlView(getContext());        else            manager.removeControlView(getContext());    }    /**     * 用于获取状态栏的高度。     *     * @return 返回状态栏高度的像素值。     */    private int getStatusBarHeight() {        if (statusBarHeight == 0) {            try {                Class c = Class.forName("com.android.internal.R$dimen");                Object o = c.newInstance();                Field field = c.getField("status_bar_height");                int x = (Integer) field.get(o);                statusBarHeight = getResources().getDimensionPixelSize(x);            } catch (Exception e) {                e.printStackTrace();            }        }        return statusBarHeight;    }}

以上是"Android如何仿IOS系统实现悬浮窗效果"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0