brunch

You can make anything
by writing

C.S.Lewis

by 장대희 Jul 28. 2016

Android SoftKeyPad Detector

ViewTreeObserver를 이용한 키패드 리스너

Android에서 SoftKeyPad가 올라왔는지 내려갔는지 알아야 할 때가 있다.

또한, 이 키패드의 높이가 얼마나 되는지도 필요할 수 있다.

내 경우 에디터를 만들 때는 정말 필요했다.


키패드의 변화를 알아먹기 위해서 이용한 것은 ViewTreeObserver.OnGlobalLayoutListener 이다.

우리는 늘 레퍼런스를 잘 봐야 한다. 투척~

https://developer.android.com/reference/android/view/ViewTreeObserver.OnGlobalLayoutListener.html



1. 키패드의 변화를 받을 Interface를 생성

키패드가 올라오면 visible이 true, 내려가면 false.

visible이 true일 때는 height로 키패드의 높이값을 pixel로 준다.


2. 키패드의 변화를 감지할 class를 생성

class의 변수 선언부

OnGlobalLayoutListener를 implements.

키패드의 최소 높이 추정치를 갖고 있다.

layout의 변화를 감지할 View를 갖는다.

화면 box의 정보를 갖고 있을 Rect를 갖는다.

화면 Orientaion이 바뀔 때도 layout이 변화한 것으로 callback 이 오는데... 이때, Orientaion 의 변화는 따로 체크하기 위하여 box 의 우측 point를 갖고 있는 mRectRight 값을 갖고 있어야 한다.

layout 의 변화에 따른 화면 높이값을 갖고 있는 mVisibleHeight 값을 갖는다.

키패드가 보이고 있는지 여부 / 키패드의 높이 / status bar 높이 등의 값을 갖는다.

Activity 또는 Fragment 의 Pause시에 layout의 변화 감지를 잠시 멈추기 위해 boolean 값을 갖는다.



class 의 생성자

생성자는 View를 직접 받을 수도 있고, Activity 또는 Fragment를 받을 수 있다.



Detector 의 start, stop, resume, pasue

Detector의 동작을 정의한 method.

start에서는 VeiwTreeObserver에 mView를 등록하고, stop에서는 해제한다.

ViewTreeObserver 에 등록/해제

ViewTreeObserver에 등록과 해제하는 method.



자 이제 대망의 ViewTreeObserver.OnGlobalLayoutListener의 callback method이다.

대망의 키패드 변화 감지

View가 보이는 영역을 Rect에 담아준다.

화면 Orientation이 바뀐 건 무시.(Rect 의 우측 값이 바뀐 거면 회전으로 간주한다.)

보이던 높이값이 바뀐 것이라면, 얼마나 변화가 일어난 건지 값을 구한다.

국내에 있는 단말 중에 xhdpi 이상을 위한 것으로... 최소 높이 300 pixel 보다 크게 변화가 일어났다면 이건 키패드가 올라온 것으로 간주한다.

callback listener로 변화를 던져준다.

 


3. 키패드 감지를 실제 사용해 보자.

Activity의 onCreate에서 디텍터를 생성한다.

@Override
public void onCreate() {
    super.onCreate();
    ...
    // 키보드 디텍터 생성
    softInputDetector = new SoftInputDetector(this);
    softInputDetector.setOnSoftInputListener(mSoftInputListener);

Activity의 onResume에서 디텍터를 시작한다.

@Override
public void onResume() {
    super.onResume();
    ...
    // 키패드 디텍터 시작
    softInputDetector.start();

Activity의 onPause에서는 디텍터를 중지한다.

@Override
public void onPause() {
    // 키패드 디텍터 중지
    softInputDetector.stop();
    super.onPause();
    ...

자 이제 디텍터의 리스너에서 이것저것 한다.

/**
 * 키패드 변화 리스너
 */
private OnSoftInputListener mSoftInputListener = new OnSoftInputListener() {
    @Override
    public void onSoftInputChanged(boolean visible, int height) {
        // 키패드 올라옴
        if (visible) {
            // TODO :: 텍스트 에디터 style window 의 높이 설정
            // TODO :: 에디터 툴바 색 변경 등등...
        } else { // 키패드 내려감
            // TODO :: 텍스트 에디터 style window 가 떠 있으면 없앰
            // TODO :: 에디터 툴바 색 변경 등등...
        }
    }
};


전체 소스는 github 참조.

https://github.com/fooldrum/Android-SoftKeyPad-Change-Listener.git



 p.s.

Android N이 곧 나온다.

이 아이는 Multi-Window를 지원한단다. TV의 PIP 같은...

아마 동작이 엉망이 될 가능성이 있다. ㅡ.ㅡ;

그러나, 또 피할 방법이 있다. 우리 앱은 Multi-Window를 지원하지 않는 앱으로 설정하면 된다.

까이꺼 가뿐하게 android:resizeableActivity=false를 선언해버리련다.

(아마 기획/디자인에서 싫어하겠지 ㅠ.ㅠ)


p.s.

이번 글은 내가 존경하는 장동수(https://www.facebook.com/iolothebard)님의 도움을 받아 작성했다.

Respect!! iolo.fitzowen!!



참고

1. View 의 getWindowVisibleDisplayFrame

https://developer.android.com/reference/android/view/View.html#getWindowVisibleDisplayFrame(android.graphics.Rect)

2. ViewTreeObserver 전체

https://developer.android.com/reference/android/view/ViewTreeObserver.html

매거진의 이전글 Android bluetooth keyboard

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari