安卓_手机卫士_第六天(来电监听,自定义悬浮toast,窗体触摸移动,双击居中多击事件 )

来电监听


业务需求:来电监听手机号,查询归属地,悬浮展示归属地查询结果

这里写图片描述

悬浮在手机上(悬浮框不停留在手机卫士应用(界面)中,所以需要去开启一个服务,在服务中去管理toast代码逻辑)
1. 点击是否开启归属地显示的自定义组合控件SettingItemView
开启:开启服务,服务中管理吐司的显示,关闭:关闭服务,不需要显示吐司
2. 只有在来电的时候(响铃状态)显示吐司,挂断电话的时候,吐司移除掉
3. 电话状态的监听
服务开启的时候,需要去做监听
mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mPhoneStateListener = new MyPhoneStateListener();
mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

关闭的时候电话状态就不需要监听

if(mTM!=null && mPhoneStateListener!=null){
mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
}

4. 是否开启来电归属地显示的判断条件
服务正在运行==来电归属地开启
服务关闭==来电归属地关闭

activity代码
PS:彻底关掉状态监听要在服务的onDestroy()方法中设置PhoneStateListener.LISTEN_NONE

    /**
     * 是否显示电话号码归属地的方法
     */
    private void initAddress() {
        final SettingItemView siv_address = (SettingItemView) findViewById(R.id.siv_address);
        //对服务是否开的状态做显示
        boolean isRunning = ServiceUtil.isRunning(this, "com.itheima.mobilesafe74.service.AddressService");
        siv_address.setCheck(isRunning);

        //点击过程中,状态(是否开启电话号码归属地)的切换过程
        siv_address.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //返回点击前的选中状态
                boolean isCheck = siv_address.isCheck();
                siv_address.setCheck(!isCheck);
                if(!isCheck){
                    //开启服务,管理吐司
                    startService(new Intent(getApplicationContext(),AddressService.class));
                }else{
                    //关闭服务,不需要显示吐司
                    stopService(new Intent(getApplicationContext(),AddressService.class));
                }
            }
        });
    }

服务代码

public class AddressService extends Service {
    public static final String tag = "AddressService";
    private TelephonyManager mTM;
    private MyPhoneStateListener mPhoneStateListener;
    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
    private View mViewToast;
    private WindowManager mWM;
    private String mAddress;
    private TextView tv_toast;
    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            tv_toast.setText(mAddress);
        };
    };
    private int[] mDrawableIds;

    @Override
    public void onCreate() {
        //第一次开启服务以后,就需要去管理吐司的显示
        //电话状态的监听(服务开启的时候,需要去做监听,关闭的时候电话状态就不需要监听)
        //1,电话管理者对象
        mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        //2,监听电话状态
        mPhoneStateListener = new MyPhoneStateListener();
        mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
        //获取窗体对象
        mWM = (WindowManager) getSystemService(WINDOW_SERVICE);

        super.onCreate();
    }

    class MyPhoneStateListener extends PhoneStateListener{
        //3,手动重写,电话状态发生改变会触发的方法
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                //空闲状态,没有任何活动(移除吐司)
                Log.i(tag, "挂断电话,空闲了.......................");
                //挂断电话的时候窗体需要移除吐司
                if(mWM!=null && mViewToast!=null){
                    mWM.removeView(mViewToast);
                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //摘机状态,至少有个电话活动。该活动或是拨打(dialing)或是通话
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                //响铃(展示吐司)
                Log.i(tag, "响铃了.......................");
                showToast(incomingNumber);
                break;
            }
            super.onCallStateChanged(state, incomingNumber);
        }
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    public void showToast(String incomingNumber) {
        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE   默认能够被触摸
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        params.format = PixelFormat.TRANSLUCENT;
        //在响铃的时候显示吐司,和电话类型一致
        params.type = WindowManager.LayoutParams.TYPE_PHONE;
        params.setTitle("Toast");

        //指定吐司的所在位置(将吐司指定在左上角)
        params.gravity = Gravity.LEFT+Gravity.TOP;

        //吐司显示效果(吐司布局文件),xml-->view(吐司),将吐司挂在到windowManager窗体上
        mViewToast = View.inflate(this, R.layout.toast_view, null);
        tv_toast = (TextView) mViewToast.findViewById(R.id.tv_toast);

        //从sp中获取色值文字的索引,匹配图片,用作展示
        mDrawableIds = new int[]{
                R.drawable.call_locate_white,
                R.drawable.call_locate_orange,
                R.drawable.call_locate_blue,
                R.drawable.call_locate_gray,
                R.drawable.call_locate_green};
        int toastStyleIndex = SpUtil.getInt(getApplicationContext(), ConstantValue.TOAST_STYLE, 0);
        tv_toast.setBackgroundResource(mDrawableIds[toastStyleIndex]);

        //在窗体上挂在一个view(权限)
        mWM.addView(mViewToast, params);

        //获取到了来电号码以后,需要做来电号码查询
        query(incomingNumber);
    }

    private void query(final String incomingNumber) {
        new Thread(){
            public void run() {
                mAddress = AddressDao.getAddress(incomingNumber);
                mHandler.sendEmptyMessage(0);
            };
        }.start();
    }

    @Override
    public void onDestroy() {
        //取消对电话状态的监听(开启服务的时候监听电话的对象)
        if(mTM!=null && mPhoneStateListener!=null){
            mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
        }
        super.onDestroy();
    }
}

