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;@Overridepublic 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() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {Log.i(TAG, "tx=" + getTranslationX() + ",ty=" + getTranslationY());if (onTouchViewListener != null) {onTouchViewListener.onViewBack();}}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic 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() {@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {setVisibility(INVISIBLE);if (onTouchViewListener != null) {onTouchViewListener.onSlideTop();}}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationPause(Animator animation) {}@Overridepublic 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() {@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {setVisibility(INVISIBLE);if (onTouchViewListener != null) {onTouchViewListener.onSlideBottom();}}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationPause(Animator animation) {}@Overridepublic 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() {@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {setVisibility(INVISIBLE);if (onTouchViewListener != null) {onTouchViewListener.onSlideLeft();}}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationPause(Animator animation) {}@Overridepublic 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() {@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {setVisibility(INVISIBLE);if (onTouchViewListener != null) {onTouchViewListener.onSlideRight();}}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationPause(Animator animation) {}@Overridepublic 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() {@Overridepublic void onViewPress() {mOverlayHandler.removeCallbacks(mReplaceRunnable);}@Overridepublic void onViewBack() {mOverlayHandler.postDelayed(mReplaceRunnable, DELAY_MILLIS);}@Overridepublic void onSlideLeft() {if (mMsgLayout.getParent() != null) {Log.i(TAG,  "左边移除消息");mOverlayHandler.removeCallbacks(mReplaceRunnable);mWindowManager.removeView(mMsgLayout);}}@Overridepublic void onSlideTop() {if (mMsgLayout.getParent() != null) {Log.i(TAG,  "顶部边移除消息");mOverlayHandler.removeCallbacks(mReplaceRunnable);mWindowManager.removeView(mMsgLayout);}}@Overridepublic void onSlideRight() {if (mMsgLayout.getParent() != null) {Log.i(TAG,  "右边移除消息");mOverlayHandler.removeCallbacks(mReplaceRunnable);mWindowManager.removeView(mMsgLayout);}}@Overridepublic void onSlideBottom() {if (mMsgLayout.getParent() != null) {Log.i(TAG,  "右边移除消息");mOverlayHandler.removeCallbacks(mReplaceRunnable);mWindowManager.removeView(mMsgLayout);}//模拟跳转界面activity.startActivity(new Intent(activity,FristActivity.class));}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onViewPress() {mOverlayHandler.removeCallbacks(mRunnable);}@Overridepublic void onViewBack() {mOverlayHandler.postDelayed(mRunnable, DELAY_MILLIS);}@Overridepublic void onSlideLeft() {removeMsg(msgLayout);}@Overridepublic void onSlideTop() {removeMsg(msgLayout);}@Overridepublic void onSlideRight() {removeMsg(msgLayout);}@Overridepublic void onSlideBottom() {removeMsg(msgLayout);//模拟点击 跳转 另一个界面activity.startActivity(new Intent(activity, FristActivity.class));}@Overridepublic 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() {@Overridepublic void onClick(View v) {if (hintCheckbox.isChecked()) {closeOverlaySettingRemind();}mOverlaySettingDialog.dismiss();}});hintRightBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic 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() {@Overridepublic 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) 的UriUri 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

android 仿微信顶部消息 展示相关推荐

  1. android放微信@功能,Android仿微信语音消息的录制和播放功能

    一.简述 效果: 实现功能: 长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音: 监听手指动作,规定区域.录音状态下手指划出规定区域取消录音,删 ...

  2. android接收消息后提示音,Android仿微信新消息提示音

    怕有些人不知道怎么进入微信的新消息提示音功能,我这里说下操作步骤: 打开微信----我---设置---新消息提醒---新消息提示音. 经过以上的步骤就进入了这样的界面 具体实现的步骤. 难点之一:获取 ...

  3. android微信加人有提示音吗,Android仿微信新消息提示音

    環信聊天消息提示音的實現 仿微信新消息提示音設置. 思路:用RingtoneManager查詢出title,Ringtone,uri信息,title用來展示,Ringtone用來播放,uri設置提示音 ...

  4. android新消息提醒功能,Android仿微信新消息提示音

    怕有些人不知道怎么进入微信的新消息提示音功能,我这里说下操作步骤: 打开微信----我---设置---新消息提醒---新消息提示音. 经过以上的步骤就进入了这样的界面 具体实现的步骤. 难点之一:获取 ...

  5. android 仿微信聊天界面 以及语音录制功能,Android仿微信录制语音功能

    本文实例为大家分享了Android仿微信录制语音的具体代码,供大家参考,具体内容如下 前言 我把录音分成了两部分 1.UI界面,弹窗读秒 2.一个类(包含开始.停止.创建文件名功能) 第一部分 由于6 ...

  6. android 仿微信demo————微信消息界面实现(移动端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  7. android 仿微信demo————微信消息界面实现(服务端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  8. android 仿微信demo————微信顶部操作栏界面实现

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  9. android 仿微信demo————微信顶部操作栏加号按钮实现(弹出子菜单)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

最新文章

  1. PHP常用正则表达式汇总 [复制链接]
  2. 朱俊彦团队提出GAN压缩算法:计算量减少20倍,生成效果不变,GPU、CPU统统能加速...
  3. 2005年存储市场关键词TOP10
  4. 最长递增子序列的个数Python解法
  5. c语言中sizeof是一个标准库函数,对C语言中的sizeof的介绍分析
  6. HTML DOM Image 对象
  7. Manjaro安装Nvidia显卡驱动失败或者启动黑屏卡死的原因以及Nvidia Prime与Intel核显切换方法
  8. tfidf处理代码_tfidf代码简单实现
  9. 简单易用的C/C++ 图像库 stb_image stb_image_write
  10. Python爬虫英语四六级网站查询准考证号
  11. 视频转文字怎么操作?快把这些方法收好
  12. html指定区域的背景颜色,JS实现点击颜色块切换指定区域背景颜色的方法
  13. pdf文件过大如何缩小上传
  14. spring事物 设计模式_是什么使事物变得美丽,以及如何在设计中使用它
  15. java字符串长度(java字符串长度压缩)
  16. 问卷调查 批量模拟真人填写 爬虫 实战
  17. redis可以代替mysql 吗_redis是否可以代替mysql
  18. html中的xmlns是什么意思?
  19. 剑指offer46. 把数字翻译成字符串
  20. 【专题学习】Contiguity(进行中)

热门文章

  1. 网站作为互联网产品如何平衡艺术与商业,网站设计需要掌握哪些思维?
  2. 计算机网络学习笔记(一)——什么是Internet
  3. 服务器系统磁盘分区,服务器磁盘分区教程
  4. MacFamilyTree 8.3.6 Mac 破解版 Mac上最强大的家谱制作软件
  5. RapidScada免费开源Scada组态软件系列教程4-各模块详细介绍
  6. 前端图片处理 - Photoshop压缩照片 / collagelt轻松拼接照片墙
  7. MySQL基础教程系列-约束(三)唯一约束
  8. matlab cnn 局部最大值,Matlab实现CNN(一)
  9. 补 2019.11.11-2019.11.17 arts:
  10. meizz (梅花雨)的一些珍藏代码奉献