Toast的悬浮窗使用

    xiaoxiao2021-03-25  94

    Toast的使用

    **Toast的使用大家都不陌生,通常情况下,我们不会在Toast上进行过于复杂的操作,只是通知用户一些消息。 今天我使用Toast来进行需要的悬浮窗改造,同时,添加用户点击事件的响应。**

    首先预览一下整体效果:

    两种悬浮窗都有响应点击事件 ,点击”X”后悬浮窗会消失。


    话不多说,代码走起~~

    <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingRight="15dp"> <RelativeLayout android:id="@+id/emui_window_big_info" android:layout_width="324dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="#fff" android:visibility="visible"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/linearLayout"> <RelativeLayout android:layout_width="324dp" android:background="#008cff" android:layout_height="wrap_content"> <TextView android:id="@+id/guide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:paddingTop="21dp" android:paddingLeft="11dp" android:textSize="15sp" android:text="悬浮窗标题1"/> <TextView android:id="@+id/guide2" android:layout_below="@id/guide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:paddingLeft="12dp" android:paddingBottom="17dp" android:textSize="15sp" android:text="悬浮窗标题2"/> <LinearLayout android:id="@+id/emui_window_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="1dp" android:layout_alignParentRight="true"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@mipmap/close"/> </LinearLayout> </RelativeLayout> <View android:layout_width="307dp" android:layout_height="1dp" android:layout_marginRight="9dp" android:layout_marginLeft="9dp" android:background="#e5e5e5"/> <RelativeLayout android:layout_width="324dp" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="43dp" android:textColor="#333333" android:gravity="center_vertical" android:paddingLeft="12dp" android:textSize="14sp" android:text="文字1"/> </RelativeLayout> <View android:layout_width="307dp" android:layout_height="1dp" android:layout_marginRight="9dp" android:layout_marginLeft="9dp" android:background="#e5e5e5"/> <RelativeLayout android:layout_width="324dp" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="43dp" android:textColor="#333333" android:gravity="center_vertical" android:paddingLeft="12dp" android:textSize="14sp" android:text="文字2"/> </RelativeLayout> <View android:layout_width="307dp" android:layout_height="1dp" android:layout_marginRight="9dp" android:layout_marginLeft="9dp" android:background="#e5e5e5"/> <RelativeLayout android:layout_width="324dp" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="43dp" android:textColor="#333333" android:gravity="center_vertical" android:paddingLeft="12dp" android:textSize="14sp" android:text="文字3"/> </RelativeLayout> </LinearLayout> </RelativeLayout> </FrameLayout>

    1.使用系统地Toast去完成悬浮窗时,使用WindowManager并指定当前悬浮窗的类型为TYPE_TOAST,同时根据需要指定gravity,flags,type.

    show()的时候,调用 mWindowManager.addView(mView, mLayoutParams)即可。

    remove()的时候,调用 mWindowManager.removeView(mView);即可。

    package com.example.sunqi.mytoast; import android.content.Context; import android.graphics.PixelFormat; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.TextView; /** * Created by sunqi on 2017/3/10. */ public class SystemToastWindow implements View.OnClickListener{ //系统Toast悬浮窗 protected WindowManager mWindowManager; protected WindowManager.LayoutParams mLayoutParams; protected Context mContext; protected View mView; protected boolean mIsShow = false; private int mCurWindowType = WindowManager.LayoutParams.TYPE_TOAST; // private int mCurWindowType = WindowManager.LayoutParams.TYPE_PHONE; private void initView() { View rootView = LayoutInflater.from(mContext).inflate(R.layout.system_float_window_layout,null); mView = rootView; ((TextView)mView.findViewById(R.id.guide)).setText("系统Toast悬浮窗"); mView.findViewById(R.id.emui_window_close).setOnClickListener(this); } public SystemToastWindow(Context context) { mContext = context; } private void init(Context context) { mLayoutParams = new WindowManager.LayoutParams(); mLayoutParams.format = PixelFormat.RGBA_8888; mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; mLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; mLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mLayoutParams.type = mCurWindowType; initView(); } public void remove() { if (mWindowManager != null) { try { if (null != mView) { mWindowManager.removeView(mView); mView = null; } mIsShow = false; } catch (Exception e) { e.printStackTrace(); } } } public void show() { init(mContext); if (null != mWindowManager && null != mView) { try { mWindowManager.addView(mView, mLayoutParams); mIsShow = true; } catch (WindowManager.BadTokenException e) { } catch (Exception e) { } } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.emui_window_close: remove(); break; } } public boolean isShow() { return mIsShow; } }

    2.使用反射的Toast去完成悬浮窗时,自定义一个FloatToastManager,同时根据需要指定gravity,flags,type.自定义FloatToastWindow

    package com.example.sunqi.mytoast; import android.content.Context; import android.graphics.PixelFormat; import android.icu.text.DateFormat; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import android.widget.Toast; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; /** * 反射Toast控制显示的位置,时间,动画,View * Created by sunqi on 2017/2/27. */ public class FloatToastManager { //反射Toast的使用类 private Context mContext; private Field mParamsField; private WindowManager.LayoutParams mParams; private Toast mToast; private Object mTN; private Method mShowMethod; private Method mHideMethod; private boolean isShow = false; private int mGravity = Gravity.CENTER; private int mXOffset = 0; private int mYOffset = 0; private int mHeight = WindowManager.LayoutParams.MATCH_PARENT; private int mWidth = WindowManager.LayoutParams.MATCH_PARENT; private boolean misInited = false; private View mView; public FloatToastManager(Context context){ mContext = context; mToast = new Toast(mContext); } public void setGravity(int gravity,int xOffset,int yOffset){ mGravity = gravity; mXOffset = xOffset; mYOffset = yOffset; } public void setSize(int height,int width){ mHeight = height; mWidth = width; } private void initVar(){ if (misInited){ return; } try { Field tnField =mToast.getClass().getDeclaredField("mTN"); tnField.setAccessible(true); mToast.setGravity(mGravity,mXOffset,mYOffset); mTN = tnField.get(mToast); mShowMethod = mTN.getClass().getMethod("show"); mHideMethod = mTN.getClass().getMethod("hide"); mParamsField = mTN.getClass().getDeclaredField("mParams"); mParamsField.setAccessible(true); mParams = (WindowManager.LayoutParams) mParamsField.get(mTN); mParams.height = mHeight; mParams.width = mWidth; mParams.format = PixelFormat.RGBA_8888; mParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; } catch (Exception e) { e.printStackTrace(); } } public void showViewOther(View view){ initVar(); if (isShow) return; mToast.setView(view); try { /**调用tn.mShowMethod()之前一定要先设置mNextView*/ Field tnNextViewField = mTN.getClass().getDeclaredField("mNextView"); tnNextViewField.setAccessible(true); tnNextViewField.set(mTN,mToast.getView()); mShowMethod.invoke(mTN); isShow = true; mView = view; }catch (Exception e){ e.printStackTrace(); } } public void hideView() { if (!isShow) return; try { if (null != mView) { // 解决消失时渐隐动画导致的闪烁问题 mView.setVisibility(View.INVISIBLE); mView.postDelayed(new Runnable() { @Override public void run() { if (null != mView) { mView.setVisibility(View.VISIBLE); mView = null; } } }, 100); } mHideMethod.invoke(mTN); //mToast.cancel(); isShow = false; Log.i("FloatToastManager", "hideView called"); } catch (Exception e) { e.printStackTrace(); Log.i("FloatToastManager", "hideView exception " + e.getMessage()); } } }
    package com.example.sunqi.mytoast; import android.content.Context; import android.graphics.PixelFormat; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.TextView; /** * Created by sunqi on 2017/3/10. */ public class FloatToastWindow implements View.OnClickListener{ //使用反射Toast的悬浮窗 protected FloatToastManager mfloatToastManager; protected Context mContext; protected View mView; protected boolean mIsShow = false; private void initView() { View rootView = LayoutInflater.from(mContext).inflate(R.layout.system_float_window_layout,null); mView = rootView; ((TextView)mView.findViewById(R.id.guide)).setText("反射使用Toast悬浮窗"); mView.findViewById(R.id.emui_window_close).setOnClickListener(this); } public FloatToastWindow(Context context) { mContext = context; } private void init(Context context) { mfloatToastManager = new FloatToastManager(mContext); initView(); } public void remove() { if (mfloatToastManager != null) { try { if (null != mView) { mfloatToastManager.hideView(); mView = null; } mIsShow = false; } catch (Exception e) { e.printStackTrace(); } } } public void show() { init(mContext); if (null != mfloatToastManager && null != mView) { try { mfloatToastManager.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL , 0 , 0 ); mfloatToastManager.setSize(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT); mfloatToastManager.showViewOther(mView); mIsShow = true; } catch (Exception e) { } } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.emui_window_close: remove(); break; } } public boolean isShow() { return mIsShow; } }

    3.具体地Window调用:

    package com.example.sunqi.mytoast; import android.app.Activity; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { private SystemToastWindow systemToastWindow; private FloatToastWindow floatToastWindow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); systemToastWindow = new SystemToastWindow(this); systemToastWindow.show(); floatToastWindow = new FloatToastWindow(this); floatToastWindow.show(); } @Override protected void onDestroy() { super.onDestroy(); } @Override public void onBackPressed() { super.onBackPressed(); if (systemToastWindow != null && systemToastWindow.isShow()){ systemToastWindow.remove(); } if (floatToastWindow != null && floatToastWindow.isShow()){ floatToastWindow.remove(); } } }

    详细代码可以参考我的具体代码项目:MyToast代码

    转载请注明原文地址: https://ju.6miu.com/read-39647.html

    最新回复(0)