可拖动、可靠边的 popupWindow 实现
0 背景
开发要实现一个可以拖动的圆角小窗,要求松手时,哪边近些靠哪边。并且还规定了拖动范围。样式如下:
1 实现
首先把 PopupWindow 的布局文件 pop.xml 实现
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="88dp"android:layout_height="132dp"android:background="@drawable/radius_12"android:id="@+id/mini_popup"android:visibility="visible"><com.google.android.material.imageview.ShapeableImageViewandroid:id="@+id/iv_live_cover"android:layout_width="88dp"android:scaleType="fitXY"android:layout_height="132dp"android:background="@color/purple_200"app:shapeAppearanceOverlay="@style/MiniDialogRoundedImageStyle" /><ImageViewandroid:id="@+id/iv_close"android:layout_width="16dp"android:layout_height="16dp"android:layout_alignParentRight="true"android:layout_marginTop="4dp"android:layout_marginRight="4dp"android:src="@color/teal_200" />
</RelativeLayout>
布局中圆角和 PopupWindow 的动画 style.xml
<!-- 圆角图片 --><style name="MiniDialogRoundedImageStyle"><item name="cornerFamily">rounded</item><item name="cornerSize">12dp</item></style><!-- PopupWindow 的动画效果 --><style name="PopupWindowAnimation"><item name="android:windowEnterAnimation">@anim/live_popup_window_in_anim</item></style>
radius_12.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="12dp"/><solid android:color="@color/white"/>
</shape>
MyPopupWindow.java
package com.example.myapplication.popupwindow;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.PopupWindow;import com.bumptech.glide.Glide;
import com.example.myapplication.R;public class MyPopupWindow extends PopupWindow {private Context mContext;private View mRootView;// 背景private ImageView mBackground;// 关闭弹窗private ImageView mIvClose;// 弹窗的移动范围private int mMinX;private int mMinY;private int mMaxX;private int mMaxY;// 屏幕宽高private int mScreenWidth;public MyPopupWindow(Context context) {super(context);mContext = context;mRootView = View.inflate(mContext, R.layout.pop, null);mScreenWidth = getScreenWidth(mContext);mMinX = dp2px(12);mMaxX = mScreenWidth - dp2px(12) - dp2px(88);mMinY = dp2px(12);mMaxY = dp2px(500);// 为了保证整体是圆角形状mRootView.findViewById(R.id.mini_popup).setClipToOutline(true);initView();}private void initView() {setContentView(mRootView);mBackground = mRootView.findViewById(R.id.iv_live_cover);mIvClose = mRootView.findViewById(R.id.iv_close);mIvClose.setOnClickListener(view -> this.dismiss());// 小窗的宽高setHeight(dp2px(132));setWidth(dp2px(88));this.setTouchInterceptor(new View.OnTouchListener() {int orgX, orgY;int offsetX, offsetY;@Overridepublic boolean onTouch(View view, MotionEvent motionEvent) {switch (motionEvent.getAction()) {case MotionEvent.ACTION_DOWN:orgX = (int) motionEvent.getX();orgY = (int) motionEvent.getY();break;case MotionEvent.ACTION_MOVE:offsetX = (int) motionEvent.getRawX() - orgX;offsetY = (int) motionEvent.getRawY() - orgY;// 限制 x 坐标offsetX = Math.max(offsetX, mMinX);offsetX = Math.min(offsetX, mMaxX);// 限制 y 坐标offsetY = Math.max(offsetY, mMinY);offsetY = Math.min(offsetY, mMaxY);update(offsetX, offsetY, -1, -1, true);break;case MotionEvent.ACTION_UP:// 小窗靠边if (offsetX < mScreenWidth / 2) {offsetX = mMinX;} else {offsetX = mMaxX;}update(offsetX, offsetY, -1, -1, true);break;}// 避免 view 中的其他点击事件被吞掉return false;}});// 设置小窗背景this.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.abc_vector_test));// 出现的动画this.setAnimationStyle(R.style.PopupWindowAnimation);}public void show(View anchor) {this.showAtLocation(anchor, Gravity.NO_GRAVITY, mMaxX, mMaxY);}@SuppressLint("CheckResult")public void setBackground(String url) {if (url != null && !TextUtils.isEmpty(url))Glide.with(mContext).load(url).into(mBackground);}public int dp2px(float dpValue) {return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density);}public int getScreenWidth(Context context) {DisplayMetrics localDisplayMetrics = new DisplayMetrics();((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);return localDisplayMetrics.widthPixels;}
}
最后在 MainActivity 中使用
mTextView = findViewById(R.id.myView);
if (mMyPopupWindow == null) {mMyPopupWindow = new MyPopupWindow(MainActivity.this);
}
mTextView.post(() -> {mMyPopupWindow.show(mTextView);
});
相关文章:

