package com.ccxt.whl.widget;
import java.util.List;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.ccxt.whl.R;
public class FloatingView extends View {
private static final String TAG = "TableShowView";
public static final int STAT_READY_GENERAL = 1; // 表示已进入普通通话状态
public static final int STAT_OPER_BUILD = 3; // 开始建立安全信道
public static final int STAT_OPER_CHECK = 4; // 开始验证身份
public static final int STAT_READY_SECURE = 5; // 表示进入加密通话状态
public static final int STAT_OPER_DES = 6;
Context mContext;
WindowManager mWindowManager; // WindowManager
ActivityManager mActivityManager; // 根据当前Activity来处理控制界面的隐藏
List<ActivityManager.RunningTaskInfo> initTaskInfo;
OnCtrlViewTouchListener mCtrlViewTouchListener;
UpdateStatHander mUpdateStatusHandler; // 用于更新当前通话状态的Handler
View mCtrlView;
View mDetailView;
long operDur; // 用于记录用户点击控件的时间,如果Touch控件的时间较短,就认为这Touch是一次点击
public FloatingView(Context context) {
super(context);
mContext = context;
mWindowManager = (WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
}
public void showFloatingBtn() {
// 设置载入view WindowManager参数
initTaskInfo = mActivityManager.getRunningTasks(1);
mCtrlViewTouchListener = new OnCtrlViewTouchListener(mWindowManager,
showCtrlView(mWindowManager));
// mCtrlViewLayoutParams = showCtrlView(mWindowManager);
mCtrlView.setOnTouchListener(mCtrlViewTouchListener);
mUpdateStatusHandler = new UpdateStatHander();
removeCtrlViewByTopActivityChag();
}
private class OnCtrlViewTouchListener implements OnTouchListener {
private static final long MAX_MILLI_TREAT_AS_CLICK = 100; //当用户触控控制按钮的时间小于该常量毫秒时,就算控制按钮的位置发生了变化,也认为这是一次点击事件
private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
// 触屏监听
float mLastX, mLastY;
int mOldOffsetX, mOldOffsetY;
int mRecordFlag = 0; // 用于重新记录CtrlView位置的标志
long mTouchDur; //记录用户触控控制按钮的时间
boolean hasShowedDetail = false;
public OnCtrlViewTouchListener(WindowManager windowManager,
WindowManager.LayoutParams layoutParams) {
mWindowManager = windowManager;
mLayoutParams = layoutParams;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
final int action = event.getAction();
float x = event.getX();
float y = event.getY();
if (mRecordFlag == 0) {
mOldOffsetX = mLayoutParams.x; // 偏移量
mOldOffsetY = mLayoutParams.y; // 偏移量
}
if (action == MotionEvent.ACTION_DOWN) {
mLastX = x;
mLastY = y;
mTouchDur = System.currentTimeMillis();
} else if (action == MotionEvent.ACTION_MOVE) {
mLayoutParams.x += (int) (x - mLastX); // 偏移量
mLayoutParams.y += (int) (y - mLastY); // 偏移量
mRecordFlag = 1;
mWindowManager.updateViewLayout(mCtrlView, mLayoutParams);
}
else if (action == MotionEvent.ACTION_UP) {
mTouchDur = System.currentTimeMillis() - mTouchDur;
int newOffsetX = mLayoutParams.x;
int newOffsetY = mLayoutParams.y;
if (mTouchDur < MAX_MILLI_TREAT_AS_CLICK || (mOldOffsetX == newOffsetX && mOldOffsetY == newOffsetY)) {
if (hasShowedDetail == false) {
if (mDetailView == null) {
showDetailView(mWindowManager);
} else {
mDetailView.setVisibility(VISIBLE);
}
hasShowedDetail = true;
} else {
mDetailView.setVisibility(INVISIBLE);
hasShowedDetail = false;
}
} else {
mRecordFlag = 0;
}
}
return true;
}
/**
* 该方法会显示详情视图
*
* @param windowManager
* 用于控制通话状态标示出现的初始位置(默认居中)、大小以及属性
* @return 会返回所创建的控制按钮的WindowManager.LayoutParams型对象。
*/
private WindowManager.LayoutParams showDetailView(
WindowManager windowManager) {
mDetailView = LayoutInflater.from(mContext).inflate(
R.layout.detail_window, null);
mDetailView.setBackgroundColor(Color.TRANSPARENT);
setDetailBtnsListener();
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
//layoutParams.type = 2003; // type是关键,这里的2002表示系统级窗口,你也可以试试2003。
layoutParams.type = 99; // type是关键,这里的2002表示系统级窗口,你也可以试试2003。
layoutParams.flags = 40;// 这句设置桌面可控
layoutParams.format = -3; // 透明
layoutParams.width = 400;
layoutParams.height = 230;
windowManager.addView(mDetailView, layoutParams);
return layoutParams;
}
private void setDetailBtnsListener() {
Button chgBtn = (Button) mDetailView
.findViewById(R.id.btn_chg_stat); // 设置改变通话状态按钮的监听器
chgBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
changCallingStat((Button) v);
}
});
Button hideBtn = (Button) mDetailView.findViewById(R.id.btn_hide); // 设置隐藏按钮的监听器
hideBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mDetailView.setVisibility(INVISIBLE);
hasShowedDetail = false;
}
});
Button removeBtn = (Button) mDetailView.findViewById(R.id.btn_remove);
removeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mWindowManager.removeView(mDetailView);
mWindowManager.removeView(mCtrlView);
}
});
}
private void changCallingStat(Button button) {
TextView currStat = (TextView) mDetailView
.findViewById(R.id.tv_curr_stat);
if ("".equals(
currStat.getText().toString())) {
button.setEnabled(false);
sendUpdateMsg(mUpdateStatusHandler, STAT_OPER_BUILD, 0);
sendUpdateMsg(mUpdateStatusHandler, STAT_OPER_CHECK, 2);
sendUpdateMsg(mUpdateStatusHandler, STAT_READY_SECURE, 3);
} else {
button.setEnabled(false);
sendUpdateMsg(mUpdateStatusHandler, STAT_OPER_DES, 0);
sendUpdateMsg(mUpdateStatusHandler, STAT_READY_GENERAL, 4);
}
}
/**
* 该方法用于向更新通话状态的Handler发送消息
*
* @param handler
* @param status
所发送的状态信息
* @param seconds
* 几秒后向handler发送消息
*/
private void sendUpdateMsg(Handler handler, int status, int seconds) {
final Message msg = Message.obtain(handler);
msg.what = status;
handler.postDelayed(new Runnable() {
@Override
public void run() {
msg.sendToTarget();
}
}, seconds * 1000);
}
}
/**
* 用于显示控制按钮,该控制按钮可以移动。当点击一次之后会弹出另一个浮动界面,本例中是详情界面
*
* @param windowManager
* 用于控制通话状态标示出现的初始位置、大小以及属性
* @return 会返回所创建的通话状态标示的WindowManager.LayoutParams型对象,该对象会在移动过程中修改。
*/
private WindowManager.LayoutParams showCtrlView(WindowManager windowManager) {
mCtrlView = LayoutInflater.from(mContext).inflate(R.layout.ctrl_window,
null);
mCtrlView.setBackgroundColor(Color.TRANSPARENT);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.type = 2003; // type是关键,这里的2002表示系统级窗口,你也可以试试2003。
layoutParams.flags = 40;// 这句设置桌面可控
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
layoutParams.x = 60;
layoutParams.y = 80;
layoutParams.width = 80;
layoutParams.height = 80;
layoutParams.format = -3; // 透明
windowManager.addView(mCtrlView, layoutParams);// 这句是重点
// 给WindowManager中丢入刚才设置的值
// 只有addview后才能显示到页面上去。
// 注册到WindowManager win是要刚才随便载入的layout,
// wmParams是刚才设置的WindowManager参数集
// 效果是将win注册到WindowManager中并且它的参数是wmParams中设置饿
return layoutParams;
}
private class UpdateStatHander extends Handler {
@Override
public void handleMessage(Message msg) {
TextView currStat = (TextView) mDetailView
.findViewById(R.id.tv_curr_stat);
Button changButton = (Button) mDetailView
.findViewById(R.id.btn_chg_stat);
ImageView statImg = (ImageView) mCtrlView
.findViewById(R.id.img_stat);
switch (msg.what) {
case STAT_READY_GENERAL:
currStat.setText(mContext.getString(R.string.stat_gen));
//statImg.setBackgroundResource(R.drawable.stat_gen);
changButton.setEnabled(true);
break;
case STAT_OPER_BUILD:
currStat.setText(mContext.getString(R.string.stat_build));
break;
case STAT_OPER_CHECK:
currStat.setText(R.string.stat_chk_auth);
break;
case STAT_READY_SECURE:
currStat.setText(mContext.getString(R.string.stat_sec));
//statImg.setBackgroundResource(R.drawable.stat_sec);
changButton.setEnabled(true);
break;
case STAT_OPER_DES:
currStat.setText(mContext.getString(R.string.stat_des));
break;
}
}
}
/**
* 该方法会在第5、10、15秒检测topActivity是否是发生了变化,如果发生了变化就移除浮动控制按钮
*
*/
private void removeCtrlViewByTopActivityChag() {
for(int i = 0; i < 5; i++) {
mUpdateStatusHandler.postDelayed(new Runnable() {
@Override
public void run() {
String currPackName= mActivityManager.getRunningTasks(1).get(0).topActivity.getPackageName(); //得到正运行的App包名
String initPackName = initTaskInfo.get(0).topActivity.getPackageName(); //得到显示浮动控制按钮时的App包名
Log.w(TAG, "oldPackageName: " + initPackName
+ " currPackageName: " + currPackName);
if(!currPackName.equals(initPackName)) {
if(mDetailView != null) {
mWindowManager.removeView(mDetailView);
mDetailView = null;
}
if(mCtrlView != null) {
mWindowManager.removeView(mCtrlView);
mCtrlView = null;
}
}
}
}, 3 * (i + 1) * 1000);
}
}
}