Android 키보드에서 소프트웨어 키보드가 보이는지 어떻게 알 수 있습니까?


249

Android에서 소프트웨어 (일명 "소프트") 키보드가 화면에 표시되는지 감지하는 방법이 있습니까?



1
수행 할 수 있습니다 - 무슨 일이 (제 3 자 키보드가 설치되어있는 경우) 키보드가 "변경 키보드"라는 시스템 알림이 열려있을 때와 같이 글로벌 알림을 확인하는 것입니다 어떤 경우에는 이에 대한 해결책이 될 수 NotificationListenerService가
Prof

2
거의 8 년 동안 여전히 견고한 솔루션이 없습니다. 만약 그들이 하나를 소개한다면, API> 30이 될 것입니다. 그래서 신경 쓰지 마십시오 ...
M.kazem Akhgary

답변:



276

이것은 나를 위해 작동합니다. 아마도 이것이 항상 모든 버전에 가장 적합한 방법 일 것 입니다 .

키보드 가시성의 속성을 만들고 onGlobalLayout 메소드가 여러 번 호출되므로 이러한 변경이 지연되는 것을 관찰하는 것이 효과적입니다. 또한 장치 회전을 확인하는 것이 좋지만 windowSoftInputMode그렇지 않습니다 adjustNothing.

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});

3
여기에 작업 요점은 다음과 같습니다 gist.github.com/faruktoptas/e9778e1f718214938b00c2dcd2bed109
파 루크 Toptas

1
이것을 utils 클래스에 넣고 액티비티를 전달하십시오. 이제 전체 앱에서 유용합니다.
저스틴

2
그리고 어디에서 contentView선언됩니까?
코드 견습생

1
@ Code-Apprentice 활동 / 조각에서 소프트 키보드 변경에 응답하려고합니다. ContentView는이 활동 / 조각 레이아웃의 루트보기입니다.
airowe

1
Android 6 및 7에서 저를 위해 일했습니다.
V.March 16'18

71

이 시도:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }

9
이것은 나를 위해 작동하지 않습니다. 키보드 표시 분기는 예를 들어 키보드가 표시되지 않았거나 표시되지 않았다가 닫을 때에도 트리거됩니다.
Peter Ajtai

30
항상 참을 돌려줍니다.
shivang Trivedi

1
예, 항상 참입니다.
Léon Pelletier

잘못된. 이것은 항상 참을 돌려줍니다
Gaurav Arora

178
이다 한심한 안드로이드 프레임 워크가 결여되어, 악화, 일관성 이 점이다. 이것은 매우 간단해야합니다.
Vicky Chijwani

57

https://github.com/ravindu1024/android-keyboardlistener에 사용할 수있는 간단한 클래스를 만들었습니다 . 프로젝트에 복사하여 다음과 같이 사용하십시오.

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});

코드 exaclty의 어디에 이것을 넣어야합니까? 나는 이것을 활동에 넣었지만 키보드 모양이나 사라지는 것을 감지하지 못했습니다.
toom

글쎄, 당신은 당신의 활동 내 어디서나 넣을 수 있습니다. setContentView () 호출 후 onCreate () 메소드에 넣으면 콜백이 발생합니다. Btw, 어떤 장치를 사용하고 있습니까?
ravindu1024

@MaulikDodia 내가 확인했고 조각에서 잘 작동합니다. 다음과 같이 설정하십시오 : KeyboardUtils.addKeyboardToggleListener (getActivity (), this); 작동해야합니다. 어떤 장치를 사용하고 있습니까?
ravindu1024

나는 Moto-G3 장치에 노력하고 있습니다. @ ravindu1024
Maulik Dodia

이 스 니펫에 감사드립니다. 리스너를 제거하는 데 필요한 코드입니다.
Pratik Butani

28

아주 쉽게

1. 루트보기에 ID를 넣으십시오.

rootView이 경우 내 루트보기를 가리키는보기 일뿐입니다 relative layout.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">

2. 활동에서 루트보기를 초기화하십시오.

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3. 키보드를 사용하여 키보드가 열렸는지 닫혔는지 감지 getViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();

                if (heightDiff > 100) { 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });

15
이봐 친구,이 마술 100이 어디서 왔는지 말해 줄래? 왜 101 또는 99가 아닌가? 감사합니다
Karoly

