package com.example.ndh.floatingball.sdk;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.example.ndh.floatingball.R;
import com.example.ndh.floatingball.util.Utils;
/**
* Created by ndh on 16/12/13.
*/
public class FloatingView extends View {
//阻力效果
private int scale = 10;
private int width = 25;
private int r = width;
private float startX;
private float startY;
//记录手指的移动
private float moveX;
private float moveY;
//中间的圆球
private Bitmap pinWheelBmp;
private String mLeft = "left";
private String mUp = "up";
private String mRight = "right";
private String mDown = "down";
private float textAlpha = 0;
private Paint mPaint;
//长按震动,提醒用户可以在屏幕上拖拽控件到任意位置
private static Vibrator sVibrator;
boolean isMoving;
private String drawText;
private float textX;
private float textY;
//定位文字的位置
private RectF rectFtop;
private RectF rectFleft;
private RectF rectFright;
private RectF rectFdown;
private RectF textRect;
//控制圆球的拖动距离
private float x;
private float y;
// 让圆球可以有一定拖出圆圈范围的效果
private final float circleScale = 3.0f / 4;
//判断是否点击
private boolean click;
//判断是否长按
private boolean longClick;
public FloatingView(Context context) {
this(context, null);
}
public FloatingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setTextSize(10);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
setBackgroundColor(Color.TRANSPARENT);
r = width = Utils.dp2pix(getContext(), width);
sVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(2 * r, 2 * r);
}
@Override
protected void onDraw(Canvas canvas) {
Log.d("ndh--", "alpha=" + textAlpha + ",r=" + r * circleScale + "r--" + r + "circleScale=" + circleScale);
mPaint.setARGB((int) (100), 0, 0, 0);
int width = getMeasuredWidth() / 2;
int height = getMeasuredHeight() / 2;
// 限定圆球移动的圆圈,该圆圈小于圆球的移动范围
canvas.drawCircle(width, height, r * circleScale, mPaint);
pinWheelBmp = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
// 限定圆球的大小
pinWheelBmp = Bitmap.createScaledBitmap(pinWheelBmp, r, r, true);
Matrix matrix = new Matrix();
if (within(moveX, moveY)) {
x = moveX;
y = moveY;
}
//通过matrix控制圆球的移动
matrix.preTranslate(getMeasuredWidth() / 2 - pinWheelBmp.getWidth() / 2 + x / scale, getMeasuredHeight() / 2 - pinWheelBmp.getHeight() / 2 + y / scale);
canvas.drawBitmap(pinWheelBmp, matrix, null);
if (!TextUtils.isEmpty(drawText)) {
mPaint.setColor(Color.WHITE);
mPaint.setAlpha((int) ((textAlpha / r) * 255));
canvas.drawText(drawText, textX, textY, mPaint);
mPaint.setAlpha(255);
}
// canvas.drawPicture();
}
private static Runnable sRunnable = new Runnable() {
@Override
public void run() {
Log.d("ndh--", "vibrate---");
sVibrator.vibrate(Config.VIBRATE_TIME);
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//rawX表示距离整个屏幕的x距离 getX表示距离父控件x距离
startX = event.getRawX();
startY = event.getRawY();
click = true;
longClick = true;
if (!FloatingWindowManager.create(getContext()).isOpen()) {
postDelayed(sRunnable, Config.WAITING_TIME);
}
case MotionEvent.ACTION_MOVE:
// 该view 是通过FloatinigWindowManager加载到窗体,由于 menuItem也是通过该管理器加载的,
//需要在menuItem加载进窗体的时候 禁止FloatingView的拖拽效果
if (FloatingWindowManager.create(getContext()).isOpen()) {
return true;
}
if (canDrag) {
moveX = event.getRawX() - startX;
moveY = event.getRawY() - startY;
if (Math.abs(moveX) > r / 10 || Math.abs(moveY) > r / 10) {
removeCallbacks(sRunnable);
isMoving = true;
click = false;
longClick = false;
drawText();
postInvalidate();
}
}
break;
case MotionEvent.ACTION_UP:
removeCallbacks(sRunnable);
isMoving = false;
if (!isLongClick(event) && click) {
FloatingViewManager.create().post(FloatingViewListener.CLICK);
break;
}
if (Math.abs(moveX / scale) > (r / 4) && Math.abs(moveX) > Math.abs(moveY)) {
//左右
if (moveX < 0) {
FloatingViewManager.create().post(FloatingViewListener.RIGHT);
} else {
FloatingViewManager.create().post(FloatingViewListener.LEFT);
}
}
if (Math.abs(moveY / scale) > (r / 4) && Math.abs(moveX) < Math.abs(moveY)) {
//上下
if (moveY < 0) {
FloatingViewManager.create().post(FloatingViewListener.DOWN);
} else {
FloatingViewManager.create().post(FloatingViewListener.UP);
}
}
moveX = 0;
moveY = 0;
textAlpha = 0;
postInvalidate();
break;
}
return true;
}
private boolean isLongClick(MotionEvent event) {
long downTime = event.getDownTime();
long upTime = event.getEventTime();
if (longClick && (upTime - downTime > Config.WAITING_TIME)) {
FloatingViewManager.create().post(FloatingViewListener.LONG_CLICK);
click = false;
longClick = false;
return true;
}
return false;
}
// 画 四个方位的字
private void drawText() {
if (Math.abs(moveX) > r / 10 && Math.abs(moveX) > Math.abs(moveY)) {
textAlpha = Math.abs((int) (moveX * 1.5) / scale);
//左右方向
if (moveX < 0) {
drawText = mRight;
textRect = rectFright;
textX = getMeasuredWidth() / 2 + getMeasuredWidth() / 4;
} else {
drawText = mLeft;
textRect = rectFleft;
textX = getMeasuredWidth() / 2 - getMeasuredWidth() / 4;
}
}
if (Math.abs(moveY) > r / 10 && Math.abs(moveX) < Math.abs(moveY)) {
textAlpha = Math.abs((int) (moveY * 1.5) / scale);
//上下方向
if (moveY < 0) {
drawText = mDown;
textRect = rectFdown;
} else {
drawText = mUp;
textRect = rectFtop;
}
textX = getMeasuredWidth() / 2;
}
textAlpha = textAlpha >= r ? r : textAlpha;
if (null != textRect)
textY = (textRect.bottom + textRect.top - mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top) / 2;
}
// 限制圆球只能在一个圆形范围移动,该方法只能放在onDraw里面,千万不要放到action_move里面,因为postInvalidate有延时,会导致实际滑动距离偏大
private boolean within(float startX, float startY) {
if (null == pinWheelBmp) {
return false;
}
double temp = (Math.sqrt((startX / scale) * (startX / scale) + (startY / scale) * (startY / scale)));
return temp <= r / 2;
}
/**
* 设置左上右下的文字提示
*
* @param left
* @param up
* @param right
* @param down
*/
@NotProguard
public void setTips(String left, String up, String right, String down) {
mLeft = left;
mUp = up;
mRight = right;
mDown = down;
}
@NotProguard
public boolean isMoving() {
return isMoving;
}
boolean canDrag = true;
@NotProguard
public void setCanDrag(boolean flag) {
canDrag = flag;
}
/**
* the width/height of this view
*
* @return
*/
@NotProguard
public int[] getSize() {
int[] size = new int[2];
size[0] = getMeasuredWidth();
size[1] = getMeasuredHeight();
// PackageManager pm=get
// ApplicationInfo applicationInfo
return size;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//以下四个矩形是为了定位 上下左右 四个方位上的字的位置
rectFtop = new RectF(getMeasuredWidth() / 2 - r * circleScale, getMeasuredHeight() / 2 - r * circleScale, getMeasuredWidth() / 2 + r * circleScale, getMeasuredHeight() / 2);
rectFleft = new RectF(getMeasuredWidth() / 2 - r * circleScale, getMeasuredHeight() / 2 - r * circleScale, getMeasuredWidth() / 2, getMeasuredHeight() / 2 + r * circleScale);
rectFright = new RectF(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - r * circleScale, getMeasuredWidth() / 2 + r * circleScale, getMeasuredHeight() / 2 + r * circleScale);
rectFdown = new RectF(getMeasuredWidth() / 2 - r * circleScale, getMeasuredHeight() / 2, getMeasuredWidth() / 2 + r * circleScale, getMeasuredHeight() / 2 + r * circleScale);
}
}