自定义悬浮toast


查询源码,模拟源码来实现

代码

    public void showToast(String incomingNumber) {
        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE   默认能够被触摸
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        params.format = PixelFormat.TRANSLUCENT;
        //在响铃的时候显示吐司,和电话类型一致
        params.type = WindowManager.LayoutParams.TYPE_PHONE;
        params.setTitle("Toast");

        //指定吐司的所在位置(将吐司指定在左上角)
        params.gravity = Gravity.LEFT+Gravity.TOP;

        //吐司显示效果(吐司布局文件),xml-->view(吐司),将吐司挂在到windowManager窗体上
        mViewToast = View.inflate(this, R.layout.toast_view, null);
        tv_toast = (TextView) mViewToast.findViewById(R.id.tv_toast);

        //从sp中获取色值文字的索引,匹配图片,用作展示
        mDrawableIds = new int[]{
                R.drawable.call_locate_white,
                R.drawable.call_locate_orange,
                R.drawable.call_locate_blue,
                R.drawable.call_locate_gray,
                R.drawable.call_locate_green};
        int toastStyleIndex = SpUtil.getInt(getApplicationContext(), ConstantValue.TOAST_STYLE, 0);
        tv_toast.setBackgroundResource(mDrawableIds[toastStyleIndex]);

        //在窗体上挂在一个view(权限)
        mWM.addView(mViewToast, params);

        //获取到了来电号码以后,需要做来电号码查询
        query(incomingNumber);
    }

    private void query(final String incomingNumber) {
        new Thread(){
            public void run() {
                mAddress = AddressDao.getAddress(incomingNumber);
                mHandler.sendEmptyMessage(0);
            };
        }.start();
    }

toast样式单选对话框

效果图
这里写图片描述
代码

    private void initToastStyle() {
         scv_toast_style = (SettingClickView) findViewById(R.id.scv_toast_style);
         //话述(产品)
         scv_toast_style.setTitle("设置归属地显示风格");
         //1,创建描述文字所在的string类型数组
         mToastStyleDes = new String[]{"透明","橙色","蓝色","灰色","绿色"};
         //2,SP获取吐司显示样式的索引值(int),用于获取描述文字

         mToastStyle = SpUtil.getInt(this, ConstantValue.TOAST_STYLE, 0);

         //3,通过索引,获取字符串数组中的文字,显示给描述内容控件
         scv_toast_style.setDes(mToastStyleDes[mToastStyle]);
         //4,监听点击事件,弹出对话框
         scv_toast_style.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //5,显示吐司样式的对话框
                showToastStyleDialog();
            }
        });
    }

    /**
     * 创建选中显示样式的对话框
     */
    protected void showToastStyleDialog() {
        Builder builder = new AlertDialog.Builder(this);
        builder.setIcon(R.drawable.ic_launcher);
        builder.setTitle("请选择归属地样式");
        //选择单个条目事件监听
        /*
         * 1:string类型的数组描述颜色文字数组
         * 2:弹出对画框的时候的选中条目索引值
         * 3:点击某一个条目后触发的点击事件
         * */
        builder.setSingleChoiceItems(mToastStyleDes, mToastStyle, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {//which选中的索引值
                //(1,记录选中的索引值,2,关闭对话框,3,显示选中色值文字)
                SpUtil.putInt(getApplicationContext(), ConstantValue.TOAST_STYLE, which);
                dialog.dismiss();
                scv_toast_style.setDes(mToastStyleDes[which]);
            }
        });
        //消极按钮
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.show();
    }