@Karoly 나는 이것이 될 수 있다고 생각합니다 1. 문제 없어. 키보드의 실제 길이보다 작아야합니다
Vlad

@Karoly는 기본적으로 창 크기를 활동의 루트보기 크기와 비교합니다. 소프트 키보드의 모양은 기본 창의 크기에 영향을 미치지 않습니다. 따라서 여전히 100의 값을 낮출 수 있습니다.
mr5

매직 넘버는 무엇보다도 topbar의 레이아웃에 따라 다릅니다. 따라서 앱과 관련이 있습니다. 내 중 하나에 400을 사용했습니다.
Morten Holmgaard 18

onGlobalLayout은 매 프레임마다 호출되므로 무거운 작업을 수행하지 마십시오.
Akshay Gaonkar

8

나는 이것을 기본으로 사용했습니다 : http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}

그런 다음이 방법을 썼습니다.

public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {

    IMMResult result = new IMMResult();
    int res;

    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

그런 다음이를 사용하여 소프트 키보드를 열었을 수있는 모든 필드 (EditText, AutoCompleteTextView 등)를 테스트 할 수 있습니다.

    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

물론 이상적인 솔루션은 아니지만 작업이 완료됩니다.


2
작동합니다. 당신이 포커스 변경에 모든 edittexts에 적용하고 하나의 글로벌 키보드 청취자 수 singelton대로 구현하는 경우
Rarw

@depperm getActivity ()는 Fragments에 고유하므로 YourActivityName.this를 대신 시도하십시오. 참조 : stackoverflow.com/questions/14480129/...
크리스토퍼 Hackl의


6

이 답변을 참조 할 수 있습니다-https : //.com/a/24105062/3629912

매번 나를 위해 일했습니다.

adb shell dumpsys window InputMethod | grep "mHasSurface"

소프트웨어 키보드가 표시되면 true를 반환합니다.


10
이것은 개발 중에 만 유용하며 앱에서 사용하기위한 솔루션이 아닙니다. (사용자는 adb를 실행하지 않습니다.)
ToolmakerSteve

5

그래서 AccessibilityServices, 창 삽입물, 화면 높이 감지 등을 오랫동안 사용 해본 결과이 방법을 찾았습니다.

면책 조항 : Android에서는 숨겨진 방법을 사용하므로 일관성이 없을 수 있습니다. 그러나 내 테스트에서 작동하는 것 같습니다.

이 메소드는 InputMethodManager # getInputMethodWindowVisibleHeight () 이며 Lollipop (5.0)부터 존재합니다.

호출하면 현재 키보드의 높이를 픽셀 단위로 반환합니다. 이론적으로 키보드의 높이는 0 픽셀이 아니어야하므로 Kotlin에서 간단한 높이 검사를 수행했습니다.

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
    //keyboard is shown
else {
    //keyboard is hidden
}

숨겨진 메소드를 호출 할 때 리플렉션을 피하기 위해 Android Hidden API 를 사용 합니다.

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic

놀라운 반사 효과
kaustubhpatange

4

이것은 내가 필요한 요구 사항에 비해 훨씬 덜 복잡했습니다. 이것이 도움이되기를 바랍니다.

MainActivity에서 :

public void dismissKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
    mKeyboardStatus = false;
}

public void showKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    mKeyboardStatus = true;
}

private boolean isKeyboardActive(){
    return mKeyboardStatus;
}

mKeyboardStatus의 기본 기본 부울 값은 false 로 초기화됩니다 .

그런 다음 다음과 같이 값을 확인하고 필요한 경우 조치를 수행하십시오.

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }

4

키보드 상태를 확인해야하는 경우 작동합니다.

fun Activity.isKeyboardOpened(): Boolean {
    val r = Rect()

    val activityRoot = getActivityRoot()
    val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)

    activityRoot.getWindowVisibleDisplayFrame(r)

    val heightDiff = activityRoot.rootView.height - r.height()

    return heightDiff > visibleThreshold;
}

fun Activity.getActivityRoot(): View {
    return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}

여기서 UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 및 dip ()는 dpToPx를 변환하는 anko func입니다.

fun dip(value: Int): Int {
    return (value * Resources.getSystem().displayMetrics.density).toInt()
}

