Android 장치에 소프트웨어 키보드가 표시되는지 여부를 확인하려면 어떻게 해야 합니까?
Android에서 소프트웨어(일명 "소프트") 키보드가 화면에 보이는지 감지하는 방법이 있습니까?
저는 이 정도면 돼요.어쩌면 이것이 모든 버전에 항상 최선의 방법일지도 모릅니다.
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)
}
}
}
});
시도해 보십시오.
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
writeToLog("Software Keyboard was shown");
} else {
writeToLog("Software Keyboard was not shown");
}
직접적인 방법은 없습니다 - 안드로이드 팀의 Dianne Hackborn이 응답한 http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a 을 참조하십시오.그러나 #onMeasure에서 윈도우 크기가 변경되었는지 확인하여 간접적으로 감지할 수 있습니다.Android에서 소프트웨어 키보드의 가시성을 확인하는 방법을 참조하십시오.
나는 이것을 위해 사용할 수 있는 간단한 수업을 만들었습니다: https://github.com/ravindu1024/android-keyboardlistener .프로젝트에 복사만 하면 다음과 같이 사용할 수 있습니다.
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
@Override
public void onToggleSoftKeyboard(boolean isVisible)
{
Log.d("keyboard", "keyboard visible: "+isVisible);
}
});
새로운 기능과 함께WindowInsetsCompat
안드로이드x 코어 릴리즈 1.5.0-alpha02에서는 아래와 같이 소프트 키보드의 가시성을 쉽게 확인할 수 있었습니다.
레딧 댓글에서 인용하기
val View.keyboardIsVisible: Boolean get() = WindowInsetsCompat .toWindowInsetsCompat(rootWindowInsets) .isVisible(WindowInsetsCompat.Type.ime())
이전 버전과의 호환성에 대한 몇 가지 참고 사항(릴리스 노트에서 인용)
새 기능
그
WindowInsetsCompat
API는 안드로이드 11의 플랫폼에 있는 API로 업데이트되었습니다.여기에는 새로운 것이 포함됩니다.ime()
화면 키보드의 가시성과 크기를 확인할 수 있는 inset type.몇 가지 주의할 점은
ime()
타입, 그것은 당신의 Activity가 사용하고 있을 때 API 23+에서 매우 안정적으로 작동합니다.adjustResize
윈도우 소프트 입력 모드.대신 사용하는 경우adjustPan
mode, API 14로 안정적으로 돌아갈 수 있어야 합니다.
참고문헌
아주 쉬운
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) { // Value should be less than keyboard's height
Log.e("MyActivity", "keyboard opened");
} else {
Log.e("MyActivity", "keyboard closed");
}
}
});
그래서 오랫동안 내게 접근성 서비스, 창 삽입 장치, 화면 높이 감지 등을 가지고 놀다가 이것을 할 수 있는 방법을 찾은 것 같습니다.
면책 사항: Android의 숨겨진 방법을 사용하므로 일관성이 없을 수 있습니다.하지만, 제 테스트에서는 효과가 있는 것 같습니다.
메서드는 InputMethodManager#get입니다.입력 방법 창 표시높이(), 그리고 그것은 롤리팝(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
}
저는 안드로이드 히든 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
Androidx.core(버전 1.5.0-rc01)에서 WindowInsetsCompat을 사용할 수 있습니다.이 코드는 API 21 이상부터 동작합니다.코틀린 코드 예제:
ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
if (isKeyboardVisible) {
}
}
root은 활동의 root 보기입니다.
갱신하다
오늘은 키보드의 가시성을 감지하는 방법을 찾고 있었습니다.처음에는 이 코드가 작동하지 않았습니다.그래서 나는 다음과 같이 해야 했습니다.
- 더하다
android:windowSoftInputMode="adjustResize"
Android Manifest.xml 파일로 이동합니다.
xml
<activity android:name="com.soumicslabs.activitykt.StartActivity"
android:theme="@style/AccountKitTheme.Default"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
/>
- 에서 를 설정합니다
WindowCompat.setDecorFitsSystemWindows(window, false)
/시스템 않음을 즉, Android 를 는합니다.
val window = this.window
WindowCompat.setDecorFitsSystemWindows(window, false) // <-- this tells android not to use system defaults, so we have to setup quite a lot of behaviors manually
- 마지막으로, 당신을 잡으세요.
onApplyWindowInsetsListener
:
val callBack = OnApplyWindowInsetsListener { view, insets ->
val imeHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom?:0
Log.e("tag", "onKeyboardOpenOrClose imeHeight = $imeHeight")
// todo: logic
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
if (isKeyboardVisible) {
// do something
}else{
// do something else
}
insets?: WindowInsetsCompat(null)
}
ViewCompat.setOnApplyWindowInsetsListener(mainContainer, callBack)
저는 이게 통했어요.
저는 이것을 근거로 사용했습니다: https://rogerkeays.com/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, AutoComplete)를 테스트할 수 있습니다.소프트키보드를 열었을 가능성이 있는 TextView(텍스트 보기) 등:
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);
더해서 이상적인 해결책은 아니지만, 일은 완수할 수 있습니다.
showSoft의 콜백 결과를 사용할 수 있습니다.()를 입력하고 SoftInput()을 숨겨 키보드 상태를 확인합니다.전체 세부 정보 및 예제 코드:
https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android
이제 마침내 코틀린을 기반으로 하는 안드로이드 R에서 직접적인 방법이 있습니다.
val imeInsets = requireView().rootWindowInsets.isVisible(WindowsInsetsCompat.Type.ime())
if (imeInsets) {
//Ime is visible
//Lets move our view by the height of the IME
view.translationX = imeInsets.bottom }
이것은 제가 필요로 하는 요구사항에 비해 훨씬 덜 복잡했습니다.도움이 되기를 바랍니다.
주 활동에 대해:
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;
}
기본 primative boolean 값 form mKeyboardStatus는 false로 초기화됩니다.
다음과 같이 값을 확인하고 필요한 경우 조치를 수행합니다.
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
키보드 상태를 확인해야 할 경우 이 작업을 수행해야 합니다.
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 100과 dip은 dpToPx하는 Anko func다를 입니다.
fun dip(value: Int): Int {
return (value * Resources.getSystem().displayMetrics.density).toInt()
}
이 답변을 참고하실 수 있습니다 - https://stackoverflow.com/a/24105062/3629912
전 매번 효과가 있었어요.
adb shell dumpsys window InputMethod | grep "mHasSurface"
소프트웨어 키보드가 보이면 true로 돌아갑니다.
다음과 같이 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
}
}
});
이 코드를 사용해 보십시오. 키보드가 있으면 정말로 작동합니다.표시된 다음 이 함수는 참 값을 반환합니다.
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;
}
안드로이드 소프트웨어 키보드는 입력 가능한 이벤트가 있을 때만 볼 수 있습니다.즉, 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 변수를 사용하여 키보드가 열리거나 열리지 않는 날씨를 파악할 수 있습니다.저한테는 잘 통했어요.
참고: InputMethodManager를 사용하여 키보드를 프로그래밍 방식으로 열면 OnFocusChangeListener를 호출하지 않으므로 이 프로세스가 작동하지 않습니다.
모든 답변에 감사드립니다. 저는 제 상황에 맞게 이해합니다.
/**
* Add global layout listener to observe system keyboard visibility
*/
private void initObserverForSystemKeyboardVisibility() {
getRootView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//Add your own code here
Log.d("TEST_CODE", "isSystemKeyboardVisible:" + isSystemKeyboardVisible())
}
});
}
/**
* Check system keyboard visibility
* @return true if visible
*/
public boolean isSystemKeyboardVisible() {
try {
final InputMethodManager manager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
final Method windowHeightMethod = InputMethodManager.class.getMethod("getInputMethodWindowVisibleHeight");
final int height = (int) windowHeightMethod.invoke(manager);
return height > 0;
} catch (Exception e) {
return false;
}
}
private fun isKeyboardVisible(rootView: View) =
ViewCompat.getRootWindowInsets(rootView)!!.isVisible(WindowInsetsCompat.Type.ime())
내 경우엔 하나밖에 없었거든요EditText
제 레이아웃을 관리하기 위해서 이 해결책을 생각해 냈습니다.잘 작동합니다. 기본적으로 관습입니다.EditText
포커스가 변경되거나 Back/Done 버튼을 누르면 포커스를 수신하고 로컬 브로드캐스트를 전송합니다.다를 .View
서를 요.android:focusable="true"
그리고.android:focusableInTouchMode="true"
clearFocus()
포커스가 첫 번째 포커스 가능 뷰로 다시 지정됩니다.더미 뷰 예제:
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>
추가정보
레이아웃 변경의 차이를 감지하는 솔루션은 화면 밀도에 따라 크게 달라지기 때문에 잘 작동하지 않습니다. 특정 장치에서는 100px가 많이 나올 수 있고 다른 장치에서는 위양성을 얻을 수 없기 때문입니다.또한 공급업체마다 키보드가 다릅니다.
@bohdan-oliynk의 답변을 바탕으로 조금 더 압축된 Kotlin 버전
private const val KEYBOARD_VISIBLE_THRESHOLD_DP = 100
fun Activity.isKeyboardOpen(): Boolean {
fun convertDpToPx(value: Int): Int =
(value * Resources.getSystem().displayMetrics.density).toInt()
val rootView = findViewById<View>(android.R.id.content)
val visibleThreshold = Rect()
rootView.getWindowVisibleDisplayFrame(visibleThreshold)
val heightDiff = rootView.height - visibleThreshold.height()
val accessibleValue = convertDpToPx(KEYBOARD_VISIBLE_THRESHOLD_DP)
return heightDiff > accessibleValue
}
fun Activity.isKeyboardClosed(): Boolean {
return isKeyboardOpen().not()
}
2023년에 드디어 공식적인 지원이 시작되었습니다!
키보드가 보이는지 확인하려면 다음 작업을 수행합니다.
val insets = ViewCompat.getRootWindowInsets(view) ?: return
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
키보드 가시성의 변화를 들으려면 다음을 수행합니다.
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets ->
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
insets
}
참고: Google은 앱이 제대로 작동하려면 edge to edge를 표시하도록 구성하는 것이 좋습니다.또한 "이 AndroidX 구현과 최상의 하위 호환성을 달성하기 위해 다음과 같이 말합니다.android:windowSoftInputMode="adjustResize"
Android Manifest.xml 의합니다"
안드로이드에서는 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();
}
}
}
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();
}
}
});
않습니다 @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
}
잘 통합니다
이것을 알아낼 수 있는 직접적인 방법이 있습니다.또한 레이아웃 변경이 필요하지 않습니다.
그래서 몰입형 전체 화면 모드에서도 작동합니다.
하지만 안타깝게도 모든 기기에서 작동하지는 않습니다.따라서 장치를 사용하여 테스트해야 합니다.
비결은 소프트 키보드를 숨기거나 보여주고 그 시도의 결과를 캡처하는 것입니다.
올바르게 작동하면 키보드가 실제로 표시되거나 숨겨지지 않습니다.우리는 단지 주를 요청할 뿐입니다.
최신 상태를 유지하려면 핸들러를 사용하여 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;
}
}
};
소프트키보드가 보이는지 확인할 수 있는 방법은 다음과 같습니다.
- ActivityManager.getRunningServices(max_count_of_services)를 사용하여 시스템에서 실행 중인 서비스를 확인합니다.
- 반환된 Activity Manager에서.ServiceInfo 인스턴스를 실행 중이며 clientCount 값에서 소프트 키보드 서비스를 확인합니다.
- 앞에서 설명한 clientCount는 소프트 키보드가 표시될 때마다 증가합니다.예를 들어 clientCount가 처음에 1인 경우 키보드가 표시될 때 2가 됩니다.
- 키보드 해지 시 clientCount가 감소합니다.이 경우 1로 재설정됩니다.
인기 있는 키보드 중 일부는 클래스에 특정 키워드를 가지고 있습니다.이름:
- Google AOSP = IME
- 스와이프 = IME
- 스위프트키 = 키보드 서비스
- Fleksy = 키보드
- Adaptxt = IME(KPTAdaptxTIME)
- Smart = 키보드(스마트 키보드)
ActivityManager에서.RunningServiceInfo 클래스 이름에서 위 패턴을 확인합니다.그리고 활동 매니저.서비스 실행 중키보드가 시스템에 바인딩되어 있음을 나타내는 Info의 clientPackage= android.
위에 언급된 정보들은 소프트 키보드가 보이는지를 알아내기 위한 엄격한 방법으로 결합될 수 있습니다.
코틀린으로 답변을 전환했는데 코틀린 사용자에게 도움이 되었으면 합니다.
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
}
}
}
}
앱에서 안드로이드R용 apis를 지원한다면 아래 방법을 사용할 수 있습니다.
In kotlin :
var imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
view.translationX = imeInsets.bottom
}
참고: 안드로이드 R에서만 사용 가능하며 안드로이드 버전 이하에서는 다른 답변을 따라야 합니다. 그렇지 않으면 업데이트하겠습니다.
adjustNothing 플래그의 활동 및 라이프사이클 이벤트와 함께 작동합니다.코틀린과 함께:
/**
* 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)
}
}
}
전체 보기 경계를 가져오는 위치
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)
}
전체 화면 크기를 얻는 위치
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
}
where 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
}
언급URL : https://stackoverflow.com/questions/4745988/how-do-i-detect-if-software-keyboard-is-visible-on-android-device-or-not
'programing' 카테고리의 다른 글
루비, 레일즈: mysql2 보석, 누가 이 보석을 사용합니까?안정적입니까? (0) | 2023.10.05 |
---|---|
#만약 정의된다면 (x) || (y) ; 이것이 유효합니까? (0) | 2023.10.05 |
워드프레스 미디어 업로더에 컨텍스트 추가 (0) | 2023.10.05 |
함수 자동 로더 (0) | 2023.10.05 |
Powershell: 다른 사용자 이름/비밀번호로 네트워크 드라이브를 매핑하는 방법 (0) | 2023.10.05 |