Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 在Activity,Service,Window中監聽Home鍵和返回鍵的一些思考,如何把事件傳遞出來的做法!

在Activity,Service,Window中監聽Home鍵和返回鍵的一些思考,如何把事件傳遞出來的做法!

編輯:關於Android編程

在Activity,Service,Window中監聽Home鍵和返回鍵的一些思考,如何把事件傳遞出來的做法!


其實像按鍵的監聽,我相信很多人都很熟練了,我肯定也不會說這些基礎的東西,所以,前期,還是一筆帶過一下,我們重點說下後半部分吧

一.Activity監聽返回鍵

這個其實大家都知道,首先我們要了解流程,你要屏蔽這個返回鍵,那你就要拿到這個返回鍵的事件了,所以我們要監聽了,而在Activity中,有兩種做法,首先,系統是提供了返回鍵的監聽的

    /**
     * 返回鍵監聽
     */
    @Override
    public void onBackPressed() {
        //super.onBackPressed();
    }

我們只要不讓使用父類的onBackPressed方法,那返回鍵就沒作用了,還有一種辦法就是系統提供的按鍵監聽的方法了

    /**
     * 按鍵監聽
     * @param keyCode
     * @param event
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                //返回鍵
                Toast.makeText(this,"返回鍵",Toast.LENGTH_SHORT).show();
                break;
        }
        return super.onKeyDown(keyCode, event);
    }

onKeyDown是按下的動作,鍵盤按下的動作就可以,他可以監聽到很多的按鍵,比如數字鍵,當然,現在數字鍵的手機還是比較少的,KeyEvent 為我們封裝了絕大多數的監聽,我們來看一下演示的效果

這裡寫圖片描述

二.Service中監聽Home鍵

onKeyDown中有監聽Home鍵的方法,但是你會發現監聽起來是無效的,這裡其實可以通過廣播的形式來監聽Home鍵,不光適用在Service,同樣的也可以適用在Activity中,我們新建一個HomeService

package com.liuguilin.keyevevtsample;

/*
 *  項目名:  KeyEvevtSample 
 *  包名:    com.liuguilin.keyevevtsample
 *  文件名:   HomeService
 *  創建者:   LGL
 *  創建時間:  2016/8/20 11:00
 *  描述:    Home鍵監聽
 */

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.widget.Toast;

public class HomeService extends Service {

    //監聽Home
    private HomeWatcherReceiver mHomeKeyReceiver;
    public static final String SYSTEM_DIALOG_REASON_KEY = "reason";
    public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        //注冊Home監聽廣播
        mHomeKeyReceiver = new HomeWatcherReceiver();
        final IntentFilter homeFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        registerReceiver(mHomeKeyReceiver, homeFilter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        //取消監聽
        unregisterReceiver(mHomeKeyReceiver);
    }

    /**
     * 監聽Home鍵
     */
    class HomeWatcherReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
                    Toast.makeText(context, "Home按鍵", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

OK,為了測試,我們加上兩個button


同時增加兩個點擊事件

    findViewById(R.id.openHome).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(new Intent(MainActivity.this,HomeService.class));
            }
        });
    findViewById(R.id.closeHome).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(new Intent(MainActivity.this,HomeService.class));
            }
        });

對了,別忘記了注冊一下Service

 

好的,我們來檢驗一下效果吧

這裡寫圖片描述

OK<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjwvYmxvY2txdW90ZT4NCjxoMiBpZD0="三在window中監聽返回鍵">三.在Window中監聽返回鍵

這裡,其實也是我項目中的一個需求,首選,我們先不說邏輯,先把window寫好,我們為了閱讀性,我們再新建一個Service——WindowService,同時去注冊一下

而我們的需求,就是啟動一個service,service裡加載一個window,但是這樣做其實是拿不到我們的按鍵時間的,都給其他人拿走了,但是這些都是後話了,我們先把window的代碼寫好

package com.liuguilin.keyevevtsample;

/*
 *  項目名:  KeyEvevtSample 
 *  包名:    com.liuguilin.keyevevtsample
 *  文件名:   WindowService
 *  創建者:   LGL
 *  創建時間:  2016/8/20 11:11
 *  描述:    窗口服務
 */

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class WindowService extends Service implements View.OnClickListener {

    //窗口管理器
    private WindowManager wm;
    //view
    private View mView;
    //布局參數
    private WindowManager.LayoutParams layoutParams;
    //取消window
    private Button btnCloseWindow;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initWindow();
    }

    /**
     * 初始化Window
     */
    private void initWindow() {
        //窗口管理器
        wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        //布局參數
        layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.flags =
                //WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | 不能觸摸
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
        //格式
        layoutParams.format = PixelFormat.TRANSLUCENT;
        //類型
        layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;

        mView = View.inflate(getApplicationContext(), R.layout.layout_window_item, null);
        btnCloseWindow = (Button) mView.findViewById(R.id.btnCloseWindow);
        btnCloseWindow.setOnClickListener(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //顯示window
        wm.addView(mView, layoutParams);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /**
     * 點擊事件
     *
     * @param view
     */
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnCloseWindow:
                //取消window
                wm.removeView(mView);
                break;
        }
    }
}