窗体触摸拖拽监听


效果图
这里写图片描述

实现思路:
设置页面点击跳转到一个透明主题,背景色被浅灰色的activity
监听拖拽的图片记录的位置

注册透明主题的activity

        <activity android:name="com.itheima.mobilesafe74.activity.ToastLocationActivity" 
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:background="#accc">
    <!-- imageView在相对布局中,所以其所在位置的规则需要由相对布局提供 -->
    <ImageView 
        android:id="@+id/iv_drag"
        android:background="@drawable/drag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button 
        android:id="@+id/bt_top"
        android:layout_width="match_parent"
        android:text="按中提示框拖拽到任意位置"
        android:gravity="center"
        android:visibility="invisible"
        android:background="@drawable/call_locate_blue"
        android:layout_height="wrap_content"/>
    <Button 
        android:layout_alignParentBottom="true"
        android:id="@+id/bt_bottom"
        android:layout_width="match_parent"
        android:text="按中提示框拖拽到任意位置"
        android:gravity="center"
        android:visibility="visible"
        android:background="@drawable/call_locate_blue"
        android:layout_height="wrap_content"/>
</RelativeLayout>

移动过程图解
这里写图片描述

左上右下坐标获取
这里写图片描述

getRowX和getX差异
这里写图片描述

下边缘显示范围
这里写图片描述

代码

public class ToastLocationActivity extends Activity {
    private ImageView iv_drag;
    private Button bt_top,bt_bottom;
    private WindowManager mWM;
    private int mScreenHeight;
    private int mScreenWidth;


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

        initUI();
    }

    private void initUI() {
        //可拖拽双击居中的图片控件
        iv_drag = (ImageView) findViewById(R.id.iv_drag);
        bt_top = (Button) findViewById(R.id.bt_top);
        bt_bottom = (Button) findViewById(R.id.bt_bottom);

        mWM = (WindowManager) getSystemService(WINDOW_SERVICE);
        mScreenHeight = mWM.getDefaultDisplay().getHeight();
        mScreenWidth = mWM.getDefaultDisplay().getWidth();

        int locationX = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_X, 0);
        int locationY = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_Y, 0);

        //左上角坐标作用在iv_drag上
        //iv_drag在相对布局中,所以其所在位置的规则需要由相对布局提供

        //指定宽高都为WRAP_CONTENT
        LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT, 
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        //将左上角的坐标作用在iv_drag对应规则参数上
        layoutParams.leftMargin = locationX;
        layoutParams.topMargin = locationY;
        //将以上规则作用在iv_drag上
        iv_drag.setLayoutParams(layoutParams);

        if(locationY>mScreenHeight/2){
            bt_bottom.setVisibility(View.INVISIBLE);
            bt_top.setVisibility(View.VISIBLE);
        }else{
            bt_bottom.setVisibility(View.VISIBLE);
            bt_top.setVisibility(View.INVISIBLE);
        }



        //监听某一个控件的拖拽过程(按下(1),移动(多次),抬起(1))
        iv_drag.setOnTouchListener(new OnTouchListener() {
            private int startX;
            private int startY;
            //对不同的事件做不同的逻辑处理
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveX = (int) event.getRawX();
                    int moveY = (int) event.getRawY();

                    int disX = moveX-startX;
                    int disY = moveY-startY;

                    //1,当前控件所在屏幕的(左,上)角的位置
                    int left = iv_drag.getLeft()+disX;//左侧坐标
                    int top = iv_drag.getTop()+disY;//顶端坐标
                    int right = iv_drag.getRight()+disX;//右侧坐标
                    int bottom = iv_drag.getBottom()+disY;//底部坐标

                    //容错处理(iv_drag不能拖拽出手机屏幕)
                    //左边缘不能超出屏幕
                    if(left<0){
                        return true;
                    }

                    //右边边缘不能超出屏幕
                    if(right>mScreenWidth){
                        return true;
                    }

                    //上边缘不能超出屏幕可现实区域
                    if(top<0){
                        return true;
                    }

                    //下边缘(屏幕的高度-22 = 底边缘显示最大值)
                    if(bottom>mScreenHeight - 22){
                        return true;
                    }

                    if(top>mScreenHeight/2){
                        bt_bottom.setVisibility(View.INVISIBLE);
                        bt_top.setVisibility(View.VISIBLE);
                    }else{
                        bt_bottom.setVisibility(View.VISIBLE);
                        bt_top.setVisibility(View.INVISIBLE);
                    }

                    //2,告知移动的控件,按计算出来的坐标去做展示
                    iv_drag.layout(left, top, right, bottom);

                    //3,重置一次其实坐标
                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();

                    break;
                case MotionEvent.ACTION_UP:
                    //4,存储移动到的位置
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_X, iv_drag.getLeft());
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_Y, iv_drag.getTop());
                    break;
                }
                //在当前的情况下返回false不响应事件,返回true才会响应事件
                return true;
            }
        });
    }
}

