自定义全局通知WindowToast

自定义全局通知WindowToast

通过Window的方式来显示的。将WindowManager.LayoutParams的属性通过状态模式封装,可以降低耦合,根据需求变化,通过WindowToast.makeWindowToast()方法重载,可以通过自定义的布局制定样式。

WindowToast是采用单例模式设计,有好有坏。采用链式编程的形式,易于使用。

效果图(在模拟器上截的图,和真机有差距)

这里写图片描述

WindowToast.class

public class WindowToast {

    private static WindowToast result;
    public final Context mContext;
    private static View sView;

    public WindowManager mWManager;
    public WindowManager.LayoutParams mParams;
    private final Handler mHandler = new Handler();
    private final Runnable mShow = new Runnable() {
        @Override
        public void run() {
            handleShow();
        }
    };

    private final Runnable mHide = new Runnable() {
        @Override
        public void run() {
            handleHide();
        }
    };
    /**
     * @by zhiqiang 2016/7/5 显示的时长
     */
    public static final int SHORT_TIME = 1500;
    public static final int LONG_TIME = 3000;

    private static State state;

    private static SparseArray<View> sparseArray = new SparseArray<>();

    private WindowToast(Context context) {
        mContext = context;
        mWManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mParams = new WindowManager.LayoutParams();
        state = new NotifyState();
        setState(state);
    }

    public static WindowToast getInstance(Context context) {
        if (result == null) {
            synchronized (WindowToast.class) {
                if (result == null) {
                    result = new WindowToast(context);
                }
            }
        }
        return result;
    }

    /**
     * @by zhiqiang 2016/7/4 获取windowToast对象
     */
    public static WindowToast makeWindowToast(Context context) {
        context = context.getApplicationContext();
        result = getInstance(context);
        if (sView == null) {
            sView = LayoutInflater.from(context).inflate(R.layout.window_toast, null);
        }
        return result;
    }

    public static WindowToast makeWindowToast(Context context, @LayoutRes int layout) {
        context = context.getApplicationContext();
        result = getInstance(context);
        if (sView == null) {
            sView = LayoutInflater.from(context).inflate(layout, null);
        }
        return result;
    }

    public static WindowToast makeWindowToast(Context context, @NonNull View view) {
        context = context.getApplicationContext();
        result = getInstance(context);
        if (sView == null) {
            sView = view;
        }
        return result;
    }

    public WindowToast setState(State state) {
        mParams = state.getParams();
        return result;
    }

    public void show() {
        mHandler.post(mShow);
    }

    public void show(int duration) {
        show();
        mHandler.removeCallbacks(mHide);
        mHandler.postDelayed(mHide, duration);
    }

    public void cancle() {
        mHandler.post(mHide);
    }

    private void handleShow() {
        if (sView != null) {
            if (sView.getParent() == null) {
                mWManager.addView(sView, mParams);
            }
        }
    }


    private void handleHide() {
        if (sView != null) {
            if (sView.getParent() != null) {
                sparseArray.clear();
                mWManager.removeView(sView);
            }
            sView = null;
        }
    }

    /**
     * @by zhiqiang 2016/7/4 通过id获取子控件
     */

    public <T extends View> T getChildView(@IdRes int id) {
        if (sView == null) return null;
        View view = sparseArray.get(id);
        if (view == null) {
            view = sView.findViewById(id);
            sparseArray.put(id, view);
        }
        return (T) view;
    }

    public WindowToast setPadding(int left, int top, int right, int bottom) {
        View view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setPadding(left, top, right, bottom);
        }
        return result;
    }

    /**
     * @by zhiqiang 2016/7/4 给相应的子控件设置属性
     */
    public WindowToast setVisiable(int visibility) {
        View view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setVisibility(visibility);
        }
        return result;
    }

    public WindowToast setVisiable(@IdRes int id, int visibility) {
        View view = getChildView(id);
        if (view != null) {
            view.setVisibility(visibility);
        }
        return result;
    }

    public WindowToast setBackgroundColor(@IdRes int id, @ColorInt int color) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackgroundColor(color);
        }
        return result;
    }

    public WindowToast setBackgroundResource(@IdRes int id, @DrawableRes int resId) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackgroundResource(resId);
        }
        return result;
    }

    public WindowToast setBackground(@IdRes int id, @ColorInt Drawable drawable) {
        View view = getChildView(id);
        if (view != null) {
            view.setBackground(drawable);
        }
        return result;
    }

    public WindowToast setText(@NonNull CharSequence charSequence) {
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setText(charSequence);
        }
        return result;
    }

    public WindowToast setText(@StringRes int string) {
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setText(mContext.getString(string));
        }
        return result;
    }

    public WindowToast setText(@IdRes int id, @NonNull CharSequence charSequence) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setText(charSequence);
        }
        return result;
    }

    public WindowToast setText(@IdRes int id, @StringRes int string) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setText(mContext.getString(string));
        }
        return result;
    }

    public WindowToast setTextColor(@ColorInt int color) {
        TextView view = getChildView(R.id.window_toast_tv);
        if (view != null) {
            view.setTextColor(color);
        }
        return result;
    }

    public WindowToast setTextColor(@IdRes int id, @ColorInt int color) {
        TextView view = getChildView(id);
        if (view != null) {
            view.setTextColor(color);
        }
        return result;
    }

    public WindowToast setImageResource(@IdRes int id, @DrawableRes int resId) {
        ImageView view = getChildView(id);
        if (view != null) {
            view.setImageResource(resId);
        }
        return result;
    }

    public WindowToast setImageBitmap(@IdRes int id, Bitmap bitmap) {
        ImageView view = getChildView(id);
        if (view != null) {
            view.setImageBitmap(bitmap);
        }
        return result;
    }

    /**还可以设置一些监听事件 -----------------------*/
}

window_toast.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/window"
    android:orientation="vertical"
    tools:context="www.weshared.test2.MainActivity">

<!--android:paddingTop="25dp"   因为StatueBar的高度大概是25dp-->
    <TextView
        android:paddingTop="25dp"
        android:id="@+id/window_toast_tv"
        android:layout_width="match_parent"
        android:layout_height="81dp"
        android:layout_gravity="center"
        android:gravity="center" />
</LinearLayout>

State.class接口

public interface State {
    WindowManager.LayoutParams getParams();
}

NotifyState.class

public class NotifyState implements State {

    @Override
    public WindowManager.LayoutParams getParams() {

        WindowManager.LayoutParams params = new WindowManager.LayoutParams();

        params.alpha = 1.0f;
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;//FLAG_LAYOUT_NO_LIMITS 不限制超出屏幕外
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.format = PixelFormat.RGBA_8888;
        params.gravity = Gravity.START | Gravity.TOP;
        params.x = 0;
        params.y = -StatuebarUtils.getStatusBarHeight();
        params.windowAnimations = R.style.windowAnimation;

        return params;
    }
}

StatuebarUtils.class

public class StatuebarUtils {

    /*获取状态栏的高度**/
    public static int getStatusBarHeight() {
        int height = 0;
        int resId = APP.getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            height = APP.getContext().getResources().getDimensionPixelSize(resId);
        }
        return height;
    }
}

MainActivity.class

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button show;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show = (Button) findViewById(R.id.show);

        show.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.show:
                WindowToast.makeWindowToast(this).setText("欢迎欢迎").setTextColor(getResources().getColor(R.color.colorPrimary)).show(2000);
                break;
        }
    }
}

权限

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值