自定义全局通知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"/>