android 浮动文字提示,怎么在Android中实现一个自由拖动并显示文字的悬浮框

怎么在Android中实现一个自由拖动并显示文字的悬浮框

发布时间:2021-01-27 15:34:05

来源:亿速云

阅读:107

作者:Leah

今天就跟大家聊聊有关怎么在Android中实现一个自由拖动并显示文字的悬浮框,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

实现步骤:

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;

}

}

看完上述内容,你们对怎么在Android中实现一个自由拖动并显示文字的悬浮框有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现自由移动、监听点击事件的悬浮窗,可以通过以下步骤来实现: 1. 在 AndroidManifest.xml 文件添加悬浮窗权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. 创建一个浮动窗口布局的 xml 文件,在其添加一个可移动的 View 控件和必要的监听事件。 3. 在 Service 创建 WindowManager 对象,并使用 addView() 方法将浮动窗口布局添加到 WindowManager 。 4. 在浮动窗口布局的 View 控件实现 onTouchEvent() 方法,监听触摸事件,并根据触摸事件的坐标改变浮动窗口的位置。 5. 在浮动窗口布局的 View 控件实现 OnClickListener() 方法,监听点击事件,并执行相应的操作。 6. 在 Service 的 onDestroy() 方法使用 removeView() 方法将浮动窗口布局从 WindowManager 移除,释放资源。 下面是一个简单的实现代码示例: ```java public class FloatWindowService extends Service { private WindowManager mWindowManager; private View mFloatView; private WindowManager.LayoutParams mParams; @Override public void onCreate() { super.onCreate(); mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mFloatView = LayoutInflater.from(this).inflate(R.layout.float_window_layout, null); mParams = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); mParams.gravity = Gravity.TOP | Gravity.LEFT; mParams.x = 0; mParams.y = 0; mWindowManager.addView(mFloatView, mParams); // 监听触摸事件,改变浮动窗口位置 mFloatView.setOnTouchListener(new View.OnTouchListener() { private int mLastX; private int mLastY; private int mDownX; private int mDownY; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastX = mParams.x; mLastY = mParams.y; mDownX = (int) event.getRawX(); mDownY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveX = (int) event.getRawX(); int moveY = (int) event.getRawY(); int dx = moveX - mDownX; int dy = moveY - mDownY; mParams.x = mLastX + dx; mParams.y = mLastY + dy; mWindowManager.updateViewLayout(mFloatView, mParams); break; } return false; } }); // 监听点击事件 mFloatView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 执行相应的操作 } }); } @Override public void onDestroy() { super.onDestroy(); mWindowManager.removeView(mFloatView); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值