3

다음과 같이 GlobalLayoutListener를 설정하여이 작업을 수행했습니다.

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });

이것은 매우 자주 호출됩니다
데니스 Kniazhev

어떤 경우에 @BrownsooHan과 다른가요? 키보드를 벗어나기 위해 다른 앱을 그리는 앱이 표시되는 방법을 찾고 있습니다.
Evan Langlois

그의 대답은 근본적으로 내 것과 동일합니다. 단지 몇 달 전에 광산을 냈으며 더 많은 투표를했습니다.
PearsonArtPhoto

3

KeyboardShown이 Shown이면이 코드를 사용해보십시오.이 함수는 true value ...를 반환합니다.

private final String TAG = "TextEditor";
private TextView mTextEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);
    mTextEditor = (TextView) findViewById(R.id.text_editor);
    mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            isKeyboardShown(mTextEditor.getRootView());
        }
    });
}

private boolean isKeyboardShown(View rootView) {
    /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
    final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;

    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
    int heightDiff = rootView.getBottom() - r.bottom;
    /* Threshold size: dp to pixels, multiply with display density */
    boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;

    Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
            + "root view height:" + rootView.getHeight() + ", rect:" + r);

    return isKeyboardShown;
}

isKeyboardShown은 표시되지 않을 때 계속 호출합니다.
Mandeep Singh

2

내 경우에는 내가 하나가 있었다 EditText내가 오순절 와서, 그래서 내 레이아웃 관리 솔루션을. 기본적으로 EditText초점을 듣고 초점이 변경되거나 뒤로 / 완료 단추를 누르면 로컬 브로드 캐스트를 보내는 사용자 지정 입니다. 당신이 더미를 배치해야하려면 View귀하의 레이아웃 android:focusable="true"android:focusableInTouchMode="true"전화 할 때 때문에 clearFocus()초점이 첫 번째 포커스보기로 재 할당됩니다. 더미 뷰의 예 :

<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>

추가 정보

레이아웃 변경의 차이를 감지하는 솔루션은 화면 밀도에 크게 의존하기 때문에 잘 작동하지 않습니다 .100px는 특정 장치에서는 많을 수 있고 다른 장치에서는 오 탐지가 될 수 없기 때문입니다. 또한 벤더마다 키보드가 다릅니다.


1

안드로이드에서는 ADB 쉘을 통해 탐지 할 수 있습니다. 이 방법을 작성하고 사용했습니다.

{
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession("<userName>", "<IP>", 22);
            session.setPassword("<Password>");
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            ChannelExec channel = (ChannelExec)session.openChannel("exec");
            BufferedReader in = new BufferedReader(new    
            InputStreamReader(channel.getInputStream()));
            channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window 
            InputMethod | findstr \"mHasSurface\"");
            channel.connect();

            String msg = null;
            String msg2 = " mHasSurface=true";

            while ((msg = in.readLine()) != null) {
                Boolean isContain = msg.contains(msg2);
                log.info(isContain);
                if (isContain){
                    log.info("Hiding keyboard...");
                    driver.hideKeyboard();
                }
                else {
                    log.info("No need to hide keyboard.");
                }
            }

            channel.disconnect();
            session.disconnect();

        } catch (JSchException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1
모든 수입품과 실제 사례가 포함 된보다 구체적인 예를 통해이 답변을 개선 할 수 있습니까?
사용자 3

1
final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int screenHeight = activityRootView.getRootView().getHeight();
            Log.e("screenHeight", String.valueOf(screenHeight));
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.e("heightDiff", String.valueOf(heightDiff));
            boolean visible = heightDiff > screenHeight / 3;
            Log.e("visible", String.valueOf(visible));
            if (visible) {
                Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
            }
        }
});

1

@ iWantScala의 답변은 훌륭하지만 저
rootView.getRootView().getHeight()에게는 효과가 없습니다. 항상 동일한 값을 갖습니다.

한 가지 방법은 두 가지 변수를 정의하는 것입니다

private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;

글로벌 리스너 추가

rootView.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            currentRootViewHeight = rootView.getHeight();
            if (currentRootViewHeight > maxRootViewHeight) {
                maxRootViewHeight = currentRootViewHeight;
            }
        }
    });

그런 다음 확인

