序言

前些日子跟朋友聊天,朋友Z果粉,前些天更新了微信,说微信出了个好方便的功能啊,我问是啥功能啊,看看我大Android有没有,他说现在阅读公众号文章如果有人给你发微信你可以把这篇文章当作悬浮窗悬浮起来,方便你聊完天不用找继续阅读,听完是不是觉得这叫啥啊,我大Android微信版不是早就有这个功能了吗,我看文章的时候看到过有这个悬浮按钮,但是我一直没有使用过,试了一下还是挺方便的,就想着自己实现一下这个功能,下面看图,大家都习惯了无图言X

原理

看完动图我们来分析一下,如何在每个页面上都存在一个View呢,有些人可能会说,写在base里面,这样每次启动一个新的Activity都要往页面上addView一次,性能不好,再说了,我们作为一个优秀的程序员能干这种重复的事吗,这种方案果断打回去;既然这样的话那我们肯定要在全局加了,那么全局是哪呢?相信了解过Activity源码的朋友肯定知道,全局可以在Window层加啊,这样既能一次性搞定,又不影响性能,说干就干。

实现

1、权限

首先我们要考虑的一个问题就是权限问题,因为要适配Android 7.0 8.0,添加悬浮窗是需要申请权限的,适配的比较全,可以直接拿来用。这里需要注意的是,为了适配Android 8.0,Window的类型需要配置一下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

//Android 8.0

mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

} else {

//其他版本

mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;

}

2、添加ViewGroup到Window

判断好权限之后,直接添加就可以了

@SuppressLint("CheckResult")

private void showWindow(Context context) {

mWindowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);

mView = LayoutInflater.from(context).inflate(R.layout.article_window, null);

ImageView ivImage = mView.findViewById(R.id.aw_iv_image);

String imageUrl = SPUtil.getStringDefault(ARTICLE_IMAGE_URL, "");

RequestOptions requestOptions = RequestOptions.circleCropTransform();

requestOptions.placeholder(R.mipmap.ic_launcher_round).error(R.mipmap.ic_launcher_round);

Glide.with(context).load(imageUrl).apply(requestOptions).into(ivImage);

initListener(context);

mLayoutParams = new WindowManager.LayoutParams();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

} else {

mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

}

mLayoutParams.format = PixelFormat.RGBA_8888; //窗口透明

mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; //窗口位置

mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

mLayoutParams.width = 200;

mLayoutParams.height = 200;

mLayoutParams.x = mWindowManager.getDefaultDisplay().getWidth() - 200;

mLayoutParams.y = 0;

mWindowManager.addView(mView, mLayoutParams);

}

3、View的拖拽实现

借助WindowManager.LayoutParams来实现,mLayoutParams.x和mLayoutParams.y分别表示mView左上角的横纵坐标,所以我们只需要改动这两个值就行了,当ACTION_UP时,计算当前mView的中心点相对窗口的位置,然后将mView动态滑动到窗口左边或者右边:

//设置触摸滑动事件

mView.setOnTouchListener(new View.OnTouchListener() {

int startX, startY; //起始点

boolean isMove; //是否在移动

long startTime;

int finalMoveX; //最后通过动画将mView的X轴坐标移动到finalMoveX

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

startX = (int) event.getX();

startY = (int) event.getY();

startTime = System.currentTimeMillis();

isMove = false;

return false;

case MotionEvent.ACTION_MOVE:

mLayoutParams.x = (int) (event.getRawX() - startX);

mLayoutParams.y = (int) (event.getRawY() - startY);

updateViewLayout(); //更新mView 的位置

return true;

case MotionEvent.ACTION_UP:

long curTime = System.currentTimeMillis();

isMove = curTime - startTime > 100;

//判断mView是在Window中的位置,以中间为界

if (mLayoutParams.x + mView.getMeasuredWidth() / 2 >= mWindowManager.getDefaultDisplay().getWidth() / 2) {

finalMoveX = mWindowManager.getDefaultDisplay().getWidth() - mView.getMeasuredWidth();

} else {

finalMoveX = 0;

}

//使用动画移动mView

ValueAnimator animator = ValueAnimator.ofInt(mLayoutParams.x, finalMoveX).setDuration(Math.abs(mLayoutParams.x - finalMoveX));

animator.addUpdateListener((ValueAnimator animation) -> {

mLayoutParams.x = (int) animation.getAnimatedValue();

updateViewLayout();

});

animator.start();

return isMove;

}

return false;

}

});

4、注意

为了让Window与Activity脱离,这里我们采用Service来做,通过Service来添加和移除View;在权限申请成功之后我们需要通知Service(其实是Activity,可能会有保存数据等操作)作相应改变(提供一个接口给Service),然后在Service中使用广播来通知Activity;最后一个需要注意的地方就是我们需要判断应用程序是否在前台还是后台来添加或移除Window,这里通过使用ActivityLifecycleCallbacks来监听Activity在前台的数量来判断应用程序是在前台还是后台