双击多击事件


多击事件参考谷歌源码实现
原理图
这里写图片描述

代码

public class MainActivity extends Activity {
    private long startTime = 0;
    private long[] mHits = new long[5];

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

        Button bt_click = (Button) findViewById(R.id.bt_click);
        Button bt_many_click = (Button) findViewById(R.id.bt_many_click);

        bt_click.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //两次点击在一定的时间间隔内,才是双击
                if(startTime!=0){
                    long endTime = System.currentTimeMillis();
                    if(endTime-startTime<500){
                        Toast.makeText(getApplicationContext(), "是男人", 0).show();
                    }
                }
                startTime = System.currentTimeMillis();
            }
        });

        bt_many_click.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //了解
                //1,原数组(要被拷贝的数组)
                //2,原数组的拷贝起始位置索引值
                //3,目标数组(原数组的数据---拷贝-->目标数组)
                //4,目标数组接受值的起始索引位置
                //5,拷贝的长度
                System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
                mHits[mHits.length-1] = SystemClock.uptimeMillis();
                if(mHits[mHits.length-1]-mHits[0]<500){
                    //响应了一个三击事件
                    Toast.makeText(getApplicationContext(), "超级赛亚人!!!!", 0).show();
                }
            }
        });


    /*  System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
        mHits[mHits.length-1] = SystemClock.uptimeMillis();
        if (mHits[0] >= (SystemClock.uptimeMillis()-500)) {
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.setClassName("android",
                    com.android.internal.app.PlatLogoActivity.class.getName());
            try {
                startActivity(intent);
            } catch (Exception e) {
                Log.e(LOG_TAG, "Unable to start activity " + intent.toString());
            }
        }*/
    }

}

将双击事件添加到设置中心的设置中
双击居中图解
这里写图片描述

public class ToastLocationActivity extends Activity {
    private ImageView iv_drag;
    private Button bt_top,bt_bottom;
    private WindowManager mWM;
    private int mScreenHeight;
    private int mScreenWidth;
    private long[] mHits = new long[2];

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

