自定义吐司

  Window表示一个窗口的概念,在日常开发中直接接触Window的机会并不多,但是在某些特殊的时候我们需要在桌面上显示一个类似悬浮窗的东西,那么这种效果就需要用到window来实现。Window是一个抽象类,它的具体实现是PhoneWindow。创建一个window是一个很简单的事,只需要通过WindowManager即可完成。WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC过程。Android中所有的视图都是通过Window来呈现的,不管是Activity、Dialog还是Toast,他们的视图实际上都是附加在Window上的,因此Window实际是View的直接管理者。单击事件由Window传递给DecorView,然后再由DecorView传递给我们的View,就连Activity的设置视图的方法setContentView在底层也是通过Window来完成的.
  
自定义吐司类 NewToast.java


public class NewToast implements View.OnTouchListener {
    private Context                    mContext;
    // 用来往顶层布局加或删视图
    private WindowManager              mWm;
    // 吐司展示的布局
    private View                       mView;
    // 布局参数对象
    private WindowManager.LayoutParams mParams;

    public NewToast(Context context) {
        super();
        this.mContext = context;

        mWm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        mParams = new WindowManager.LayoutParams();
        // layout_width
        mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        // layout_height
        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        // gravity
        mParams.gravity = Gravity.LEFT | Gravity.TOP;
        // 背景透明
        mParams.format = PixelFormat.TRANSPARENT;//
        // 坐标
        mParams.x = 100;
        mParams.y = 100;
        // 类型
        mParams.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
        // 特殊属性
        mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 屏幕高亮
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 不支持点击
        // |WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;//不支持拖动
    }

    /***
     * 方法
     *
     * @param msg
     */
    public void show(String msg) {
        dismiss();
        mView = View.inflate(mContext, R.layout.view_toast, null);
        mView.setBackgroundResource(R.drawable.shape_address_toast_normal);
        mView.setOnTouchListener(this);

        // 处理拖动事件OnTouchListener 例:公交车上的xx事件
        TextView tvTitle = (TextView) mView.findViewById(R.id.view_toast_tv_title);
        tvTitle.setText(msg);
        mWm.addView(mView, mParams);// 1.布局 2.布局参数对象
        long delayMillis = 3000;// 延时发消息
        Runnable r = new Runnable() {
            @Override
            public void run() {
                dismiss();
            }
        };
        // 设置5000自动消失
        new Handler().postDelayed(r, delayMillis);
    }

    /***
     * 方法
     *
     */
    public void dismiss() {
        if (mView != null) {
            mWm.removeView(mView);
            mView = null;
        }
    }

    /***
     * 方法 MotionEvent事件的参数 x,y 与操作状态action
     * mParams.type=WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
     *
     * 还要求权限<!-- 添加窗口优先级的权限 -->
     * <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
     * //特殊属性 mParams.flags=WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON//屏幕高亮
     * |WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//不支持点击
     * //|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;//不支持拖动
     *
     * @param v
     * @param event
     * @return
     */
    private int mStartX;
    private int mStartY;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            // e1
            mStartX = (int) event.getRawX();
            mStartY = (int) event.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:
            // e2
            int newX = (int) event.getRawX();
            int newY = (int) event.getRawY();

            // off
            int offX = newX - mStartX;
            int offY = newY - mStartY;

            // 更新控件
            mParams.x = mParams.x + offX;
            mParams.y = mParams.y + offY;

            int xMin=0;
            int yMin=0;
            //获取显示对象  可以获取屏幕的参数 宽高 屏幕密度
            Display display=mWm.getDefaultDisplay();
            int xMax=display.getWidth()-mView.getWidth();
            int yMax=display.getHeight()-mView.getHeight();
            if (mParams.x <= xMin) {
                mParams.x = xMin;
            }
            if (mParams.x >= xMax) {
                mParams.x = xMax;
            }
            if (mParams.y <= yMin) {
                mParams.y = yMin;
            }
            if (mParams.y >= yMax) {
                mParams.y = yMax;
            }
            System.out.println("    mParams.x "+    mParams.x+" mParams.y"+ mParams.y);

            // 控件刷新 因为params.x params.y
            mWm.updateViewLayout(mView, mParams);// 1当前布局 2.更新后LayoutParams

            // 更新e1的位置
            mStartX = (int) event.getRawX();
            mStartY = (int) event.getRawY();
            break;
        case MotionEvent.ACTION_UP:
            break;
        }
        return true;// 需要自己处理并消费这个整件
    }
}

布局文件view_toast.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="8dp" >
    <TextView
        android:drawableLeft="@drawable/location"
        android:id="@+id/view_toast_tv_title"
        android:layout_width="wrap_content"
        android:gravity="left|center_vertical"
        android:layout_centerInParent="true"
        android:drawablePadding="5dp"
        android:layout_height="wrap_content"
        android:text="归属地:"
        android:textColor="#FFFFFF" />
</RelativeLayout>

自定义吐司背景 shape_address_toast_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- 填充色 -->
    <solid android:color="#ADAAAD" />
    <!-- 圆角 -->
    <corners android:radius="5dp" />
    <!-- 内边距 -->
    <padding android:left="8dp"
        android:top="8dp"
        android:right="8dp"
        android:bottom="8dp"/>
    <!-- 最小的宽高 -->
    <size android:width="20dp"
        android:height="20dp"/>

</shape>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值