可拖动、可靠边的 popupWindow 实现
0 背景 开发要实现一个可以拖动的圆角小窗,要求松手时,哪边近些靠哪边。并且还规定了拖动范围。样式如下: 1 实现 首先把 PopupWindow 的布局文件 pop.xml 实现 <?xml version"1.0" encoding"utf-8"?> <R…...

C# 依赖注入如何实现
在 C# 中,依赖注入(Dependency Injection,简称 DI)是一种编程技术,用于减少代码之间的耦合。依赖注入可以通过构造函数注入、属性注入或方法注入实现。在 .NET Core 和 .NET 5 中,还提供了一个内置的依赖注…...

Redis 9 数据库
4 设置键的生存时间或过期时间 通过EXPIRE命令或者PEXPIRE命令,客户端可以以秒或者毫秒精度为数据库中的某个键设置生存时间(TimeToLive,TTL),在经过指定的秒数或者毫秒数之后,服务器就会自动删除生存时间…...

43-设计问题-最小栈
原题链接: 198. 打家劫舍 题目描述: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入&a…...

基于RK3588全高端智能终端机器人主板
一、小尺寸板型设计 该款主板为小型板,尺寸仅为125*85mm,更小更紧凑,可完美适应各类高端智能自助终端; 二、八核高端处理器 采用RK3588S八核64位处理器,8nm LP制程,主频最高达2.4GHz,搭载Andr…...

穿越风波,“长红”的直播电商依然扎根产业和消费者
当消费者将最后一个快递拿进家门,2023年的双11也就落下了帷幕。相较于往年组队、拼单的玩法,如今最受欢迎的双11 流程,或许已经变成点进自己心仪主播、店铺的直播间,翻阅最新的产品清单,从中选择购物目标,在…...

LLM大模型 (chatgpt) 在搜索和推荐上的应用
目录 1 大模型在搜索的应用1.1 召回1.1.1 倒排索引1.1.2 倒排索引存在的问题1.1.3 大模型在搜索召回的应用 (实体倒排索引) 1.2 排序1.2.1 大模型在搜索排序应用(融入LLM实体排序) 2 大模型在推荐的应用2.1 学术界关于大模型在推荐的研究2.2 …...

中国净初级生产力年度合成产品NPP(MYD17A3H.006)
中国净初级生产力年度合成产品NPP(MYD17A3H.006)由航天宏图实验室提供,根据NASA MODIS数据(MYD17A3H.006)通过航天宏图 Smoother计算得到的平滑后NPP产品,解决了影像云雾覆盖、像元异常值等问题。对处理后的…...

GitHub如何删除仓库
GitHub如何删除仓库 删除方法第一步第二步第三步 删除方法 第一步 在仓库的界面选择Settings 第二步 选择General,页面拉到最后。 第三步 删除仓库。...

漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(3)
书接上文漫谈广告机制设计 | 万剑归宗:聊聊广告机制设计与收入提升的秘密(2),我们聊到囚徒困境是完全信息静态博弈,参与人存在占优策略,最终达到占优均衡,并且是对称占优均衡。接下来我们继续…...

安装系统时无raid驱动处理办法
场景描述 安装系统时可以进入安装界面,但是无法识别到硬盘,查看服务器硬件均无异常且从bios或者raid配置界面中能正常看到raid信息及硬盘信息,运行lspci 命令查看到服务器有raid卡,但是未加载驱动。 获取驱动程序模块 查看raid…...

ForkLift:macOS文件管理器/FTP客户端
ForkLift 是一款macOS下双窗口的文件管理器,可以代替本地的访达。ForkLift同时具备连接Ftp、SFtp、WebDav以及云服务器。 ForkLift还具备访达不具备的小功能,比如从文件夹位置打开终端,显示隐藏文件,制作替换等功能。ForkLift 是一…...

信息系统项目管理师 第四版 第20章 高级项目管理
1.项目集管理 1.1.项目集管理标准 1.2.项目集管理角色和职责 1.3.项目集管理绩效域 2.项目组合管理 2.1.项目组合管理标准 2.2.项目组合管理角色和职责 2.3.项目组合管理绩效域 3.组织级项目管理 3.1.组织级项目管理标准 3.2.业务价值与业务评估 3.3.OPM框架要素 3…...

Apache Pulsar 技术系列 - 基于 Pulsar 的海量 DB 数据采集和分拣
导语 Apache Pulsar 是一个多租户、高性能的服务间消息传输解决方案,支持多租户、低延时、读写分离、跨地域复制、快速扩容、灵活容错等特性。本文是 Pulsar 技术系列中的一篇,主要介绍 Pulsar 在海量DB Binlog 增量数据采集、分拣场景下的应用。 前言…...

