IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【app】1.2 悬浮窗_移动 -> 正文阅读

[移动开发]【app】1.2 悬浮窗_移动

前言

当前实现了直接通过paint绘制一个圆显示在最上层。

尝试新增内容:
1 增加权限申请,因为如果未打开权限,点击绘制圆按钮,app会异常退出。
2 尝试通过layout.xml文件绘制悬浮窗,并设置悬浮球的view的范围为圆,而非长方形
3 新增view的移动和点击双事件区分
4 移动时view重新显示

1 增加权限申请

在activity创建中直接申请

代码来源:Android 可任意位置移动的悬浮窗

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //申请悬浮权限
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(getApplicationContext())) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                startActivityForResult(intent, 0);
            } else {
//                mIntent = new Intent(MainActivity.this/*需要启动service的activity*/, FloatWindowService.class/*需要启动的service*/);
//                bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);//直接启动服务方式启动
                Toast.makeText(getApplicationContext(), "open permission", Toast.LENGTH_SHORT).show();

            }
        }
   	}

在这里插入图片描述
在这里插入图片描述

2 使用layout定义view,代替paint

定义一个layout文件,设置float_window_small.xml
id为small_window_layout

float_window_small.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"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/small_window_layout"
    >

    <TextView
        android:id="@+id/percent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:text="@string/small_floatBall_text"
        android:textColor="#FF0000"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

布局效果
在这里插入图片描述

参考代码:Android 可任意位置移动的悬浮窗
仿照以下代码

LayoutInflater inflater = LayoutInflater.from(getApplication());
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_window, null, false);
View view = mFloatLayout.findViewById(R.id.playMonitor);//自定义悬浮窗布局
view.setOnTouchListener(this);//设置移动监听,此处view是自定义充满布局的控件
mWindowManager.addView(mFloatLayout, wp);

1 获取应用的布局服务
2 使用inflate()函数初始化定义布局mFloatLayout,注意参数为layout信息
3 查找到对应view的id
4 监听到移动
5 添加view?存疑,在监听中使用到了updateViewLayout,这里又用了addview

2.1 显示大小问题

layout和view关系:我理解的是一个activity对应一个window,window中可以包含多个view,而view的内容就包含布局layout,布局可分为5种,布局中又包含多个控件。
参考:android layout与view机制
activity–window–view–layout–textview/button

需要注意两点。
view/layout的长宽定义在layoutparam中,即代码中看到的viewparams,类型为WindowManager.LayoutParams。
在set_viewparams中有定义,view的长宽为100,view的起始点(左上角)在(200,200)位置。

            //窗口长宽,注意与view一致
            viewparams.width = 100;
            viewparams.height = 100;
            //子控件,居左居上
            viewparams.gravity = Gravity.LEFT | Gravity.TOP;
            //起始位置      // 相对于创建的窗口位置
            viewparams.x = 200;
            viewparams.y = 200;

在strings.xml文件中定义了textview的显示内容

<resources>
    <string name="app_name">demo_v3_addmove</string>
    <string name="small_floatBall_text">11111111</string>
</resources>

所以,呈现的效果是
在这里插入图片描述
我们尝试将显示内容增多

<resources>
    <string name="app_name">demo_v3_addmove</string>
    <string name="small_floatBall_text">111111111111</string>
</resources>

效果一致。

尝试将viewparams参数的长宽变大
viewparams.width=200;
viewparams.height=200;
在这里插入图片描述
这时候发现显示变了,第一行显示9个1,第二行

2.2 更新view函数

updateViewLayout和addview

2.2.1 LayoutInflater布局服务

参考文章:LayoutInflater(布局服务)

获取LayoutInflater:

LayoutInflater inflater1 = LayoutInflater.from(this);  
LayoutInflater inflater2 = getLayoutInflater();  
LayoutInflater inflater3 = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); 

2.3 差异

使用layout创建悬浮球。
执行修改颜色函数时,显示的颜色就改变了,不需要wm移除后添加。
存疑:是否自定义view也可以实现。不适用,再找其他方法
设定颜色时会调用updateTextColors(),更新text颜色。

    public void setTextColor(int color) {
        mTextColor = ColorStateList.valueOf(color);
        updateTextColors();
    }

测试发现,第一次显示layout时,点击layout,颜色无法改变,应该是未识别到点击事件?
原因:我把创建点击layout监听放在了closebutton里了,移动到openbutton就可以。

待办:如何实现在layout上画图,然后填充颜色自定义。

3 尝试使用windowmanager自定义函数更新view

之前已有的一项功能时点击view时,颜色变为绿色,使用的方法时先移除view,再重新添加。
打算使用下WindowManager.updateViewLayout(),看看是否有效。

