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

项目中需要实现一个状态显示的悬浮框,要求可以设置两种模式:拖动模式和不可拖动模式。

实现效果图如下:

5ab379003aa852009b8a2e05a309dbb3.gif

实现步骤:

1.首先要设置该悬浮框的基本属性:

/**

* 显示弹出框

*

* @param context

*/

@SuppressWarnings("WrongConstant")

public static void showPopupWindow(final Context context, String showtxt) {

if (isShown) {

return;

}

isShown = true;

// 获取WindowManager

mWindowManager = (WindowManager) context

.getSystemService(Context.WINDOW_SERVICE);

mView = setUpView(context, showtxt);

params = new WindowManager.LayoutParams();

// 类型,系统提示以及它总是出现在应用程序窗口之上。

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;

// 设置flag

int flags = canTouchFlags;

// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

// 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件

params.flags = flags;

// 不设置这个弹出框的透明遮罩显示为黑色

params.format = PixelFormat.TRANSLUCENT;

// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口

// 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按

// 不设置这个flag的话,home页的划屏会有问题

params.width = LayoutParams.WRAP_CONTENT;

params.height = LayoutParams.WRAP_CONTENT;

params.gravity = Gravity.TOP;

mWindowManager.addView(mView, params);

}

比较重要的点是要注意设置flags,我这里提供了两种flags以供切换:

private static int canTouchFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

private static int notTouchFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|

WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

第一种是可触摸不可聚焦模式,第二种是不可触摸不可聚焦模式。其他的flags可以从api中查阅。

2.设置悬浮框的拖动监听事件:

private static View setUpView(final Context context, String showtxt) {

View view = LayoutInflater.from(context).inflate(R.layout.layout_popwindow,

null);

TextView showTv = (TextView) view.findViewById(R.id.tv_showinpop);

showTv.setText(showtxt);

rl_drag_showinpop = (RelativeLayout) view.findViewById(R.id.rl_drag_showinpop);

rl_drag_showinpop.setOnTouchListener(new View.OnTouchListener() {

private float lastX; //上一次位置的X.Y坐标

private float lastY;

private float nowX; //当前移动位置的X.Y坐标

private float nowY;

private float tranX; //悬浮窗移动位置的相对值

private float tranY;

@Override

public boolean onTouch(View v, MotionEvent event) {

boolean ret = false;

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

// 获取按下时的X,Y坐标

lastX = event.getRawX();

lastY = event.getRawY();

ret = true;

break;

case MotionEvent.ACTION_MOVE:

// 获取移动时的X,Y坐标

nowX = event.getRawX();

nowY = event.getRawY();

// 计算XY坐标偏移量

tranX = nowX - lastX;

tranY = nowY - lastY;

params.x += tranX;

params.y += tranY;

//更新悬浮窗位置

mWindowManager.updateViewLayout(mView, params);

//记录当前坐标作为下一次计算的上一次移动的位置坐标

lastX = nowX;

lastY = nowY;

break;

case MotionEvent.ACTION_UP:

break;

}

return ret;

}

});

这里要在down的时候记录坐标,move事件中使用修改params坐标进行移动。

3.设置悬浮框文字属性:

public static void setShowTxt(String txt) {

try {

TextView showTv = (TextView) mView.findViewById(R.id.tv_showinpop);

showTv.setText(txt);

mWindowManager.updateViewLayout(mView, params);

}catch (Exception e){

Log.d(TAG, "setShowTxt: 更新悬浮框错误");

e.printStackTrace();

if(e.getMessage().contains("not attached to window manager")){

mWindowManager.addView(mView, params);

}

}

}

4.更新悬浮框图片显示:

public static void setShowImg(Bitmap bitmap) {

try {

ImageView showImg = (ImageView) mView.findViewById(R.id.iv_showinpop);

showImg.setImageBitmap(bitmap);

mWindowManager.updateViewLayout(mView, params);

}catch (Exception e){

Log.d(TAG, "setShowTxt: 更新悬浮框错误");

e.printStackTrace();

if(e.getMessage().contains("not attached to window manager")){

mWindowManager.addView(mView, params);

}

}

}

介绍完毕,整个类都封装好了,代码如下:

/**

* 悬浮窗工具类

* created by Pumpkin at 17/3/28

*/

