蹭一波热度:记微信跳一跳辅助线开发

时间:2021-01-21 23:22:56

蹭一波热度:记微信跳一跳辅助线开发

  • 场景
    前两天下午三点多时候,老板突然一个电话过来:“那个小甘啊,最近微信跳一跳小游戏很火啊,我们现在已经有了全自动脚本了,现在需要一个提升用户参与感的辅助工具,就是需要一条辅助线来帮助用户得到更高分,这个东西你来做一下,务必用最短的时间把它实现了。”唉,那么没办法只能开撸了。

  • 基本思路
    既然是辅助线,那么肯定是在所有窗口的前面,看到这个自然就想到了利用WindowManager来实现一个悬浮在所有窗口前面的Window,利用Service在后台不断更新小人头部的坐标,通过监听手指按下和弹起不断在Window中addView和removeView来绘制辅助线。Tips:监听手指在屏幕上的事件和不断寻找小人头部坐标是Native以前实现好的成熟方案=。=这里我并不会。

  • 编码实现
    1.Service关键代码
    创建没有事件的悬浮窗

private void createToucher() {
//赋值WindowManager&LayoutParam.
params = new WindowManager.LayoutParams();
windowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);
//设置type.系统提示型窗口,一般都在应用程序窗口之上.
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
//设置效果为背景透明.
params.format = PixelFormat.RGBA_8888;
//设置flags.不可聚焦及不可使用按钮对悬浮窗进行操控.
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_FULLSCREEN
;

//设置窗口初始停靠位置.
params.gravity = Gravity.LEFT | Gravity.TOP;
params.x = 0;
params.y = 0;

params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
}

WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE这三个标记很重要,不加会拦截事件,导致其他窗口无法响应事件。

监听手指按下与弹起并绘制辅助线

 @Override
public void onTouchDown() { /*手指按下时开始画线*/
try {
if (point.x != -1 && point.y != -1) {
lineView = new LineView(DrawLineService.this);
lineView.start(point.x, point.y);
windowManager.addView(lineView, params);
}
} catch (Exception ignored) {
}
}
      @Override
public void onTouchUp() {
try { /*手指弹起时释放画线*/
lineView.stop();
windowManager.removeView(lineView);
} catch (Exception ignored) {
}
}

2.辅助线的View

public class LineView extends View {

private static final float SPEED_X = 0.60f / 1080f;
private static final float SPEED_Y = 0.35f / 1920f;

private float mx, my, incrementY, incrementX;
private int mWidth;
private int mHeight;

private long startTime;
private Timer mTimer = new Timer();
TimerTask mTimerTask;
Paint p;

private float mHeadOffset;
public static float gOffset = 1f;

/*因为底层接口返回的是小人头部坐标 线需要从脚部开始划 所以需要调整*/
private float mDefaultHeadOffset = 40f;

public LineView(Context context) {
super(context);
init();
}

private void init() {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
mWidth = displayMetrics.widthPixels;
mHeight = displayMetrics.heightPixels;
p = new Paint();
p.setColor(Color.RED);
p.setAntiAlias(true);
p.setStrokeWidth(10.0f);
mHeadOffset = ConvertUtils.dip2px(getContext(), mDefaultHeadOffset);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(mx, my, incrementX, incrementY, p);// 斜线
}


/**
* 手指按压住以后该方法执行,内部使用TimerTask完成直线绘制
*
* @param x 小人头部x坐标
* @param y 小人头部y坐标
*/

public void start(float x, float y) {
startTime = System.currentTimeMillis();
y += mHeadOffset; /*小人脚部y坐标*/
this.incrementX = x;
this.incrementY = y;
this.mx = x;
this.my = y;
if (isRight(mx)) {
mTimerTask = new TimerTask() {
@Override
public void run() {
float ellapsed = System.currentTimeMillis() - startTime;
/**
* tips:0.35和0.60是根据测试结果调出来的 需要根据实际情况优化
*/

incrementY = my - ellapsed * SPEED_Y * mHeight * gOffset; /* y / x = 0.58*/
incrementX = mx - ellapsed * SPEED_X * mWidth * gOffset;
postInvalidate();
}
};
} else {
mTimerTask = new TimerTask() {
@Override
public void run() {
float ellapsed = System.currentTimeMillis() - startTime;
incrementY = my - ellapsed * SPEED_Y * mHeight * gOffset;
incrementX = mx + ellapsed * SPEED_X * mWidth * gOffset;
postInvalidate();
}
};
}
/*每隔10ms绘制一次*/
mTimer.schedule(mTimerTask, 0, 10);
}

/**
* 手指松开时调用该方法,调用时停止画线
*/

public void stop() {
mTimerTask.cancel();
mTimerTask = null;
}

/**
* 判断当前小人在左边还是右边(根据左右来判断斜线往哪边画)
* @return true 右边 false坐标
*/

private boolean isRight(float x) {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
if (x < width / 2) {
return false; //left
} else {
return true;
}
}
}
  • 最后附上效果图

蹭一波热度:记微信跳一跳辅助线开发