Toast的悬浮窗使用

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代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值