1.自定义拖动view
package com.example.overlaymsg;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.LinearInterpolator;
import android.widget.RelativeLayout;
public class OverlayMsgRelativeLayout extends RelativeLayout {
private final String TAG = "OMRelativeLayout";
private OnTouchViewListener onTouchViewListener;
public OverlayMsgRelativeLayout(Context context) {
this(context, null);
}
public OverlayMsgRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public OverlayMsgRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private float downX, downY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (onTouchViewListener != null) {
onTouchViewListener.onViewPress();
}
downX = event.getRawX();
downY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getRawX();
int moveY = (int) event.getRawY();
/**上、左、右 拖动 */
// if (moveY - downY < 0) {//向上拖动
// setTranslationY(moveY - downY);
// }
// setTranslationX(moveX - downX);
/**上、下、左、右 拖动 */
setTranslationY(moveY - downY);
setTranslationX(moveX - downX);
/**向下滑时,改变透明度*/
if (getTranslationY() > 0) {
setAlpha(1 - (getTranslationY() / (getMeasuredHeight())));
}
Log.i(TAG, "tx=" + getTranslationX() + ",ty=" + getTranslationY());
break;
case MotionEvent.ACTION_UP:
if (Math.abs(downX - event.getRawX()) <= 10 && Math.abs(downY - event.getRawY()) <= 10 && onTouchViewListener != null) {//常规点击事件
onTouchViewListener.onViewClick();
} else if (getTranslationY() < 0 && Math.abs(getTranslationY()) > getMeasuredHeight() / 3) {
animTopDismiss();
} else if (getTranslationY() > 0 && Math.abs(getTranslationY()) > getMeasuredHeight() / 2) {
animBottomDismiss();
} else if (getTranslationX() > getMeasuredWidth() / 4) {
animRightDismiss();
} else if (getTranslationX() < -getMeasuredWidth() / 4) {
animLeftDismiss();
} else {
// setTranslationX(0);
// setTranslationY(0);
setAlpha(1);//透明度还原
animBack();
}
break;
default:
break;
}
return true;
}
private int getScreenWidth() {
DisplayMetrics dm = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
getDisplay().getRealMetrics(dm);
}
// DisplayMetrics dm = getResources().getDisplayMetrics();
Log.i(TAG, "getScreenWidth=" + dm.widthPixels + ",h==" + dm.heightPixels);
return dm.widthPixels;
}
/**
* 动画,从顶部弹出
*/
private void animShow() {
//使用动画从顶部弹出
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationY", -getMeasuredHeight(), 0);
animator.setDuration(300);
animator.start();
}
/**
* 动画,从顶部弹出
*/
private void animBack() {
ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(this, "translationX", getTranslationX(), 0);
objectAnimatorX.setInterpolator(new LinearInterpolator());
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(this, "translationY", getTranslationY(), 0);
objectAnimatorY.setInterpolator(new LinearInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimatorX, objectAnimatorY);
animatorSet.setDuration(100);
animatorSet.start();
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Log.i(TAG, "tx=" + getTranslationX() + ",ty=" + getTranslationY());
if (onTouchViewListener != null) {
onTouchViewListener.onViewBack();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
/**
* 动画,从顶部收回
*/
private void animTopDismiss() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationY", getTranslationY(), -getMeasuredHeight());
animator.setDuration(100);
animator.setInterpolator(new LinearInterpolator());
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
if (onTouchViewListener != null) {
onTouchViewListener.onSlideTop();
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
}
/**
* 动画,从顶部收回
*/
private void animBottomDismiss() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationY", getTranslationY(), getMeasuredHeight() * 2.5f);
animator.setDuration(100);
animator.setInterpolator(new LinearInterpolator());
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
if (onTouchViewListener != null) {
onTouchViewListener.onSlideBottom();
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
}
/**
* 动画,从左边收回
*/
private void animLeftDismiss() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationX", getTranslationX(), -getScreenWidth());
animator.setDuration(100);
animator.setInterpolator(new LinearInterpolator());
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
if (onTouchViewListener != null) {
onTouchViewListener.onSlideLeft();
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
}
/**
* 动画,从右边收回
*/
private void animRightDismiss() {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, "translationX", getTranslationX(), getScreenWidth());
animator.setDuration(100);
animator.setInterpolator(new LinearInterpolator());
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(INVISIBLE);
if (onTouchViewListener != null) {
onTouchViewListener.onSlideRight();
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
}
public void setOnTouchViewListener(OnTouchViewListener onTouchViewListener) {
this.onTouchViewListener = onTouchViewListener;
}
public interface OnTouchViewListener {
void onViewPress();
void onViewBack();
void onSlideLeft();
void onSlideTop();
void onSlideRight();
void onSlideBottom();
void onViewClick();
}
}
2.消息展示
package com.example.overlaymsg;
import android.app.Activity;
import android.app.Dialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.Stack;
public class OverlayMsgHelper {
private static final String TAG = "OverlayMsgHelper";
private static View mMsgLayout;
private static int mLastHashCode = -1;
private static WindowManager mWindowManager;
private static Handler mOverlayHandler;
private static final long DELAY_MILLIS = 5000;//消息停留默认5000毫秒
private static Stack<View> mStack = new Stack<>();//多条消息叠加
private static Dialog mOverlaySettingDialog;//权限弹窗
/**
* 功能实现1:顶部消息替换
*/
public static void showReplaceMsg(String title,String content) {
final Activity activity = MyApplication.getMyApplication().getAliveActivity();
if(activity==null){
return;
}
/**创建 handler*/
if (mOverlayHandler == null) {
mOverlayHandler = new Handler(activity.getMainLooper());
}
Log.i(TAG, "mLastHashCode==" + activity.hashCode() + ",name=" + activity.getLocalClassName());
/**判断是否 已切换其他activity*/
if (mLastHashCode != activity.hashCode()) {
mLastHashCode = activity.hashCode();
if (mMsgLayout != null && mMsgLayout.getParent() != null && mWindowManager != null) {
mWindowManager.removeView(mMsgLayout);
}
}
/**移除定时任务*/
mOverlayHandler.removeCallbacks(mReplaceRunnable);
/**获取当前activity 的windowManager (注意:必须使用activity 实例,防止某些机型无法显示)*/
mWindowManager = activity.getWindowManager();
if (mMsgLayout == null || mMsgLayout.getParent() == null) {
mMsgLayout = LayoutInflater.from(MyApplication.getMyApplication()).inflate(R.layout.overlay_msg_layout, null, false);
ImageView ivIcon = mMsgLayout.findViewById(R.id.overlay_msg_icon);
TextView tvTitle = mMsgLayout.findViewById(R.id.overlay_msg_title);
TextView tvContent = mMsgLayout.findViewById(R.id.overlay_msg_content);
TextView tvTime = mMsgLayout.findViewById(R.id.overlay_msg_time);
tvTitle.setText(title);
tvContent.setText(content);
WindowManager.LayoutParams mWindowParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(activity)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //8.0新特性
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
}
}
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowParams.windowAnimations = R.style.overlay_msg_style_ainm;
mWindowParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//此方法 测量有误差,这里用于 获取 大概高度
mMsgLayout.measure(0, 0);
int measuredWidth = mMsgLayout.getMeasuredWidth();// 获取宽度
int measuredHeight = mMsgLayout.getMeasuredHeight();// 获取高度
Log.i(TAG, "measuredWidth=" + measuredWidth + ",measuredHeight=" + measuredHeight);
mWindowParams.height = measuredHeight * 2;//设置窗口高度,用于向下拖动效果
// mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;//设置窗口自适应高度
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.gravity = Gravity.TOP;
/**全屏的 activity 设置 边距*/
if ((activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) {
mWindowParams.y = getStatusBarHeight();
}
OverlayMsgRelativeLayout msgRelativeLayout = mMsgLayout.findViewById(R.id.overlay_rl_layout);
msgRelativeLayout.setOnTouchViewListener(new OverlayMsgRelativeLayout.OnTouchViewListener() {
@Override
public void onViewPress() {
mOverlayHandler.removeCallbacks(mReplaceRunnable);
}
@Override
public void onViewBack() {
mOverlayHandler.postDelayed(mReplaceRunnable, DELAY_MILLIS);
}
@Override
public void onSlideLeft() {
if (mMsgLayout.getParent() != null) {
Log.i(TAG, "左边移除消息");
mOverlayHandler.removeCallbacks(mReplaceRunnable);
mWindowManager.removeView(mMsgLayout);
}
}
@Override
public void onSlideTop() {
if (mMsgLayout.getParent() != null) {
Log.i(TAG, "顶部边移除消息");
mOverlayHandler.removeCallbacks(mReplaceRunnable);
mWindowManager.removeView(mMsgLayout);
}
}
@Override
public void onSlideRight() {
if (mMsgLayout.getParent() != null) {
Log.i(TAG, "右边移除消息");
mOverlayHandler.removeCallbacks(mReplaceRunnable);
mWindowManager.removeView(mMsgLayout);
}
}
@Override
public void onSlideBottom() {
if (mMsgLayout.getParent() != null) {
Log.i(TAG, "右边移除消息");
mOverlayHandler.removeCallbacks(mReplaceRunnable);
mWindowManager.removeView(mMsgLayout);
}
//模拟跳转界面
activity.startActivity(new Intent(activity,FristActivity.class));
}
@Override
public void onViewClick() {
if (mMsgLayout.getParent() != null) {
Log.i(TAG, "点击消息=");
mWindowManager.removeView(mMsgLayout);
mOverlayHandler.removeCallbacks(mReplaceRunnable);
}
//模拟跳转界面
activity.startActivity(new Intent(activity,FristActivity.class));
}
});
/**添加到窗口*/
mWindowManager.addView(mMsgLayout, mWindowParams);
} else {
if (mMsgLayout.getParent() != null) {
ImageView ivIcon = mMsgLayout.findViewById(R.id.overlay_msg_icon);
TextView tvTitle = mMsgLayout.findViewById(R.id.overlay_msg_title);
TextView tvContent = mMsgLayout.findViewById(R.id.overlay_msg_content);
TextView tvTime = mMsgLayout.findViewById(R.id.overlay_msg_time);
tvTitle.setText(title);
tvContent.setText(content);
/**更新消息*/
mWindowManager.updateViewLayout(mMsgLayout, mMsgLayout.getLayoutParams());
}
}
/**应用上层显示权限申请提示框*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(activity)) {
showOverlaySettingDialog(activity);
}
}
/**震动*/
phoneVibrates();
/**播放通知铃声*/
playRing(MyApplication.getMyApplication());
/**开启定时任务*/
mOverlayHandler.postDelayed(mReplaceRunnable, DELAY_MILLIS);
}
/**用于 替换消息的 runnable*/
private static Runnable mReplaceRunnable = new Runnable() {
@Override
public void run() {
if (mMsgLayout != null && mMsgLayout.getParent() != null && mWindowManager != null) {
mWindowManager.removeView(mMsgLayout);
}
}
};
/**
* 功能实现2:顶部消息重叠
*/
public static void showOverlayMsg(String title, String content) {
final Activity activity = MyApplication.getMyApplication().getAliveActivity();
if (activity == null) {
return;
}
/**创建 handler*/
if (mOverlayHandler == null) {
mOverlayHandler = new Handler(MyApplication.getMyApplication().getMainLooper());
}
Log.i(TAG, "activity-name=" + activity.getLocalClassName());
/**移除定时任务*/
mOverlayHandler.removeCallbacks(mRunnable);
/**获取当前activity 的windowManager (注意:必须使用activity 实例,防止某些机型无法显示)*/
mWindowManager = activity.getWindowManager();
final View msgLayout = LayoutInflater.from(MyApplication.getMyApplication()).inflate(R.layout.overlay_msg_layout, null, false);
ImageView ivIocn = msgLayout.findViewById(R.id.overlay_msg_icon);
TextView tvTitle = msgLayout.findViewById(R.id.overlay_msg_title);
TextView tvContent = msgLayout.findViewById(R.id.overlay_msg_content);
TextView tvTime = msgLayout.findViewById(R.id.overlay_msg_time);
tvContent.setText(content);
tvTitle.setText(title);
tvTime.setText("现在");
WindowManager.LayoutParams mWindowParams = new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(activity)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //8.0新特性
mWindowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
mWindowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
}
}
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
mWindowParams.windowAnimations = R.style.overlay_msg_style_ainm;
mWindowParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//此方法 测量有误差,这里用于 获取 大概高度
msgLayout.measure(0, 0);
int measuredWidth = msgLayout.getMeasuredWidth();// 获取宽度
int measuredHeight = msgLayout.getMeasuredHeight();// 获取高度
Log.i(TAG, "measuredWidth=" + measuredWidth + ",measuredHeight=" + measuredHeight);
mWindowParams.height = measuredHeight * 2;//设置窗口高度,用于向下拖动效果
// mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;//设置窗口自适应高度
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.gravity = Gravity.TOP;
/**全屏的 activity 设置 边距*/
if ((activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) {
mWindowParams.y = getStatusBarHeight();
}
OverlayMsgRelativeLayout msgRelativeLayout = msgLayout.findViewById(R.id.overlay_rl_layout);
msgRelativeLayout.setOnTouchViewListener(new OverlayMsgRelativeLayout.OnTouchViewListener() {
@Override
public void onViewPress() {
mOverlayHandler.removeCallbacks(mRunnable);
}
@Override
public void onViewBack() {
mOverlayHandler.postDelayed(mRunnable, DELAY_MILLIS);
}
@Override
public void onSlideLeft() {
removeMsg(msgLayout);
}
@Override
public void onSlideTop() {
removeMsg(msgLayout);
}
@Override
public void onSlideRight() {
removeMsg(msgLayout);
}
@Override
public void onSlideBottom() {
removeMsg(msgLayout);
//模拟点击 跳转 另一个界面
activity.startActivity(new Intent(activity, FristActivity.class));
}
@Override
public void onViewClick() {
/** 1.点击消息后移除当前 */
if (msgLayout.getParent() != null) {
Log.i(TAG, "点击消息=");
mOverlayHandler.removeCallbacks(mRunnable);
mWindowManager.removeView(msgLayout);
mStack.remove(msgLayout);
/**如果还有消息则 延时移除*/
if (mStack.size() > 0) {
mOverlayHandler.postDelayed(mRunnable, DELAY_MILLIS);
}
//模拟点击 跳转 另一个界面
activity.startActivity(new Intent(activity, FristActivity.class));
}
/** 2.点击消息后移除所有 */
// if (msgLayout.getParent() != null) {
// /**立即移除 所有消息*/
// mOverlayHandler.post(mRunnable);
// Log.i(TAG, "点击消息=" + msgLayout.getParent().getClass().getName());
// }
}
});
/**应用上层显示权限申请提示框*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(activity)) {
showOverlaySettingDialog(activity);
}
}
/**存入列表*/
mStack.push(msgLayout);
/**添加到窗口*/
mWindowManager.addView(msgLayout, mWindowParams);
/**震动*/
phoneVibrates();
/**播放通知铃声*/
playRing(MyApplication.getMyApplication());
/**开启定时任务*/
mOverlayHandler.postDelayed(mRunnable, DELAY_MILLIS);
}
/**
* 提示 开启 应用上层显示
* @param activity
*/
public static void showOverlaySettingDialog(final Activity activity) {
if ((mOverlaySettingDialog != null && mOverlaySettingDialog.isShowing()) || !isOverlaySettingRemind()) {
return;
}
mOverlaySettingDialog = new Dialog(activity, R.style.overlay_setting_dialog_style);
mOverlaySettingDialog.setCanceledOnTouchOutside(true);
View view = LayoutInflater.from(MyApplication.getMyApplication()).inflate(R.layout.dialog_overlay_setting, null, false);
mOverlaySettingDialog.addContentView(view, new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mOverlaySettingDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mOverlaySettingDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
// 设置宽度为屏宽、靠近屏幕底部。
Window window = mOverlaySettingDialog.getWindow();
WindowManager.LayoutParams wlp = window.getAttributes();
wlp.gravity = Gravity.CENTER;
wlp.width = getScreenWidth(activity) * 8 / 10;
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(wlp);
TextView hintTitle = view.findViewById(R.id.hint_title);
TextView hintContent = view.findViewById(R.id.hint_content);
TextView hintLeftBtn = view.findViewById(R.id.cancel_btn_text);
Button hintRightBtn = view.findViewById(R.id.hint_right_btn);
final CheckBox hintCheckbox = view.findViewById(R.id.hint_checkbox);
hintTitle.setText("应用权限");
hintContent.setText("消息提醒需要您授予以下权限:\n1.显示在其他应用的上层权限\n\n是否前往应用授权页面?");
hintLeftBtn.setText("取消");
hintRightBtn.setText("立即前往");
hintLeftBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hintCheckbox.isChecked()) {
closeOverlaySettingRemind();
}
mOverlaySettingDialog.dismiss();
}
});
hintRightBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hintCheckbox.isChecked()) {
closeOverlaySettingRemind();
}
/**跳转设置开启 应用上层显示*/
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + MyApplication.getMyApplication().getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
}
mOverlaySettingDialog.dismiss();
}
});
/**显示提示框*/
mOverlaySettingDialog.show();
}
private static void removeMsg(View msgLayout) {
if (msgLayout.getParent() != null && mWindowManager != null) {
Log.i(TAG, "消息滑出");
mWindowManager.removeView(msgLayout);
mStack.remove(msgLayout);
}
/**如果还有消息则延时移除*/
if (mStack.size() > 0) {
mOverlayHandler.postDelayed(mRunnable, DELAY_MILLIS);
}
}
private static Runnable mRunnable = new Runnable() {
@Override
public void run() {
while (!mStack.isEmpty()) {
View pop = mStack.pop();
if (pop != null && pop.getParent() != null && mWindowManager != null) {
mWindowManager.removeView(pop);
Log.i(TAG, "stack.size==" + mStack.size());
}
}
Log.i(TAG, "final-stack.size==" + mStack.size());
}
};
/**
* 获取状态栏高度
* @return
*/
private static int getStatusBarHeight() {
int result = 0;
int resourceId = MyApplication.getMyApplication().getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = MyApplication.getMyApplication().getResources().getDimensionPixelSize(resourceId);
}
return result;
}
/**
* 获取屏幕宽度
* @return
*/
private static int getScreenWidth(Activity activity) {
DisplayMetrics dm = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
activity.getWindowManager().getDefaultDisplay().getRealMetrics(dm);
}
Log.i(TAG, "getScreenWidth=" + dm.widthPixels + ",h==" + dm.heightPixels + ",barH==" + getStatusBarHeight());
return dm.widthPixels;
}
/**
* 关闭显示上层应用权限提醒
* @return
*/
public static void closeOverlaySettingRemind() {
SharedPreferences sharedPreferences = MyApplication.getMyApplication().getSharedPreferences("overlay_setting_remind", Activity.MODE_PRIVATE);
sharedPreferences.edit().putBoolean("is_remind", false).apply();
}
/**
* @return 是否 已关闭显示上层应用权限提醒
*/
public static boolean isOverlaySettingRemind() {
SharedPreferences sharedPreferences = MyApplication.getMyApplication().getSharedPreferences("overlay_setting_remind", Activity.MODE_PRIVATE);
return sharedPreferences.getBoolean("is_remind", true);
}
/**
* 手机震动
*/
private static void phoneVibrates() {
Vibrator vib = (Vibrator) MyApplication.getMyApplication().getSystemService(Service.VIBRATOR_SERVICE);
vib.vibrate(new long[]{150, 250, 150, 250}, -1);
}
/**
* 播放铃声
*/
public static void playRing(Context context) {
try {
//用于获取手机 默认提示音(RingtoneManager.TYPE_NOTIFICATION) 的Uri
Uri ringUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
MediaPlayer mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(context, ringUri);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
mMediaPlayer.setLooping(false);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上为核心代码,简单实现了 类似 微信的 顶部消息 展示
完整项目:https://download.csdn.net/download/qq_29364417/15015386