        initUI();
    }

    private void initUI() {
        //可拖拽双击居中的图片控件
        iv_drag = (ImageView) findViewById(R.id.iv_drag);
        bt_top = (Button) findViewById(R.id.bt_top);
        bt_bottom = (Button) findViewById(R.id.bt_bottom);

        mWM = (WindowManager) getSystemService(WINDOW_SERVICE);
        mScreenHeight = mWM.getDefaultDisplay().getHeight();
        mScreenWidth = mWM.getDefaultDisplay().getWidth();

        int locationX = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_X, 0);
        int locationY = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_Y, 0);

        //左上角坐标作用在iv_drag上
        //iv_drag在相对布局中,所以其所在位置的规则需要由相对布局提供

        //指定宽高都为WRAP_CONTENT
        LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT, 
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        //将左上角的坐标作用在iv_drag对应规则参数上
        layoutParams.leftMargin = locationX;
        layoutParams.topMargin = locationY;
        //将以上规则作用在iv_drag上
        iv_drag.setLayoutParams(layoutParams);

        if(locationY>mScreenHeight/2){
            bt_bottom.setVisibility(View.INVISIBLE);
            bt_top.setVisibility(View.VISIBLE);
        }else{
            bt_bottom.setVisibility(View.VISIBLE);
            bt_top.setVisibility(View.INVISIBLE);
        }

        iv_drag.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                System.arraycopy(mHits, 1, mHits, 0, mHits.length-1);
                mHits[mHits.length-1] = SystemClock.uptimeMillis();
                if(mHits[mHits.length-1]-mHits[0]<500){
                    //满足双击事件后,调用代码
                    int left = mScreenWidth/2 - iv_drag.getWidth()/2;
                    int top = mScreenHeight/2 - iv_drag.getHeight()/2;
                    int right = mScreenWidth/2+iv_drag.getWidth()/2;
                    int bottom = mScreenHeight/2+iv_drag.getHeight()/2;

                    //控件按以上规则显示
                    iv_drag.layout(left, top, right, bottom);

                    //存储最终位置
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_X, iv_drag.getLeft());
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_Y, iv_drag.getTop());
                }
            }
        });

        //监听某一个控件的拖拽过程(按下(1),移动(多次),抬起(1))
        iv_drag.setOnTouchListener(new OnTouchListener() {
            private int startX;
            private int startY;
            //对不同的事件做不同的逻辑处理
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveX = (int) event.getRawX();
                    int moveY = (int) event.getRawY();

                    int disX = moveX-startX;
                    int disY = moveY-startY;

                    //1,当前控件所在屏幕的(左,上)角的位置
                    int left = iv_drag.getLeft()+disX;//左侧坐标
                    int top = iv_drag.getTop()+disY;//顶端坐标
                    int right = iv_drag.getRight()+disX;//右侧坐标
                    int bottom = iv_drag.getBottom()+disY;//底部坐标

                    //容错处理(iv_drag不能拖拽出手机屏幕)
                    //左边缘不能超出屏幕
                    if(left<0){
                        return true;
                    }

                    //右边边缘不能超出屏幕
                    if(right>mScreenWidth){
                        return true;
                    }

                    //上边缘不能超出屏幕可现实区域
                    if(top<0){
                        return true;
                    }

                    //下边缘(屏幕的高度-22 = 底边缘显示最大值)
                    if(bottom>mScreenHeight - 22){
                        return true;
                    }

                    if(top>mScreenHeight/2){
                        bt_bottom.setVisibility(View.INVISIBLE);
                        bt_top.setVisibility(View.VISIBLE);
                    }else{
                        bt_bottom.setVisibility(View.VISIBLE);
                        bt_top.setVisibility(View.INVISIBLE);
                    }

                    //2,告知移动的控件,按计算出来的坐标去做展示
                    iv_drag.layout(left, top, right, bottom);

                    //3,重置一次其实坐标
                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();

                    break;
                case MotionEvent.ACTION_UP:
                    //4,存储移动到的位置
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_X, iv_drag.getLeft());
                    SpUtil.putInt(getApplicationContext(), ConstantValue.LOCATION_Y, iv_drag.getTop());
                    break;
                }
                //在当前的情况下返回false不响应事件,返回true才会响应事件

                //既要响应点击事件,又要响应拖拽过程,则此返回值结果需要修改为false
                return false;
            }
        });
    }
}

自定义toast获取设置中心中设置的位置及添加移动事件