public class WindowsUitlity {

private static String TAG = WindowsUitlity.class.getSimpleName();

private static WindowManager mWindowManager = null;

private static WindowManager.LayoutParams params;

public static Boolean isShown = false;

private static View mView = null;

/**

* 显示弹出框

*

* @param context

*/

@SuppressWarnings("WrongConstant")

public static void showPopupWindow(final Context context, String showtxt) {

if (isShown) {

return;

}

isShown = true;

// 获取WindowManager

mWindowManager = (WindowManager) context

.getSystemService(Context.WINDOW_SERVICE);

mView = setUpView(context, showtxt);

params = new WindowManager.LayoutParams();

// 类型,系统提示以及它总是出现在应用程序窗口之上。

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |

WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;

// 设置flag

int flags = canTouchFlags;

// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

// 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件

params.flags = flags;

// 不设置这个弹出框的透明遮罩显示为黑色

params.format = PixelFormat.TRANSLUCENT;

// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口

// 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按

// 不设置这个flag的话,home页的划屏会有问题

params.width = LayoutParams.WRAP_CONTENT;

params.height = LayoutParams.WRAP_CONTENT;

params.gravity = Gravity.TOP;

mWindowManager.addView(mView, params);

}

private static int canTouchFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

private static int notTouchFlags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|

WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

/**

* 设置是否可响应点击事件

*

* @param isTouchable

*/

public static void setTouchable(boolean isTouchable) {

if (isTouchable) {

params.flags = canTouchFlags;

} else {

params.flags = notTouchFlags;

}

mWindowManager.updateViewLayout(mView, params);

}

/**

* 隐藏弹出框

*/

public static void hidePopupWindow() {

if (isShown && null != mView) {

mWindowManager.removeView(mView);

isShown = false;

}

}

public static void setShowTxt(String txt) {

try {

TextView showTv = (TextView) mView.findViewById(R.id.tv_showinpop);

showTv.setText(txt);

mWindowManager.updateViewLayout(mView, params);

}catch (Exception e){

Log.d(TAG, "setShowTxt: 更新悬浮框错误");

e.printStackTrace();

if(e.getMessage().contains("not attached to window manager")){

mWindowManager.addView(mView, params);

}

}

}

public static void setShowImg(Bitmap bitmap) {

try {

ImageView showImg = (ImageView) mView.findViewById(R.id.iv_showinpop);

showImg.setImageBitmap(bitmap);

mWindowManager.updateViewLayout(mView, params);

}catch (Exception e){

Log.d(TAG, "setShowTxt: 更新悬浮框错误");

e.printStackTrace();

if(e.getMessage().contains("not attached to window manager")){

mWindowManager.addView(mView, params);

}

}

}

static RelativeLayout rl_drag_showinpop;

private static View setUpView(final Context context, String showtxt) {

View view = LayoutInflater.from(context).inflate(R.layout.layout_popwindow,

null);

TextView showTv = (TextView) view.findViewById(R.id.tv_showinpop);

showTv.setText(showtxt);

rl_drag_showinpop = (RelativeLayout) view.findViewById(R.id.rl_drag_showinpop);

rl_drag_showinpop.setOnTouchListener(new View.OnTouchListener() {

private float lastX; //上一次位置的X.Y坐标

private float lastY;

private float nowX; //当前移动位置的X.Y坐标

private float nowY;

private float tranX; //悬浮窗移动位置的相对值

private float tranY;

@Override

public boolean onTouch(View v, MotionEvent event) {

boolean ret = false;

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

// 获取按下时的X,Y坐标

lastX = event.getRawX();

lastY = event.getRawY();

ret = true;

break;

case MotionEvent.ACTION_MOVE:

// 获取移动时的X,Y坐标

nowX = event.getRawX();

nowY = event.getRawY();

// 计算XY坐标偏移量

tranX = nowX - lastX;

tranY = nowY - lastY;

params.x += tranX;

params.y += tranY;

//更新悬浮窗位置

mWindowManager.updateViewLayout(mView, params);

//记录当前坐标作为下一次计算的上一次移动的位置坐标

lastX = nowX;

lastY = nowY;

break;

case MotionEvent.ACTION_UP:

break;

}

return ret;

}

});

return view;

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android4.2.2的Stagefright维护编解码器的数据流

这里是他们自己的源代码阅读点滴总结属性,转请注明出处,谢谢。欢迎和大家分享。qq:1037701636 email:gzzaigcn2012gmail.comAndroid源代码版本号Version:4.2.2; 硬件平台 全志A31前沿:在前面的博文中,基本提到的是stag…

PHP的安装

PHP的环境也是诸多服务器软件的必要因素之一,它是一个HTML内嵌式语言,在服务器端执行。由于PHP的开源高效化平台,所以搭建一个php环境是一个运维工程师必备的能力。现在lamp也有类似lnmp.org那种一键安装包,地址是http://yumlamp.…

android 横向铺满,Android开发全程记录(八)——设置ImageView显示的图片铺满全屏(适应魅族等不常见屏幕比例)...

为适应不同屏幕的手机,ImageView显示的图片可能不铺满屏幕,如果定高的话,两边可能会出现空白。魅族手机就会有这种情况,在其他手机里显示正常,在魅族手机里显示,图片左右两边会出现空白,为解决这…

tihs 关键字

//this关键词/*调用类中的属性 调用类中的方法或构造方法 调用当前对象,调用自己的方法,可以省略。 */ //http://blog.sina.com.cn/s/blog_71f6c1980100wtj4.html//this指当前对象自己public class Google{String s"hello";public Google(Stri…

良好的编程习惯

*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com *************************************************** 良好的编程习惯良好的习惯对于人的成长是非常重要的,良好的编程习惯对于我…

ntfs for mac使用注意事项有哪些?

2019独角兽企业重金招聘Python工程师标准>>> mac的用户有很多,一些用户朋友会发现自己的电脑是无法读写ntfs驱动器的。而ntfs驱动器又是一种常用的驱动器。面对这种情况我们可以选择用NTFS for Mac软件来帮助我们,它可以读写ntfs驱动器&#…

android音乐播放器文章,Android复习09【内容提供者、音乐播放器】

目 录PersonCpPersonCp.javainsert()ContentObserver音乐播放器1、添加读写权限1.1、动态权限授予(调用封装好的方法)2、获取音乐文件(MainActivity.java)2、Music.java(实体类)申请访问SD卡的权限设置适配器下拉刷新PersonCpPersonCp.javapackage cn.wangzg.personcp;import a…

程序员的业余项目

程序员的业余项目&#xff0c;我们也叫它 side project。 前几天&#xff0c;100offer 发起了一场活动叫 <寻找实干和坚持的技术力量>&#xff0c;他们是这么说的&#xff1a; 世界在被代码改变着&#xff0c;而我们在创造着代码。 仅仅是因为好玩&#xff0c;他开发了…

C语言的数组名和对数组名取地址

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 相信不少的C语言初学者都知道&#xff0c;数组名相当于指针&#xff0c;指向数组的首地…

小米 android 8,小米华为们谁最良心?10大手机厂商安卓8.0升级情况盘点

3月8日&#xff0c;谷歌放出了首个安卓9.0开发者预览版的固件包&#xff0c;不出意外的话&#xff0c;它的正式版会在今年正式亮相。但对广大安卓用户来说&#xff0c;想要立刻用上最新系统并非易事。目前来说&#xff0c;安卓碎片化问题依然严重&#xff0c;我们不妨现实点&am…

窥探Swift之数组安全索引与数组切片

在Swift中的数组和字典中下标是非常常见的&#xff0c;数组可以通过索引下标进行元素的查询&#xff0c;字典可以通过键下标来获取相应的值。在使用数组时&#xff0c;一个常见的致命错误就是数组越界。如果在你的应用程序中数组越界了&#xff0c;那么对不起&#xff0c;如果由…

大小端模式的快速判断方法

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 大小端的问题剖析&#xff1a; 嵌 入式系统开发者应该对Little-endian和Big-endian模…

【RAC】How to Proceed from Failed 11gR2 CRS Installation

Applies to: [ID 942166.1] Oracle Server – Enterprise Edition – Version: 11.2.0.1 to 11.2.0.2 – Release: 11.2 to 11.2 Generic UNIX Generic Linux Goal This goal of this note is to provide steps to proceed from failed 11gR2 Grid Infrastructure installat…

WinForm支持拖拽效果

有一个MSDN客户提问在WinForm中如何实现拖拽效果——比如在WinForm中有一个Button&#xff0c;我要实现的效果是拖拽这个Button到目标位置后生成一个该控件的副本。 其实这个操作主要分成三步走&#xff1a; 1&#xff09;确定被拖拽的对象&#xff1a; 这里是Button&#xff0…

win7 64位出现桌面右键鼠标显示忙碌

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 将下面绿色内容复制到txt文本中&#xff0c;然后另存为1.bat 双击运行即可 【针对64位…

android tee,Android 9.0的新增安全特性与TEE

Android P&#xff0c;预计将于 2018 年第三季度发布最终版本。特别是Android8.0以来&#xff0c;安全性是Android版本变更的一个重要因素。从安全性增强方面来看&#xff0c;本次Android9.0版本主要有以下几个方面&#xff1a;统一的指纹身份验证对话框Android P 中&#xff0…

哪些要素会让咱们呈现抑郁症的病症

依据最新研讨标明&#xff0c;一自个的性情怎样&#xff0c;本来是天然生成的&#xff0c;后天的日子&#xff0c;仅仅对咱们的性情进行批改&#xff0c;但在咱们潜意识中&#xff0c;违反自个性情的行动&#xff0c;会让咱们感到格外累&#xff0c;所以&#xff0c;不少人即是…

如何定义一个只能在堆上(栈上)生成对象的类?

在C中&#xff0c;类的对象建立分为两种&#xff0c;一种是静态建立&#xff0c;如A a&#xff1b;另一种是动态建立&#xff0c;如A* ptrnew A&#xff1b;这两种方式是有区别的。 静态建立一个类对象&#xff0c;是由编译器为对象在栈空间中分配内存&#xff0c;是通过直接移…

canny算子的理论分析

****************************************************************************************************************************************** 红&#xff1a;数字图像处理视频教程&#xff08;两部&#xff09; {中科院版36讲视频教程 电子科大版70讲视频教程&#x…

Android为spinner设置适配器,Android Spinner与适配器模式详解及实例代码

最近做项目对Android Spinner 使用&#xff0c;这里简单写个小例子&#xff0c;来测试如何使用。Spinner是一个下拉列表&#xff0c;往安卓界面中拖拽一个Spinner控件&#xff0c;在属性中设置Android:entries“array/spinner_data”其中spinner_data为在string中设置的数组。数…