工具类构造方法的实现,同源码一样,我们这里也是初始化窗体的一些基本参数,并且初始化吐司要显示的布局。
/**
* 构造
* @param context
*/
public CustomToastUtil(Context context) {
this.mContext = context;
initParams();
}
/**
* 初始化窗体属性
*/
private void initParams() {
mWm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mParams = new WindowManager.LayoutParams();
mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// 类型
mParams.type = WindowManager.LayoutParams.TYPE_PHONE;
// 透明,不透明会出现重叠效果
mParams.format = PixelFormat.TRANSLUCENT;
// 位置属性
mParams.gravity = Gravity.TOP + Gravity.LEFT; // 左上
// 进来的时候把存储的位置读取显示出来
mParams.x = PreferenceUtil.getInt(mContext, "lastX");
mParams.y = PreferenceUtil.getInt(mContext, "lastY");
// 初始化吐司窗口布局
mView = View.inflate(mContext, R.layout.view_toast, null);
}
接下来就是显示吐司的逻辑,其实特别简单,核心代码只有一句,这里要先获取自定义填充布局文件中的TextView显示文本显示你要弹出的文本,然后对View的点击进行了监听,实现了双击将吐司居中显示,和三击隐藏吐司的功能。
/**
* 弹出自定义吐司
*/
public void popToast(String text) {
TextView tvName = (TextView) mView.findViewById(R.id.tv_toast_name);
// 设置显示的文字
tvName.setText(text);
// 吐司窗体的背景可以在布局文件之中指定也可以在代码中设置
// 设置吐司的双击事件,点击之后会到中心点
mView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 双击事件处理逻辑
System.arraycopy(mHits1, 1, mHits1, 0, mHits1.length - 1);
mHits1[mHits1.length - 1] = SystemClock.uptimeMillis();
if (mHits1[0] >= (SystemClock.uptimeMillis() - 500)) {
// 双击之后执行
// 让吐司移动到x中心,y不需要对中
// 更新窗体的坐标
mParams.x = (mWm.getDefaultDisplay().getWidth() - mView.getWidth()) / 2;
mWm.updateViewLayout(mView, mParams);
// 点击完退出的时候也把位置信息存储起来
PreferenceUtil.putInt(mContext, "lastX", mParams.x);
PreferenceUtil.putInt(mContext, "lastY", mParams.y);
}
// 三击事件处理逻辑
System.arraycopy(mHits2, 1, mHits2, 0, mHits2.length - 1);
mHits2[mHits2.length - 1] = SystemClock.uptimeMillis();
if (mHits2[0] >= (SystemClock.uptimeMillis() - 600)) {
// 点击之后将吐司移除掉
if (mView != null) {
if (mView.getParent() != null) {
mWm.removeView(mView);
}
}
}
}
});
// 设置吐司的触摸滑动事件
mView.setOnTouchListener(new View.OnTouchListener() {
int startX;
int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // 按下
// 手指按下时的坐标位置
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE: // 移动
// 移动后的坐标位置
int newX = (int) event.getRawX();
int newY = (int) event.getRawY();
// 偏移量
int dx = newX - startX;
int dy = newY - startY;
// 给偏移量设置边距
// 小于x轴
if (mParams.x < 0) {
mParams.x = 0;
}
// 小于y轴
if (mParams.y < 0) {
mParams.y = 0;
}
// 超出x轴
if (mParams.x > mWm.getDefaultDisplay().getWidth() - mView.getWidth()) {
mParams.x = mWm.getDefaultDisplay().getWidth() - mView.getWidth();
}
// 超出y轴
if (mParams.y > mWm.getDefaultDisplay().getHeight() - mView.getHeight()) {
mParams.y = mWm.getDefaultDisplay().getHeight() - mView.getHeight();
}
// 更新窗体的坐标
mParams.x += dx;
mParams.y += dy;
mWm.updateViewLayout(mView, mParams);
// 重新赋值起始坐标
startX = (int) event.getRawX();
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP: // 抬起
// 抬起来的时候保存最后一次的位置,下次进来时直接显示出来
PreferenceUtil.putInt(mContext, "lastX", mParams.x);
PreferenceUtil.putInt(mContext, "lastX", mParams.y);
break;
default:
break;
}
return false; // 当有父控件有点击事件时,这里要返回false,不然父控件就拿不到点击事件了
}
});
if (mView != null) {
if (mView.getParent() != null) {
mWm.removeView(mView);
}
}
// 添加到窗体管理器中才能显示出来
mWm.addView(mView, mParams);
}