if (currentRootViewHeight >= maxRootViewHeight) {
    // Keyboard is hidden
} else {
    // Keyboard is shown
}

잘 작동합니다


1

이제 Kotlin을 기반으로 Android R에서 시작하는 직접적인 방법이 있습니다.

 val imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
     //Ime is visible
     //Lets move our view by the height of the IME
     view.translationX = imeInsets.bottom }

0

나는 비슷한 문제가 있었다. 화면의 Enter 버튼 (키보드를 숨겼습니다)에 반응해야했습니다. 이 경우 키보드가 열린 텍스트보기의 OnEditorAction을 편집 할 수 있습니다. 편집 가능한 상자가 여러 개인 경우 모든 상자를 구독하십시오.

활동에서 키보드를 완벽하게 제어 할 수 있으므로 모든 개폐 이벤트를 듣는 경우 키보드가 열렸는지 여부에 관계없이 어떤 시점에서도 문제에 직면하지 않습니다.


나를 위해 작동하지 않습니다. OnEditorAction에서만 Enter 키를받습니다.
3c71

0

이것을 알아내는 직접적인 방법이 있습니다. 또한 레이아웃을 변경할 필요가 없습니다.
몰입 형 전체 화면 모드에서도 작동합니다.
그러나 불행히도 모든 장치에서 작동하지는 않습니다. 따라서 장치로 테스트해야합니다.

요령은 소프트 키보드를 숨기거나 표시하고 시도 결과를 캡처하는 것입니다.
올바르게 작동하면 키보드가 실제로 표시되거나 숨겨지지 않습니다. 우리는 단지 국가를 요구합니다.

최신 상태를 유지하려면 처리기를 사용하여 예를 들어 200 밀리 초마다이 작업을 반복하면됩니다.

아래 구현은 단일 검사 만 수행합니다.
여러 번 검사를 수행하는 경우 모든 (_keyboardVisible) 테스트를 활성화해야합니다.

public interface OnKeyboardShowHide
{
    void    onShowKeyboard( Object param );
    void    onHideKeyboard( Object param );
}

private static Handler      _keyboardHandler    = new Handler();
private boolean             _keyboardVisible    = false;
private OnKeyboardShowHide  _keyboardCallback;
private Object              _keyboardCallbackParam;

public void start( OnKeyboardShowHide callback, Object callbackParam )
{
    _keyboardCallback      = callback;
    _keyboardCallbackParam = callbackParam;
    //
    View view = getCurrentFocus();
    if (view != null)
    {
        InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
        imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
        imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
    }
    else // if (_keyboardVisible)
    {
        _keyboardVisible = false;
        _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
    }
}

private ResultReceiver      _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
    @Override
    protected void onReceiveResult( int resultCode, Bundle resultData )
    {
        switch (resultCode)
        {
            case InputMethodManager.RESULT_SHOWN :
            case InputMethodManager.RESULT_UNCHANGED_SHOWN :
                // if (!_keyboardVisible)
                {
                    _keyboardVisible = true;
                    _keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
                }
                break;
            case InputMethodManager.RESULT_HIDDEN :
            case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
                // if (_keyboardVisible)
                {
                    _keyboardVisible = false;
                    _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
                }
                break;
        }
    }
};

전화하는 방법과 어디서?
Mahdi Astanei

0

다음은 소프트 키보드가 표시되는지 확인하는 해결 방법입니다.

  1. ActivityManager.getRunningServices (max_count_of_services);를 사용하여 시스템에서 서비스가 실행 중인지 확인하십시오.
  2. 리턴 된 ActivityManager.RunningServiceInfo 인스턴스에서 소프트 키보드 서비스에 대한 clientCount 값을 확인하십시오 .
  3. 앞에서 언급 한 clientCount는 매번 증가하며 소프트 키보드가 표시됩니다. 예를 들어, clientCount가 처음에 1이면 키보드가 표시 될 때 2가됩니다.
  4. 키보드 해제시 clientCount가 감소합니다. 이 경우 1로 재설정됩니다.

인기있는 키보드 중 일부는 classNames에 특정 키워드가 있습니다.

  1. Google AOSP = IME
  2. Swype = IME
  3. 스위프트 키 = KeyboardService
  4. Fleksy = 키보드
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. 스마트 = 키보드 (SmartKeyboard)