這裡有一點要注意的地方,首先,window是需要權限的

好的,為了測試,我們些個按鈕

同時給他加上點擊事件

findViewById(R.id.openWindow).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(new Intent(MainActivity.this, WindowService.class));
            }
        });

OK,到這裡,我們的window算是寫好了,但是寫好了,也就出來我們今天要探討的問題了

這裡寫圖片描述

你這個Window,拿不到返回事件,所以我按返回鍵的時候Activity退出了,window還在,那window就是沒有拿到這個事件了,那我們應該怎麼去拿到這個事件呢?我們怎麼按返回鍵先退出Window再退出Activity呢?其實我們只要注意這行代碼

mView = View.inflate(getApplicationContext(), R.layout.layout_window_item, null);

我們這裡也是有一個View的,我們可用把這個事件給攔截過來,這都是有可能的,想到了就去做,那我們最終要怎麼去做?我們可用重寫這個view,把事件通過接口的方式綁定在這個window上,如果不聽不明白,你可以跟我一起來看下這段代碼,我們這個view,我給他一個容器,那我們就重寫LinearLayout

package com.liuguilin.keyevevtsample;

/*
 *  項目名:  KeyEvevtSample 
 *  包名:    com.liuguilin.keyevevtsample
 *  文件名:   SessionLinearLayout
 *  創建者:   LGL
 *  創建時間:  2016/8/20 11:33
 *  描述:    事件分發/攔截返回按鈕
 */

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.LinearLayout;

public class SessionLinearLayout extends LinearLayout {


    private DispatchKeyEventListener mDispatchKeyEventListener;

    public SessionLinearLayout(Context context) {
        super(context);
    }

    public SessionLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SessionLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (mDispatchKeyEventListener != null) {
            return mDispatchKeyEventListener.dispatchKeyEvent(event);
        }
        return super.dispatchKeyEvent(event);
    }

    public DispatchKeyEventListener getDispatchKeyEventListener() {
        return mDispatchKeyEventListener;
    }

    public void setDispatchKeyEventListener(DispatchKeyEventListener mDispatchKeyEventListener) {
        this.mDispatchKeyEventListener = mDispatchKeyEventListener;
    }

    //監聽接口
    public static interface DispatchKeyEventListener {
        boolean dispatchKeyEvent(KeyEvent event);
    }

}

我在這裡,只是把他作為一個中轉站,把事件給傳遞出來就好了,那我們現在window加載的layout的根布局就是他了


那我們的View也是他了,我們直接來看詳細的代碼吧

package com.liuguilin.keyevevtsample;

/*
 *  項目名:  KeyEvevtSample 
 *  包名:    com.liuguilin.keyevevtsample
 *  文件名:   WindowService
 *  創建者:   LGL
 *  創建時間:  2016/8/20 11:11
 *  描述:    窗口服務
 */

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

public class WindowService extends Service implements View.OnClickListener {

    //窗口管理器
    private WindowManager wm;
    //view
    private SessionLinearLayout mView;
    //布局參數
    private WindowManager.LayoutParams layoutParams;
    //取消window
    private Button btnCloseWindow;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initWindow();
    }

    /**
     * 初始化Window
     */
    private void initWindow() {
        //窗口管理器
        wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        //布局參數
        layoutParams = new WindowManager.LayoutParams();
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.flags =
                //WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | 不能觸摸
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                       ;
        //格式
        layoutParams.format = PixelFormat.TRANSLUCENT;
        //類型
        layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;

        mView = (SessionLinearLayout) View.inflate(getApplicationContext(), R.layout.layout_window_item, null);
        btnCloseWindow = (Button) mView.findViewById(R.id.btnCloseWindow);
        btnCloseWindow.setOnClickListener(this);

        //監聽返回鍵
        mView.setDispatchKeyEventListener(mDispatchKeyEventListener);
    }
    /**
     * 返回鍵監聽
     */
    private SessionLinearLayout.DispatchKeyEventListener mDispatchKeyEventListener = new SessionLinearLayout.DispatchKeyEventListener() {

        @Override
        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                if (mView.getParent() != null) {
                    wm.removeView(mView);
                }
                return true;
            }
            return false;
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //顯示window
        wm.addView(mView, layoutParams);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /**
     * 點擊事件
     *
     * @param view
     */
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnCloseWindow:
                //取消window
                wm.removeView(mView);
                break;
        }
    }
}

OK,我們這裡只是用了一個小技巧而已,但是在實際開發當中還是很實用的,我們直接來看效果

這裡寫圖片描述

好的,本篇博文就先到這裡,感謝你的耐心閱讀,覺得不錯的haunted贊一個喲,有不足的地方也請指正

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved