栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android 实现可任意拖动的悬浮窗功能(类似悬浮球)

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 实现可任意拖动的悬浮窗功能(类似悬浮球)

最近开发项目中,有个在屏幕上任意拖动的悬浮窗功能,其实就是利用 WindowManager的api来完成这个需求,具体的实现的功能如下:
1.自定义view

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.xinrui.recordscreen.R;
import java.lang.reflect.Field;

public class RecordScreenView extends LinearLayout implements View.OnClickListener{
  private WindowManager mWindowManager;
  private WindowManager.LayoutParams mLayoutParams;
  private long mLastDownTime;
  private float mLastDownX;
  private float mLastDownY;
  private boolean mIsLongTouch;
  private boolean mIsTouching;
  private float mTouchSlop;
  private final static long LONG_CLICK_LIMIT = 20;
  private final static int TIME_COUNT = 0;
  private int mStatusBarHeight;
  private int mCurrentMode,time=0;
  private final static int MODE_NONE = 0x000;
  private final static int MODE_MOVE = 0x001;
  private int mOffsetToParent;
  private int mOffsetToParentY;
  private Context mContext;
  public RecordScreenView(Context context) {
    super(context);
    this.mContext=context;
    mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    initView();
  }
  private void initView() {
    View view = inflate(getContext(), R.layout.layout_ball, this);
    mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    mCurrentMode = MODE_NONE;
    recordtime(0);
    mStatusBarHeight = getStatusBarHeight();
    mOffsetToParent = dip2px(25);
    mOffsetToParentY = mStatusBarHeight + mOffsetToParent;
    view.setonTouchListener(new onTouchListener() {
      @Override
      public boolean onTouch(View v, final MotionEvent event) {
 switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
     mIsTouching = true;
     mLastDownTime = System.currentTimeMillis();
     mLastDownX = event.getX();
     mLastDownY = event.getY();
     postDelayed(new Runnable() {
@Override
public void run() {
  if (isLongTouch()) {
    mIsLongTouch = true;
  }
}
     }, LONG_CLICK_LIMIT);
     break;
   case MotionEvent.ACTION_MOVE:
     if (!mIsLongTouch && isTouchSlop(event)) {
return true;
     }
     if (mIsLongTouch && (mCurrentMode == MODE_NONE || mCurrentMode == MODE_MOVE)) {
mLayoutParams.x = (int) (event.getRawX() - mOffsetToParent);
mLayoutParams.y = (int) (event.getRawY() - mOffsetToParentY);
mWindowManager.updateViewLayout(RecordScreenView.this, mLayoutParams);//不断刷新悬浮窗的位置
mCurrentMode = MODE_MOVE;
     }
     break;
   case MotionEvent.ACTION_CANCEL:
   case MotionEvent.ACTION_UP:
     mIsTouching = false;
     if (mIsLongTouch) {
mIsLongTouch = false;
     }
     mCurrentMode = MODE_NONE;
     break;
 }
 return true;
      }
    });
  }
  private boolean isLongTouch() {
    long time = System.currentTimeMillis();
    if (mIsTouching && mCurrentMode == MODE_NONE && (time - mLastDownTime >= LONG_CLICK_LIMIT)) {
      return true;
    }
    return false;
  }
  
  private boolean isTouchSlop(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    if (Math.abs(x - mLastDownX) < mTouchSlop && Math.abs(y - mLastDownY) < mTouchSlop) {
      return true;
    }
    return false;
  }
  public void setLayoutParams(WindowManager.LayoutParams params) {
    mLayoutParams = params;
  }
  
  private int getStatusBarHeight() {
    int statusBarHeight = 0;
    try {
      Class c = Class.forName("com.android.internal.R$dimen");
      Object o = c.newInstance();
      Field field = c.getField("status_bar_height");
      int x = (Integer) field.get(o);
      statusBarHeight = getResources().getDimensionPixelSize(x);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return statusBarHeight;
  }
  public int dip2px(float dip) {
    return (int) TypedValue.applyDimension(
 TypedValue.COMPLEX_UNIT_DIP, dip, getContext().getResources().getDisplayMetrics()
    );
  }
}

2.添加windowManager添加view

import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;



public class FloatWindowManager {
  private static RecordScreenView mBallView;

  private static WindowManager mWindowManager;


  public static void addBallView(Context context) {
    if (mBallView == null) {
      WindowManager windowManager = getWindowManager(context);
      int screenWidth = windowManager.getDefaultDisplay().getWidth();
      int screenHeight = windowManager.getDefaultDisplay().getHeight();
      mBallView = new RecordScreenView(context);
      LayoutParams params = new LayoutParams();
      params.x = screenWidth/2;
      params.y = screenHeight/2+150;
      params.width = LayoutParams.WRAP_CONTENT;
      params.height = LayoutParams.WRAP_CONTENT;
      params.gravity = Gravity.LEFT | Gravity.TOP;
      params.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
      params.format = PixelFormat.RGBA_8888;
      params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
   | LayoutParams.FLAG_NOT_FOCUSABLE;
      mBallView.setLayoutParams(params);
      windowManager.addView(mBallView, params);
    }
  }

  public static void removeBallView(Context context) {
    if (mBallView != null) {
      WindowManager windowManager = getWindowManager(context);
      windowManager.removeView(mBallView);
      mBallView = null;
    }
  }

  private static WindowManager getWindowManager(Context context) {
    if (mWindowManager == null) {
      mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }
    return mWindowManager;
  }
}

3.Acitivity中调用

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

import com.xinrui.recordscreen.view.FloatWindowManager;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= 23) {
    //设置中请求开启悬浮窗权限
      if (!Settings.canDrawOverlays(this)) {
 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 startActivity(intent);
 Toast.makeText(this, MainActivity.this.getResources().getString(R.string.open_float), Toast.LENGTH_SHORT).show();
      }else{
 initView();
      }
    }
  }

  private void initView() {
    FloatWindowManager.addBallView(MainActivity.this);
    finish();
  }
}

5.AndroidManifest.xml



  
  
  
  //悬浮窗权限
  
    
      
 

 
      
    

总结

到此这篇关于Android 实现可任意拖动的悬浮窗功能(类似悬浮球)的文章就介绍到这了,更多相关Android任意拖动的悬浮窗内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/154065.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号