android 仿微信顶部消息 展示

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值