ActivityManager.RunningServiceInfo의 ClassNames에서 위 패턴을 확인하십시오. 또한 ActivityManager.RunningServiceInfo의 clientPackage = android는 키보드가 시스템에 바인딩되어 있음을 나타냅니다.

위에서 언급 한 정보를 결합하여 소프트 키보드가 보이는지 엄격하게 알 수 있습니다.


0

아시다시피 안드로이드 소프트웨어 키보드는 입력이 가능한 경우에만 표시됩니다. 다시 말해 키보드는 EditText에 포커스가있을 때만 표시됩니다. 즉, OnFocusChangeListener 를 사용하여 키보드가 보이는 날씨를 얻을 수 있습니다 .

//Declare this Globally

public boolean isKeyBoardVisible = false;

//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*

text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus)
            isKeyBoardVisible = true;
        else
            isKeyBoardVisible = false;
    }
});

이제 클래스의 어느 곳에서나 isKeyBoardVisible 변수 를 사용 하여 키보드가 열려 있거나없는 날씨를 얻을 수 있습니다. 그것은 나를 위해 잘 작동했습니다.

참고 : 이 프로세스는 OnFocusChangeListener를 호출하지 않기 때문에 InputMethodManager를 사용하여 프로그래밍 방식으로 키보드를 열면 작동 하지 않습니다.


실제로는 해킹이 아니며 중첩 된 조각 사례에서는 작동하지 않았습니다. 내가 아직 이것을 시도하지 않았으므로 활동에 대해 말할 수 없습니다.
antroid 2018 년

0

답변을 kotlin으로 변환했습니다. 이것이 kotlin 사용자에게 도움이되기를 바랍니다.

private fun checkKeyboardVisibility() {
    var isKeyboardShowing = false

    binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
        val r = Rect()
        binding.coordinator.getWindowVisibleDisplayFrame(r)
        val screenHeight = binding.coordinator.rootView.height

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        val keypadHeight = screenHeight - r.bottom


        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true

            }
        } else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false

            }
        }
    }
}

0

adjustNothing 플래그와 함께 작동하며 수명주기 이벤트가 사용됩니다. Kotlin과 함께 :

/**
 * This class uses a PopupWindow to calculate the window height when the floating keyboard is opened and closed
 *
 * @param activity The parent activity
 *  The root activity that uses this KeyboardManager
 */
class KeyboardManager(private val activity: AppCompatActivity) : PopupWindow(activity), LifecycleObserver {

    private var observerList = mutableListOf<((keyboardTop: Int) -> Unit)>()

    /** The last value of keyboardTop */
    private var keyboardTop: Int = 0

    /** The view that is used to calculate the keyboard top  */
    private val popupView: View?

    /** The parent view  */
    private var parentView: View

    var isKeyboardShown = false
        private set

    /**
     * Create transparent view which will be stretched over to the full screen
     */
    private fun createFullScreenView(): View {
        val view = LinearLayout(activity)
        view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT)
        view.background = ColorDrawable(Color.TRANSPARENT)
        return view
    }

    init {
        this.popupView = createFullScreenView()
        contentView = popupView

        softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE or LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
        inputMethodMode = INPUT_METHOD_NEEDED

        parentView = activity.findViewById(android.R.id.content)

        width = 0
        height = LayoutParams.MATCH_PARENT

        popupView.viewTreeObserver.addOnGlobalLayoutListener {
            val rect = Rect()
            popupView.getWindowVisibleDisplayFrame(rect)

            val keyboardTop = rect.bottom
            if (this.keyboardTop != keyboardTop) {
                isKeyboardShown = keyboardTop < this.keyboardTop
                this.keyboardTop = keyboardTop
                observerList.forEach { it(keyboardTop) }
            }
        }
        activity.lifecycle.addObserver(this)
    }

    /**
     * This must be called after the onResume of the Activity or inside view.post { } .
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun start() {
        parentView.post {
            if (!isShowing && parentView.windowToken != null) {
                setBackgroundDrawable(ColorDrawable(0))
                showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
            }
        }
    }

    /**
     * This manager will not be used anymore
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun close() {
        activity.lifecycle.removeObserver(this)
        observerList.clear()
        dismiss()
    }

    /**
     * Set the keyboard top observer. The observer will be notified when the keyboard top has changed.
     * For example when the keyboard is opened or closed
     *
     * @param observer The observer to be added to this provider
     */
    fun registerKeyboardTopObserver(observer: (keyboardTop: Int) -> Unit) {
        observerList.add(observer)
    }
}