class ApplicationLifecycle : Application.ActivityLifecycleCallbacks {

private var started: Int = 0

override fun onActivityPaused(activity: Activity?) {

}

override fun onActivityResumed(activity: Activity?) {

}

override fun onActivityStarted(activity: Activity?) {

started++

if (started == 1) {

Log.e("TAG", "应用在前台了!!!")

}

}

override fun onActivityDestroyed(activity: Activity?) {

}

override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {

}

override fun onActivityStopped(activity: Activity?) {

started--

if (started == 0) {

Log.e("TAG", "应用在后台了!!!")

}

}

override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {

}

}

本文代码已传至Github,有需要的朋友可以下载下来看看。

总结

以上所述是小编给大家介绍的Android仿微信文章悬浮窗效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对dt猫网站的支持!

android 微信浮窗实现_Android仿微信文章悬浮窗效果的实现代码相关推荐

  1. android 微信浮窗实现_Android仿微信视屏悬浮窗效果

    在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点. 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频 ...

  2. android仿微信下拉二楼_Android仿微信下拉列表实现

    本文要实现微信6.1中点击顶部菜单栏的"+"号按钮时,会弹出一个列表框.这里用的了Activity实现,其实最好的方法可以用ActionBar,不过这货好像只支持3.0以后的版本. ...

  3. java实现仿微信app聊天功能_Android仿微信语音聊天功能

    本文实例讲述了Android仿微信语音聊天功能代码.分享给大家供大家参考.具体如下: 项目效果如下: 具体代码如下: AudioManager.java package com.xuliugen.we ...

  4. 安卓开发仿微信图片拖拽_Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)...

    [实例简介] Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动) [实例截图] [核心代码] ImageDemo-2014-02-18 └── ImageDemo-2014-02-18 ├ ...

  5. 安卓开发仿微信图片拖拽_Android 仿微信朋友圈图片拖拽返回

    目前的app的动画效果是越来越炫了,很多主流app的图片预览返回都有类似功能,比较常见的是ios自带相册,微信朋友圈等等.自己项目中也有类似功能,最近整理了一下这个功能的代码,做个笔记记录,有兴趣的朋 ...

  6. android 微信缩小通话界面_Android仿微信多人音视频通话界面

    工作中需要实现一个类似微信多人视频通话功能的界面,分别使用自定义viewgroup和自定义layoutmanager的方式进行了实现.最终工作中采用了layoutmanager,因为可以使用paylo ...

  7. 安卓开发仿微信图片拖拽_Android 仿微信朋友圈发表图片拖拽和删除功能

    朋友圈实现原理 我们使用 Android Device Monitor 来分析朋友圈发布图片的界面实现原理.如果需要分析其他应用的界面实现也是采用这种方法哦. 打开 Android Device Mo ...

  8. 基于微信小程序开发的仿微信demo

    (本文参考自github/liujians,地址:https://github.com/liujians/weApp) 作者声明: 基于微信小程序开发的仿微信demo  整合了ionic的样式库和we ...

  9. Android开发之仿手机卫士悬浮窗效果

    基本的实现原理,这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多.主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,upda ...

  10. Android 悬浮窗,绝对是目前相关悬浮窗开源库最完美的适配方案

    PerfectFloatWindow 项目地址:Alonsol/PerfectFloatWindow 简介: android 全局悬浮窗,目前已经适配华为,小米,vivo,oppo,一加,三星,魅族, ...

最新文章

  1. tensorflow lstm 实现 RNN / LSTM 的关键几个步骤 多层通俗易懂
  2. 【学习笔记】【oc】类和对象及类的三大基本特征
  3. 大正整数排序~(结构体排序~)
  4. python opencv过滤红色
  5. (数据库系统概论|王珊)第一章绪论-第二节:数据模型
  6. 国内三大PT(Private Tracker)站分析
  7. mysql 表单记录主键重新从1开始排序
  8. Python2.x(3.x)安装及Ulipad的安装和使用
  9. 华为交换机初始化_华为交换机的初始配置
  10. 在ADF应用中,能够通过 oracle.adf.view.rich.security.FRAME_BUSTING 参数来使用framebusting功能。
  11. [跑步] 跑步者的力量训练
  12. 变量命名神器 CODELF
  13. TSV文件、CSV文件
  14. springMVC的大体结构及工作流程
  15. 高中计算机教师研究方向,高中信息技术教师专业知识研究
  16. Auto-Rig Pro文档翻译:安装
  17. [Unity官方文档翻译]Downloading and Installing Unity下载和安装unity教程
  18. 【数据可视化】第三章——数据可视化综合实践
  19. 项目开发日报表——第二天
  20. 并发编程的艺术03-Bakery互斥锁算法

热门文章

  1. Linux - history命令详解
  2. 【光纤传输特性】图文并茂,你该了解这些
  3. Python3.6支付宝账单爬虫
  4. ActiveMQ笔记(一)
  5. Nik Collection v3.0.7 2020 Mac/Win PS/LR超强调色滤镜合集Nik插件中文版+中文教程
  6. xp启用计算机共享打印机,Win7共享XP打印机设置方法【win7不能共享xp打印机】解决方法...
  7. 移动app用户体验与性能优化
  8. 内网ip和外网ip区别
  9. 新手用计算机制作工作表,新手怎么制作Excel表格?Excel表格制作教程介绍
  10. 【lidar】单目深度估计与伪雷达点云、可视化