自己之前写的浮标,代码和UI有耦合,没空修改,复制下来改改就可以用
package com.yyl.mydemo.view;
/**
* @author 林雷
* @email 374353845@qq.com
* 悬浮窗 (浮标)
* yl_float_right yl_float_left 两个图片是浮标分别隐藏在左右屏幕漏出来的小半边
* 使用:
* 使用 activity : ActivityUtil.getTopActivity()
*/
public class YLFloatView extends FrameLayout implements OnTouchListener {
private String PLEASE_LOGIN = "请登录后进行操作";
/**
* 浮标的高度
*/
private final int floatH = 43;
/**
* 浮标logo的宽度
*/
int floatHideLogoW = 0;
/**
* logo 和 第一个菜单 的间距
* 注:不管左边或者右边,都是第一个间距
*/
private int logoAndFirstMenuMargin = 48;
/**
* 最后一个菜单离尾巴的间距
* 注:不管左边或者右边,都是最后一个菜单离尾巴的间距
*/
private int lastMenuAndEndMargin = 18;
/**
* 隐藏LOGO
*/
private final int HANDLER_TYPE_HIDE_LOGO = 100;
/**
* 退出动画
*/
private final int HANDLER_TYPE_CANCEL_ANIM = 101;
private WindowManager.LayoutParams mWmParams;
private WindowManager mWindowManager;
private Context context;
private boolean mIsRight;//浮标是否在右边
private boolean mCanHide;//是否允许隐藏
private boolean isHideFloat;//浮标是否隐藏 (显示半边)
private float mTouchStartX;
private float mTouchStartY;
private int mScreenWidth;
private int mScreenHeight;
private boolean mDraging;
/**
* 是否显示浮标的标识
*/
private boolean mShowLoader = true;
private FrameLayout fLayoutFloat;
private ImageView imgFloatIcon;
private ImageView imgFolatNotify;
// private ImageView imgMore;
private LinearLayout lLayoutMenu;
// private ImageView imgPhone;
// private ImageView imgQQ;
// private ImageView imgRelation;
// private ImageView imgWX;
// private ImageView imgLogout;
private FrameLayout p;
// private ImageView imgCenter;
private Timer mTimer = new Timer();
private TimerTask mTimerTask;
/**
* 菜单内容第一个
*/
private LinearLayout lLayoutMenuFirst = null;
/**
* 菜单内容最后一个
*/
private LinearLayout lLayoutMenuLast = null;
/**
* 注销
*/
private LinearLayout lLayoutMenuLogout = null;
/**
* 显示登录UI
*/
private LinearLayout lLayoutMenuShowLoginUI = null;
final Handler mTimerHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == HANDLER_TYPE_HIDE_LOGO) {
// 比如隐藏悬浮框
if (mCanHide) {
isHideFloat = true;
mCanHide = false;
hideFloatUI();
}
} else if (msg.what == HANDLER_TYPE_CANCEL_ANIM) {
imgFolatNotify.clearAnimation();
imgFolatNotify.setVisibility(View.GONE);
mShowLoader = false;
}
super.handleMessage(msg);
}
};
public YLFloatView(Context context) {
super(context);
init(context);
}
private void init(Context mContext) {
this.context = mContext;
// 浮标只显示 1半 , -6 px 让其更贴近屏幕旁边
floatHideLogoW = floatH / 2 - 6;
setWindowManager();
hide();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
YLog.i("onConfigurationChanged");
// 更新浮动窗口位置参数 靠边
DisplayMetrics dm = new DisplayMetrics();
// 获取屏幕信息
mWindowManager.getDefaultDisplay().getMetrics(dm);
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
int oldX = mWmParams.x;
int oldY = mWmParams.y;
switch (newConfig.orientation) {
case Configuration.ORIENTATION_LANDSCAPE://横屏
if (mIsRight) {
mWmParams.x = mScreenWidth;
mWmParams.y = oldY;
} else {
mWmParams.x = oldX;
mWmParams.y = oldY;
}
break;
case Configuration.ORIENTATION_PORTRAIT://竖屏
if (mIsRight) {
mWmParams.x = mScreenWidth;
mWmParams.y = oldY;
} else {
mWmParams.x = oldX;
mWmParams.y = oldY;
}
break;
}
mWindowManager.updateViewLayout(this, mWmParams);
}
private void setWindowManager() {
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
// 更新浮动窗口位置参数 靠边
DisplayMetrics dm = new DisplayMetrics();
// 获取屏幕信息
mWindowManager.getDefaultDisplay().getMetrics(dm);
mScreenWidth = dm.widthPixels;
mScreenHeight = dm.heightPixels;
this.mWmParams = new WindowManager.LayoutParams();
// 设置window type 不作对 19以下系统的适配
mWmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// mWmParams.type = WindowManager.LayoutParams.TYPE_TOAST;
// } else {
// mWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
// }
// 设置图片格式,效果为背景透明
mWmParams.format = PixelFormat.RGBA_8888;
// 设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
mWmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
// 调整悬浮窗显示的停靠位置为左侧置�?
mWmParams.gravity = Gravity.LEFT | Gravity.TOP;
mScreenHeight = mWindowManager.getDefaultDisplay().getHeight();
// 以屏幕左上角为原点,设置x、y初始值,相对于gravity
mWmParams.x = 0;
mWmParams.y = mScreenHeight / 2;
// 设置悬浮窗口长宽数据
mWmParams.width = LayoutParams.WRAP_CONTENT;
mWmParams.height = LayoutParams.WRAP_CONTENT;
addView(createView(context));
mWindowManager.addView(this, mWmParams);
}
/**
* 刷新浮标窗口参数
* 整个浮标
*/
private void refreshFloatWindowParams() {
if (isHideFloat) {
// 窗口隐藏
mWmParams.alpha = 0.3f;
mWindowManager.updateViewLayout(YLFloatView.this, mWmParams);
} else {
// 窗口显示
mWmParams.alpha = 1f;
mWindowManager.updateViewLayout(this, mWmParams);
}
}
/**
* 隐藏浮标的UI操作
* 只露出半边 logo
*/
private void hideFloatUI() {
//隐藏后浮标的宽的
refreshFloatWindowParams();
refreshFloatLogoParams();
refreshFloatMenuParams();
lLayoutMenu.setVisibility(View.GONE);
}
/**
* 刷新 logo 的参数
*/
private void refreshFloatLogoParams() {
LayoutParams fLayoutFloatParams = (LayoutParams) fLayoutFloat.getLayoutParams();
if (mIsRight) {
fLayoutFloatParams.gravity = Gravity.RIGHT;
} else {
fLayoutFloatParams.gravity = Gravity.LEFT;
}
if (isHideFloat) {
// 隐藏
fLayoutFloatParams.width = DisplayUtil.dp2px(floatHideLogoW);
fLayoutFloatParams.height = DisplayUtil.dp2px(floatH);
if (mIsRight) {
imgFloatIcon.setImageResource(ResUtil.getDrawableId(context, "yl_float_right"));
} else {
imgFloatIcon.setImageResource(ResUtil.getDrawableId(context, "yl_float_left"));
}
} else {
// 显示
fLayoutFloatParams.width = DisplayUtil.dp2px(floatH);
fLayoutFloatParams.height = DisplayUtil.dp2px(floatH);
imgFloatIcon.setImageResource(ResUtil.getDrawableId(
context, "yl_float_logo"));
}
fLayoutFloat.setLayoutParams(fLayoutFloatParams);
}
/**
* 创建Float view
*
* @param context
* @return
*/
private View createView(final Context context) {
p = new FrameLayout(context);
p.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, DisplayUtil.dp2px(floatH)));
addMenuContentView(context);
// 浮标 start
fLayoutFloat = new FrameLayout(context);
LayoutParams fLayoutFloatParams = new LayoutParams(DisplayUtil.dp2px(floatH), DisplayUtil.dp2px(floatH));
fLayoutFloatParams.gravity = Gravity.LEFT;
fLayoutFloat.setLayoutParams(fLayoutFloatParams);
fLayoutFloat.setOnTouchListener(this);
//浮标头像
imgFloatIcon = new ImageView(context);
LinearLayout.LayoutParams imgFloatIconParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
imgFloatIcon.setLayoutParams(imgFloatIconParams);
imgFloatIcon.setImageResource(ResUtil.getDrawableId(context, "yl_float_logo"));
// 浮标刷新
imgFolatNotify = new ImageView(context);
imgFolatNotify.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imgFolatNotify.setImageResource(ResUtil.getDrawableId(context, "yl_anim_background"));
fLayoutFloat.addView(imgFloatIcon);
fLayoutFloat.addView(imgFolatNotify);
// 浮标 end
p.addView(lLayoutMenu);
p.addView(fLayoutFloat);
p.setOnTouchListener(this);
p.measure(MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED), MeasureSpec
.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
fLayoutFloat.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YLog.i("进入点击菜单按钮");
isHideFloat = false;
refreshFloatLogoParams();
refreshFloatMenuParams();
changeMeunVisibilityByIsLogin(lLayoutMenuLogout, true);
changeMeunVisibilityByIsLogin(lLayoutMenuShowLoginUI, false);
if (!mDraging) {
if (lLayoutMenu.getVisibility() == View.VISIBLE) {
lLayoutMenu.setVisibility(View.GONE);
} else {
lLayoutMenu.setVisibility(View.VISIBLE);
}
}
}
});
return p;
}
/**
* 添加菜单内容
*
* @param context
*/
private void addMenuContentView(Context context) {
lLayoutMenu = new LinearLayout(context);
LinearLayout.LayoutParams lLayoutMenuParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, DisplayUtil.dp2px(floatH));
lLayoutMenuParams.gravity = Gravity.CENTER; //布局文件中的Android:layout_gravity属性
lLayoutMenu.setGravity(Gravity.CENTER); //布局文件中的Android:gravity属性
lLayoutMenu.setLayoutParams(lLayoutMenuParams);
lLayoutMenu.setOrientation(LinearLayout.HORIZONTAL);
lLayoutMenu.setVisibility(View.GONE);
lLayoutMenu.setBackgroundResource(ResUtil.getDrawableId(context, "yl_menu_bg"));
lLayoutMenuFirst = createMeunUI(context, logoAndFirstMenuMargin, 8, "yl_relation", "横竖屏切换");
lLayoutMenuLogout = createMeunUI(context, "yl_logout", "注销");
lLayoutMenuShowLoginUI = createMeunUI(context, "yl_login", "登录");
lLayoutMenuLast = createMeunUI(context, 8, lastMenuAndEndMargin, "yl_more", " 更多");
lLayoutMenu.addView(lLayoutMenuFirst);
lLayoutMenu.addView(lLayoutMenuLogout);
lLayoutMenu.addView(lLayoutMenuShowLoginUI);
lLayoutMenu.addView(lLayoutMenuLast);
lLayoutMenuLogout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YLog.i("点击注销按钮");
changeMeunVisibilityByIsLogin(lLayoutMenuLogout, true);
// userService.logout(ActivityUtil.getTopActivity());
}
});
lLayoutMenuShowLoginUI.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YLog.i("点击显示登录UI按钮");
changeMeunVisibilityByIsLogin(lLayoutMenuShowLoginUI, false);
// userService.showLoginUI(ActivityUtil.getTopActivity());
}
});
lLayoutMenuLast.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YLog.i("点击更多按钮");
// if (YLUserUtil.isLogin()) {
// floatService.createBigFloat();
// floatService.showBigFloat();
// } else {
// ToastUtil.showShortToast(PLEASE_LOGIN);
// }
}
});
lLayoutMenuFirst.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
YLog.i("点击横竖屏切换按钮");
Activity currentActivity = ActivityUtil.getTopActivity();
// 如果是 BigFloatActivity 不允许切换成竖屏
// if (currentActivity instanceof BigFloatActivity) {
// YLog.i("当前 activity 为 BigFloatActivity ");
// ToastUtil.showShortToast("浮标界面不允许切换为竖屏");
// return;
// }
// boolean currentOrientation = systemService.isScreenOrientation();
// systemService.setScreenOrientation(!currentOrientation);
}
});
}
/**
* 创建菜单中每个功能的UI
* 注:第一个控件 setMargins(DisplayUtil.dp2px(context, 53), 0, 0, 0); 距离左边的距离必须是 53
* 注:最后一个控件 setMargins(0, 0, DisplayUtil.dp2px(context, 16), 0) 距离右边的距离必须是 16
*
* @param context
* @param marginLeft
* @param marginRight
* @param drawableName
* @param textName
*/
private LinearLayout createMeunUI(Context context, int marginLeft, int marginRight, String drawableName, String textName) {
LinearLayout lLayoutMenu = new LinearLayout(context);
int llLayoutH = floatH - 6;
LinearLayout.LayoutParams lLayoutMenuParams = new LinearLayout.LayoutParams(DisplayUtil.dp2px(23), DisplayUtil.dp2px(llLayoutH), 1);
lLayoutMenu.setGravity(Gravity.CENTER); //布局文件中的Android:gravity属性
lLayoutMenuParams.setMargins(DisplayUtil.dp2px(context, marginLeft), 0, DisplayUtil.dp2px(context, marginRight), 0);
lLayoutMenu.setLayoutParams(lLayoutMenuParams);
lLayoutMenu.setOrientation(LinearLayout.VERTICAL);
ImageView imgMenu = new ImageView(context);
imgMenu.setLayoutParams(new LinearLayout.LayoutParams(DisplayUtil.dp2px(22), DisplayUtil.dp2px(22)));
imgMenu.setImageResource(ResUtil.getDrawableId(context, drawableName));
TextView txtMenu = new TextView(context);
LinearLayout.LayoutParams txtMenuParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtil.dp2px(12));
txtMenu.setGravity(Gravity.CENTER); //布局文件中的Android:gravity属性
txtMenu.setLayoutParams(txtMenuParams);
// txtMenu.setTextColor(ColorsConstan.WHITE);
txtMenu.setTextSize(10);
txtMenu.setText(textName);
lLayoutMenu.addView(imgMenu);
lLayoutMenu.addView(txtMenu);
return lLayoutMenu;
}
/**
* 创建菜单中每个功能的UI
*
* @param context
* @param drawableName
* @param textName
*/
private LinearLayout createMeunUI(Context context, String drawableName, String textName) {
return createMeunUI(context, 0, 0, drawableName, textName);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
removeTimerTask();
// 获取相对屏幕的坐标,即以屏幕左上角为原点
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// YLog.i("ACTION_DOWN");
mTouchStartX = event.getX();
mTouchStartY = event.getY();
isHideFloat = false;
refreshFloatLogoParams();
refreshFloatWindowParams();
mDraging = false;
break;
case MotionEvent.ACTION_MOVE:
// YLog.i("ACTION_MOVE");
float mMoveStartX = event.getX();
float mMoveStartY = event.getY();
// 如果移动量大于3才移动
if (Math.abs(mTouchStartX - mMoveStartX) > 3
&& Math.abs(mTouchStartY - mMoveStartY) > 3) {
mDraging = true;
// 更新浮动窗口位置参数
mWmParams.x = (int) (x - mTouchStartX);
mWmParams.y = (int) (y - mTouchStartY);
mWindowManager.updateViewLayout(this, mWmParams);
lLayoutMenu.setVisibility(View.GONE);
return false;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
YLog.i("ACTION_CANCEL ");
if (mWmParams.x >= mScreenWidth / 2) {
mWmParams.x = mScreenWidth;
mIsRight = true;
} else if (mWmParams.x < mScreenWidth / 2) {
mIsRight = false;
mWmParams.x = 0;
}
refreshFloatLogoParams();
refreshFloatMenuParams();
timerForHide();
mWindowManager.updateViewLayout(this, mWmParams);
// 初始化
mTouchStartX = mTouchStartY = 0;
break;
}
return false;
}
private void removeTimerTask() {
if (mTimerTask != null) {
mTimerTask.cancel();
mTimerTask = null;
}
}
private void removeFloatView() {
try {
mWindowManager.removeView(this);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 隐藏悬浮窗
*/
public void hide() {
setVisibility(View.GONE);
Message message = mTimerHandler.obtainMessage();
message.what = HANDLER_TYPE_HIDE_LOGO;
mTimerHandler.sendMessage(message);
removeTimerTask();
}
/**
* 是否显示悬浮窗
*/
public boolean isShow() {
if (VISIBLE == getVisibility()) {
return true;
} else {
return false;
}
}
/**
* 根据登录状态 改变菜单按钮的显示状态
*
* @param meun
* @param loginIsShow 登录后是否显示, ture 是 ; false 否
*/
private void changeMeunVisibilityByIsLogin(LinearLayout meun, boolean loginIsShow) {
//
// if (loginIsShow) {
// if (YLUserUtil.isLogin()) {
// meun.setVisibility(VISIBLE);
// } else {
// meun.setVisibility(GONE);
// }
// } else {
// if (YLUserUtil.isLogin()) {
// meun.setVisibility(GONE);
// } else {
// meun.setVisibility(VISIBLE);
// }
// }
}
/**
* 显示悬浮窗
*/
public void show() {
if (getVisibility() != View.VISIBLE) {
setVisibility(View.VISIBLE);
if (mShowLoader) {
isHideFloat = false;
refreshFloatLogoParams();
refreshFloatWindowParams();
mShowLoader = false;
startAnimation();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
//隐藏logo
timerForHide();
// 取消动画
mTimerHandler.sendEmptyMessage(HANDLER_TYPE_CANCEL_ANIM);
}
}, 1460); // 320 * 4 = 1280 + 180 = 1460 1460毫秒后启动定时器,
}
}
}
private void startAnimation() {
//1次320毫秒旋转 旋转 4次
RotateAnimation rotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
rotateAnimation.setRepeatMode(Animation.RESTART);
rotateAnimation.setRepeatCount(4);
rotateAnimation.setDuration(320);
imgFolatNotify.startAnimation(rotateAnimation);
}
/**
* 根据浮标在屏幕的位置
* 设置浮标内容的参数,浮标内容的排序
*/
private void refreshFloatMenuParams() {
// YLog.i("refreshFloatMenuParams");
if (imgFloatIcon == null) return;
// YLog.i("refreshFloatMenuParams !=========");
LinearLayout.LayoutParams lLayoutMenuLastParams = (LinearLayout.LayoutParams) lLayoutMenuLast.getLayoutParams();
LinearLayout.LayoutParams lLayoutMenuFirstParams = (LinearLayout.LayoutParams) lLayoutMenuFirst.getLayoutParams();
lLayoutMenu.removeView(lLayoutMenuFirst);
lLayoutMenu.removeView(lLayoutMenuLast);
if (mIsRight) {
// YLog.i("位于右边 !=========");
// 位于右边
// 第一个控件
//注: 第一个控件 setMargins(DisplayUtil.dp2px(context, 16), 0, 0, 0); 左边的距离必须是 16
lLayoutMenuLastParams.setMargins(DisplayUtil.dp2px(context, lastMenuAndEndMargin), 0, DisplayUtil.dp2px(context, 8), 0);
lLayoutMenuLast.setLayoutParams(lLayoutMenuLastParams);
// 最后一个控件
//注:最后一个控件 setMargins(0, 0, DisplayUtil.dp2px(context, 53), 0) 距离右边的距离必须是 53
lLayoutMenuFirstParams.setMargins(DisplayUtil.dp2px(context, 8), 0, DisplayUtil.dp2px(context, logoAndFirstMenuMargin), 0);
lLayoutMenuFirst.setLayoutParams(lLayoutMenuFirstParams);
lLayoutMenu.addView(lLayoutMenuLast, 0);
lLayoutMenu.addView(lLayoutMenuFirst);
} else {
// 位于左边
// YLog.i("位于左边 !=========");
// 第一个控件
//注: 第一个控件 setMargins(DisplayUtil.dp2px(context, 53), 0, 0, 0) 左边的距离必须是 53
lLayoutMenuFirstParams.setMargins(DisplayUtil.dp2px(context, logoAndFirstMenuMargin), 0, DisplayUtil.dp2px(context, 8), 0);
lLayoutMenuFirst.setLayoutParams(lLayoutMenuFirstParams);
// 最后一个控件
//注:最后一个控件 setMargins(0, 0, DisplayUtil.dp2px(context, 16), 0) 距离右边的距离必须是 16
lLayoutMenuLastParams.setMargins(DisplayUtil.dp2px(context, 8), 0, DisplayUtil.dp2px(context, lastMenuAndEndMargin), 0);
lLayoutMenuLast.setLayoutParams(lLayoutMenuLastParams);
lLayoutMenu.addView(lLayoutMenuFirst, 0);
lLayoutMenu.addView(lLayoutMenuLast);
}
}
/**
* 定时隐藏float view
*/
private void timerForHide() {
mCanHide = true;
//结束任务
if (mTimerTask != null) {
try {
mTimerTask.cancel();
mTimerTask = null;
} catch (Exception e) {
}
}
mTimerTask = new TimerTask() {
@Override
public void run() {
Message message = mTimerHandler.obtainMessage();
message.what = HANDLER_TYPE_HIDE_LOGO;
mTimerHandler.sendMessage(message);
}
};
if (mCanHide) {
mTimer.schedule(mTimerTask, 6000, 3000);
}
}
/**
* 打开用户中心
*/
private void openUserCenter() {
// PJSDK.doUCenter();
}
//
/**
* 打开客服页面
*/
private void openFeedback() {
// Intent intent = new Intent(PJSDK.getContext(), CustomerServicesActivity.class);
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// PJSDK.getContext().startActivity(intent);
}
/**
* 是否Float view
*/
public void destroy() {
hide();
removeFloatView();
removeTimerTask();
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
try {
mTimerHandler.removeMessages(1);
} catch (Exception e) {
}
}
}