public class AddressService extends Service {
    public static final String tag = "AddressService";
    private TelephonyManager mTM;
    private MyPhoneStateListener mPhoneStateListener;
    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
    private View mViewToast;
    private WindowManager mWM;
    private String mAddress;
    private TextView tv_toast;
    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            tv_toast.setText(mAddress);
        };
    };
    private int[] mDrawableIds;
    private int mScreenHeight;
    private int mScreenWidth;

    @Override
    public void onCreate() {
        //第一次开启服务以后,就需要去管理吐司的显示
        //电话状态的监听(服务开启的时候,需要去做监听,关闭的时候电话状态就不需要监听)
        //1,电话管理者对象
        mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        //2,监听电话状态
        mPhoneStateListener = new MyPhoneStateListener();
        mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
        //获取窗体对象
        mWM = (WindowManager) getSystemService(WINDOW_SERVICE);

        mScreenHeight = mWM.getDefaultDisplay().getHeight();
        mScreenWidth = mWM.getDefaultDisplay().getWidth();

        super.onCreate();
    }

    class MyPhoneStateListener extends PhoneStateListener{
        //3,手动重写,电话状态发生改变会触发的方法
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                //空闲状态,没有任何活动(移除吐司)
                Log.i(tag, "挂断电话,空闲了.......................");
                //挂断电话的时候窗体需要移除吐司
                if(mWM!=null && mViewToast!=null){
                    mWM.removeView(mViewToast);
                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //摘机状态,至少有个电话活动。该活动或是拨打(dialing)或是通话
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                //响铃(展示吐司)
                Log.i(tag, "响铃了.......................");
                showToast(incomingNumber);
                break;
            }
            super.onCallStateChanged(state, incomingNumber);
        }
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    public void showToast(String incomingNumber) {
        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE   默认能够被触摸
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        params.format = PixelFormat.TRANSLUCENT;
        //在响铃的时候显示吐司,和电话类型一致
        params.type = WindowManager.LayoutParams.TYPE_PHONE;
        params.setTitle("Toast");

        //指定吐司的所在位置(将吐司指定在左上角)
        params.gravity = Gravity.LEFT+Gravity.TOP;

        //吐司显示效果(吐司布局文件),xml-->view(吐司),将吐司挂在到windowManager窗体上
        mViewToast = View.inflate(this, R.layout.toast_view, null);
        tv_toast = (TextView) mViewToast.findViewById(R.id.tv_toast);


        mViewToast.setOnTouchListener(new OnTouchListener() {
            private int startX;
            private int startY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveX = (int) event.getRawX();
                    int moveY = (int) event.getRawY();

                    int disX = moveX-startX;
                    int disY = moveY-startY;

                    params.x = params.x+disX;
                    params.y = params.y+disY;

                    //容错处理
                    if(params.x<0){
                        params.x = 0;
                    }

                    if(params.y<0){
                        params.y=0;
                    }

                    if(params.x>mScreenWidth-mViewToast.getWidth()){
                        params.x = mScreenWidth-mViewToast.getWidth();
                    }

                    if(params.y>mScreenHeight-mViewToast.getHeight()-22){
                        params.y = mScreenHeight-mViewToast.getHeight()-22;
                    }

                    //告知窗体吐司需要按照手势的移动,去做位置的更新
                    mWM.updateViewLayout(mViewToast, params);

                    startX = (int) event.getRawX();
                    startY = (int) event.getRawY();

                    break;
                case MotionEvent.ACTION_UP:
                    SpUtil.putInt(getApplicationContext(),ConstantValue.LOCATION_X, params.x);
                    SpUtil.putInt(getApplicationContext(),ConstantValue.LOCATION_Y, params.y);
                    break;
                }
                //true 响应拖拽触发的事件
                return true;
            }
        });

        //读取sp中存储吐司位置的x,y坐标值

        // params.x为吐司左上角的x的坐标
        params.x = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_X, 0);
        // params.y为吐司左上角的y的坐标
        params.y = SpUtil.getInt(getApplicationContext(), ConstantValue.LOCATION_Y, 0);

        //从sp中获取色值文字的索引,匹配图片,用作展示
        mDrawableIds = new int[]{
                R.drawable.call_locate_white,
                R.drawable.call_locate_orange,
                R.drawable.call_locate_blue,
                R.drawable.call_locate_gray,
                R.drawable.call_locate_green};
        int toastStyleIndex = SpUtil.getInt(getApplicationContext(), ConstantValue.TOAST_STYLE, 0);
        tv_toast.setBackgroundResource(mDrawableIds[toastStyleIndex]);

        //在窗体上挂在一个view(权限)
        mWM.addView(mViewToast, params);

        //获取到了来电号码以后,需要做来电号码查询
        query(incomingNumber);
    }

    private void query(final String incomingNumber) {
        new Thread(){
            public void run() {
                mAddress = AddressDao.getAddress(incomingNumber);
                mHandler.sendEmptyMessage(0);
            };
        }.start();
    }

    @Override
    public void onDestroy() {
        //取消对电话状态的监听(开启服务的时候监听电话的对象)
        if(mTM!=null && mPhoneStateListener!=null){
            mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
        }
        super.onDestroy();
    }
}

猜你喜欢

转载自blog.csdn.net/opopopwqwqwq/article/details/80034698