항상 키보드 위에서 볼 수있는 유용한 방법

fun KeyboardManager.updateBottomMarginIfKeyboardShown(
        view: View,
        activity: AppCompatActivity,
        // marginBottom of view when keyboard is hide
        marginBottomHideKeyboard: Int,
        // marginBottom of view when keybouard is shown
        marginBottomShowKeyboard: Int
) {
    registerKeyboardTopObserver { bottomKeyboard ->
        val bottomView = ViewUtils.getFullViewBounds(view).bottom
        val maxHeight = ScreenUtils.getFullScreenSize(activity.windowManager).y
        // Check that view is within the window size
        if (bottomView < maxHeight) {
            if (bottomKeyboard < bottomView) {
                ViewUtils.updateMargin(view, bottomMargin = bottomView - bottomKeyboard +
                        view.marginBottom + marginBottomShowKeyboard)
            } else ViewUtils.updateMargin(view, bottomMargin = marginBottomHideKeyboard)
        }
    }
}

getFullViewBounds

fun getLocationOnScreen(view: View): Point {
    val location = IntArray(2)
    view.getLocationOnScreen(location)
    return Point(location[0], location[1])
}

fun getFullViewBounds(view: View): Rect {
     val location = getLocationOnScreen(view)
     return Rect(location.x, location.y, location.x + view.width,
            location.y + view.height)
 }

어디서 getFullScreenSize

fun getFullScreenSize(wm: WindowManager? = null) =
            getScreenSize(wm) { getRealSize(it) }

private fun getScreenSize(wm: WindowManager? = null, block: Display.(Point) -> Unit): Point {
    val windowManager = wm ?: App.INSTANCE.getSystemService(Context.WINDOW_SERVICE)
            as WindowManager
    val point = Point()
    windowManager.defaultDisplay.block(point)
    return point
}

여기서 updateMargin

fun updateMargin(
        view: View,
        leftMargin: Int? = null,
        topMargin: Int? = null,
        rightMargin: Int? = null,
        bottomMargin: Int? = null
) {
    val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
    if (leftMargin != null) layoutParams.leftMargin = leftMargin
    if (topMargin != null) layoutParams.topMargin = topMargin
    if (rightMargin != null) layoutParams.rightMargin = rightMargin
    if (bottomMargin != null) layoutParams.bottomMargin = bottomMargin
    view.layoutParams = layoutParams
}

-1

나는 이것을 다음과 같이했지만, 당신의 목표가 keyboad를 닫고 여는 것이라면 만 가능합니다.

닫기 예 : (키보드가 이미 닫혀 있는지 확인-닫지 않은 경우)

imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        super.onReceiveResult(resultCode, resultData);
                        if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
                            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    }
                });

문제는 두 키보드가 표시되지 않거나 알아 관련이 있었다
고팔 싱 Sirvi

-1

a를 사용 중일 수 있습니다.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Log.d(
    getClass().getSimpleName(), 
    String.format("conf: %s", newConfig));

    if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
        onHardwareKeyboardChange(newConfig.hardKeyboardHidden);

        hardKeyboardHidden = newConfig.hardKeyboardHidden;
    }

    if (newConfig.keyboardHidden != keyboardHidden) {
        onKeyboardChange(newConfig.keyboardHidden);

        keyboardHidden = newConfig.hardKeyboardHidden;
    }

}

public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;

//todo
private void onKeyboardChange(int keyboardHidden) {

}

//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {

}

이것은 소프트웨어 키보드가 아닌 하드웨어 키보드에서만 작동합니다.
anthonymonori


-1

앱에서 AndroidR 용 API를 지원하는 경우 아래 방법을 사용할 수 있습니다.

In kotlin :
    var imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
        view.translationX = imeInsets.bottom 
    }

참고 : 이것은 AndroidR에서만 사용할 수 있으며 아래 안드로이드 버전은 다른 답변을 따라야합니다. 그렇지 않으면 업데이트 할 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.