BaseDialogView
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import com.bnux.api.common.tools.log.BnLogHelper;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* <p>功能描述:对话框的基础View
* 详细描述:
*
* @author 龚寿生
* @version V1.0
* @date 2021/1/21 16:13
*/
public abstract class BaseDialogView extends View implements View.OnTouchListener {
//当前屏幕宽度
private static final int MAX_SCREEN_WIDTH = 1600;
private static final long TIME_DIALOG_DISMISS = 15000;
private static final long TIME_ANIMATION_DISMISS = 500;
private static final int MAX_SLIDE_SIZE = 100;
private static final long TIME_ANIMATION_END_DIALOG_DISMISS = 600;
private ScheduledExecutorService mScheduledExecutorService;
private WindowManager mWindowManager;
private View view;
private float lastX;
private int defaultX;
private int width;
private boolean display = false;
private long size = 0;
private long last = 0;
protected final Context mContext;
protected WindowManager.LayoutParams layoutParams;
protected BaseDialogView(Context context) {
super(context);
mContext = context;
init();
initView(view);
}
/**
* 初始化界面
*/
private void init() {
//加载View视图,这个就是我们要显示的内容
view = LayoutInflater.from(mContext).inflate(layoutId(), null);
view.setOnTouchListener(this);
//获取WindowManage
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
//设置LayoutParams的属性
layoutParams = new WindowManager.LayoutParams();
//该Type描述的是形成的窗口的层级关系
layoutParams.type = getBnWindowType();
//该flags描述的是窗口的模式,是否可以触摸,可以聚焦等
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
//设置窗口的位置
layoutParams.gravity = getLayoutParamsGravity();
//不设置这个弹出框的透明遮罩显示为黑色
layoutParams.format = PixelFormat.TRANSLUCENT;
//窗口的宽
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//窗口的高
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
defaultX = layoutParams.x;
DisplayMetrics metrics2 = getResources().getDisplayMetrics();
width = metrics2.widthPixels;
mScheduledExecutorService = Executors.newScheduledThreadPool(2);
}
/**
* 默认布局在顶部居中显示
*
* @return 返回布局显示的位置
*/
protected int getLayoutParamsGravity() {
return Gravity.TOP | Gravity.CENTER_HORIZONTAL;
}
/**
* 这个方法主要是返回布局资源的R.layout.id
*
* @return 返回布局资源ID
*/
protected abstract int layoutId();
/**
* 这个方法主要是初始化View相关,确定自己布局有哪些控件需要初始化
*
* @param view 当前的布局对象
*/
protected abstract void initView(View view);
/**
* 这个方法主要是初始化View相关,确定自己布局有哪些控件需要初始化
*
* @return 当前的布局对象
*/
protected abstract int getBnWindowType();
/**
* 显示view界面
*/
protected void showView() {
BnLogHelper.LogV("显示Dialog");
if (display) {
hideView();
}
if (null != mWindowManager) {
size++;
display = true;
mWindowManager.addView(view, layoutParams);
scheduleTimeout();
}
}
/**
* 移除view界面
*/
protected void hideView() {
BnLogHelper.LogV("移除View界面");
if (display && null != mWindowManager) {
display = false;
mWindowManager.removeView(view);
}
}
/**
* 定时移除view界面
*/
private void scheduleTimeout() {
BnLogHelper.LogV("定时任务启动");
// 延时任务
mScheduledExecutorService.schedule((() -> {
last++;
if (last == size) {
hideView();
}
}), TIME_DIALOG_DISMISS, TimeUnit.MILLISECONDS);
}
/**
* 获取当前界面是否在显示
*
* @return 显示或者隐藏
*/
public boolean isDisplay() {
return display;
}
/**
* 主要处理拖动的事件,结束后的动画
*
* @param v 当前界面
* @param event 滑动处理
* @return 是否消耗事件
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
BnLogHelper.LogV("滑动删除");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
// 计算偏移量
float offsetX = event.getX() - lastX;
if (offsetX > 0) {
layoutParams.x = defaultX + (int) offsetX;
mWindowManager.updateViewLayout(view, layoutParams);
}
break;
case MotionEvent.ACTION_UP:
ValueAnimator animator;
if (event.getX() - lastX > MAX_SLIDE_SIZE) {
animator = ValueAnimator.ofInt(layoutParams.x, width);
endAnimRemoveView();
endAnimRemoveView();
} else {
animator = ValueAnimator.ofInt(layoutParams.x, defaultX);
}
animator.addUpdateListener(animation -> {
layoutParams.x = (int) animation.getAnimatedValue();
mWindowManager.updateViewLayout(view, layoutParams);
});
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(TIME_ANIMATION_DISMISS);
animator.start();
break;
default:
break;
}
return true;
}
/**
* 动画结束后移除view界面,恢复默认位置
*/
private void endAnimRemoveView() {
// 延时任务
mScheduledExecutorService.schedule((() -> {
hideView();
layoutParams.x = defaultX;
}), TIME_ANIMATION_END_DIALOG_DISMISS, TimeUnit.MILLISECONDS);
}
}