HDFS、MapReduce原理--学习笔记
1.Hadoop框架 1.1框架与Hadoop架构简介 (1)广义解释 从广义上来说,随着大数据开发技术的快速发展与逐步成熟,在行业里,Hadoop可以泛指为:Hadoop生态圈。 也就是说,Hadoop指的是大数据生态圈整…...

PC端使子组件的弹框关闭
子组件 <template><el-dialog title"新增部门" :visible"showDialog" close"close"> </el-dialog> </template> <script> export default {props: {showDialog: {type: Boolean,default: false,},},data() {retu…...

PHPStorm PHP-CS-Fixer
我用的是brew安装: brew install php-cs-fixer phpstorm配置: setting搜索fixer 指定安装php-cs-fixer的目录: https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/installation.rst 图文详解PHPStorm实现自动执行代码格式化-…...

SpringBoot中日志的使用log4j
SpringBoot中日志的使用log4j 项目中日志系统是必不可少的,目前比较流行的日志框架有 log4j、logback 等,这两个框架的作者是同一个 人,Logback 旨在作为流行的 log4j 项目的后续版本,从而恢复 log4j 离开的位置。 另外 slf4j(…...

迭代器与生成器
章节目录: 一、迭代器1.1 相关概述1.2 基本使用1.3 自定义迭代器 二、生成器2.1 相关概述2.2 基本使用2.3 三种应用场景 三、yield 和 class 定义的迭代器对比四、结束语 一、迭代器 1.1 相关概述 迭代是 Python 最强大的功能之一,是访问集合元素的一种…...

适用于 Windows 的 10 个最佳视频转换器:快速转换高清视频
您是否遇到过由于格式不兼容而无法在您的设备上播放视频或电影的情况?您想随意播放从您的相机、GoPro 导入的视频,还是以最合适的格式将它们上传到媒体网站?您的房间里是否有一堆 DVD 光盘,想将它们转换为数字格式以便于播放&…...

分布式锁的概念、应用场景、实现方式和优缺点对比
一:什么是分布式锁 分布式锁是一种用于协调分布式系统中多个节点对共享资源的访问的机制。在分布式系统中,由于多个节点的并发执行,可能会导致对共享资源的竞争,而分布式锁的目的就是确保在任何时刻,只有一个节点能够持…...

Linux:常见指令
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》 文章目录 前言一、常见指令ls指令pwd指令cd指令touch指令mkdir指令rmdir指令rm指令man指令cp指令mv指令cat指令tac指令echo指令more指令less指令head指令tail指令date显示Cal指令find指令gr…...

大数据基础设施搭建 - ZooKeeper
文章目录 一、上传压缩包二、解压压缩包三、本机安装3.1 修改配置文件3.1.1 创建ZooKeeper数据存储目录3.1.2 修改配置文件名3.1.2 修改配置文件内容 3.3 启动/停止服务端3.4 测试(1)启动客户端(2)测试客户端操作 四、集群安装4.1…...

网站优化工具Google Optimize
Google Optimize 是一款由Google提供的网站优化工具。Google Optimize旨在帮助网站管理员通过对网页内容、设计和布局进行测试和优化,来提升用户体验和网站的转化率。 Google Optimize 提供了 A/B 测试和多变量测试功能,使网站管理员能够比较和评估不同…...

PostgreSQL创建分区表,并插入大量数据
创建分区表,按日期范围分区 CREATE TABLE sales (id serial,sale_date DATE, amount NUMERIC, PRIMARY KEY(id, sale_date) ) PARTITION BY RANGE (sale_date); 创建分区 CREATE TABLE sales_2019 PARTITION OF sales FOR VALUES FROM (2019-0…...

NewStarCTF2023 Reverse Week3 EzDLL WP
分析 这里调用了z3h.dll中的encrypt函数。 用ida64载入z3h.dll 直接搜索encrypt 找到了一个XTEA加密。接着回去找key和密文。 发现key 这里用了个调试状态来判断是否正确,v71,要v7=1才会输出Right,即程序要处于飞调试状态。 可…...

软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】
软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】 课本里章节里所有蓝色字体的思维导图...

php-cli
//运行index.php ./php index.php//启动php内置服务器 ./php -S 0.0.0.0:8080//启动内置服务在后台运行,日志输出到本目录下的server.log nohup ./php -S 0.0.0.0:8080 -t . > server.log 2>&1 &# 查找 PHP 进程 ps aux | grep "php -S 0.0.0.0:…...

[C/C++] 数据结构 LeetCode:用队列实现栈
题目描述: 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类: void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元…...

ESP32网络开发实例-物联网声污染监测系统
物联网声污染监测系统 文章目录 物联网声污染监测系统1、KY-038 声音传感器模块2、软件准备3、硬件准备4、代码实现在本文中,我们将使用 ESP32、声音模块和 Blynk 应用程序创建一个基于物联网的声音污染监测系统。 我们将使用 KY-038 麦克风传感器以分贝为单位检测声音并在 OL…...