在click监听中新增


    public class touchfloatballview_youkaiListener implements View.OnClickListener {
        @Override
        public void onClick(View arg0) {
            if (mWindowManager != null) {
                Toast.makeText(getApplicationContext(), "change ball color", Toast.LENGTH_SHORT).show();
//                ball.paint.setColor(Color.GREEN);//设置颜色为红
//                ball.cx = 50;
                ball.cy = 50;
//                ball.();
//                mWindowManager.updateViewLayout(ball, viewparams);

                if (ball_status == false) {
                    record_on();
                } else if (ball_status == true) {
                    record_off();
                } else
                    Log.d("", "error value");

				//方法1.先移除再添加
                remove_view();
                add_view();
                //方法2.直接使用WindowManager.updateViewLayout
                mWindowManager.updateViewLayout(ball,viewparams);

                if (ball.getVisibility() == View.VISIBLE) {
                    Toast.makeText(getApplicationContext(), "view display", Toast.LENGTH_SHORT).show();
                }
            }
            //(ball,viewparams);
        }
    }

测试失败。

3.1 参考文章

view 的绘制和刷新

Android屏幕刷新机制

4 拖动悬浮球

4.1 参考文章

Android 可任意位置移动的悬浮窗

关于View的setOnTouchListener和setOnClickListener冲突

用户手势检测-GestureDetector使用详解

Android MotionEvent详解

4.2 分析功能

view监听触摸事件,其中主要是三种:按下ACTION_DOWN,移动ACTION_MOVE,弹起ACTION_UP。

与此同时还有一点是view的坐标,若改变则需要重新绘制view,进行刷新。

刷新条件:
1 监听到up事件
2 监听到移动,同步刷新

参考文章:可拖拽悬浮窗、对话框悬浮窗的简单实现

这里需要注意的一点,参考文章使用的是touch监听,而我之前写过一个click监听,主要是监听悬浮框的点击,来实现录制和停止。

4.3 实现


    public class touchfloatballview_youkaiListener implements View.OnClickListener {
        @Override
        public void onClick(View arg0) {
            if (mWindowManager != null) {
                if (ball_status == false) {
                    record_on();
                } else if (ball_status == true) {
                    record_off();
                } else
                    Log.d("", "error value");

                remove_view();
                add_view();
            }
        }
    }

// 代码来源:https://www.cnblogs.com/tianzhijiexian/p/3994546.html
    private class FloatingListener implements View.OnTouchListener {
        @Override
        public boolean onTouch(View arg0, MotionEvent event) {

            int action = event.getAction();
            switch(action){
                case MotionEvent.ACTION_DOWN:
                    isMove = false;
                    mTouchStartX = (int)event.getRawX();
                    mTouchStartY = (int)event.getRawY();
                    mStartX = (int)event.getX();
                    mStartY = (int)event.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    mTouchCurrentX = (int) event.getRawX();
                    mTouchCurrentY = (int) event.getRawY();
                    viewparams_layout.x += mTouchCurrentX - mTouchStartX;
                    viewparams_layout.y += mTouchCurrentY - mTouchStartY;
                    mWindowManager.updateViewLayout(mlayout, viewparams_layout);

                    mTouchStartX = mTouchCurrentX;
                    mTouchStartY = mTouchCurrentY;
                    break;
                case MotionEvent.ACTION_UP:
                    mStopX = (int)event.getX();
                    mStopY = (int)event.getY();
                    //System.out.println("|X| = "+ Math.abs(mStartX - mStopX));
                    //System.out.println("|Y| = "+ Math.abs(mStartY - mStopY));
                    if(Math.abs(mStartX - mStopX) >= 1 || Math.abs(mStartY - mStopY) >= 1){
                        isMove = true;
                    }
                    break;
            }
            return mGestureDetector.onTouchEvent(event);  //此处必须返回false,否则OnClickListener获取不到监听
        }
    }

在打开layout view的button监听中创建上述两个监听,分别是click监听录制和播放,touch监听移动


    public class openlayoutviewListener implements OnClickListener {
        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            // display status in textview "button on"
            text = (TextView) findViewById(R.id.textView);
            text.setText("layoutview on");

            Toast.makeText(getApplicationContext(), "layoutview on", Toast.LENGTH_SHORT).show();

            if(status_layoutview == false){
                mWindowManager.addView(mlayout, viewparams_layout);
                status_layoutview = true;
            }

            // listen for floatingtextview touch
            mlayout.setOnClickListener(new touchlayoutview_youkaiListener());
            mlayout.setOnTouchListener(new FloatingListener());
        }
    }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-11 17:38:03  更:2021-10-11 17:38:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:30:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码