매우 간단한 작업을 수행해야합니다. 소프트웨어 키보드가 표시되어 있는지 확인하십시오. 이것은 안드로이드에서 가능합니까?
답변
NEW ANSWER 추가 2012 년 1 월 25 일
아래 답변을 작성한 후 누군가가 ViewTreeObserver 와 친구들, 버전 1 이후 SDK에 숨어있는 API가 있음을 알려주었습니다 .
사용자 정의 레이아웃 유형이 필요하지 않고 훨씬 간단한 솔루션은 활동의 루트보기에 알려진 ID를 부여하는 것입니다 @+id/activityRoot
.
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
// ... do something here
}
}
});
다음과 같은 유틸리티 사용
public static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
쉬운!
참고 :
응용 프로그램은 Android Manifest 에서이 플래그를 설정해야합니다. android:windowSoftInputMode="adjustResize"
그렇지 않으면 위의 솔루션이 작동하지 않습니다.
원래 답변
그렇습니다. 가능하지만 그보다 훨씬 어렵습니다.
키보드가 언제 나타나고 사라지는 지에 대해 신경 써야하는 경우 (종종 자주) 내 최상위 레이아웃 클래스를 재정의하는 클래스로 사용자 정의하는 것 onMeasure()
입니다. 기본 논리는 레이아웃이 창의 전체 영역보다 훨씬 적게 채워지면 소프트 키보드가 표시된다는 것입니다.
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;
/*
* LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when
* the soft keyboard is shown and hidden (something Android can't tell you, weirdly).
*/
public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {
public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
}
public interface Listener {
public void onSoftKeyboardShown(boolean isShowing);
}
private Listener listener;
public void setListener(Listener listener) {
this.listener = listener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
Activity activity = (Activity)getContext();
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int diff = (screenHeight - statusBarHeight) - height;
if (listener != null) {
listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
그런 다음 활동 수업에서 …
public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
mainLayout.setListener(this);
...
}
@Override
public void onSoftKeyboardShown(boolean isShowing) {
// do whatever you need to do here
}
...
}
답변
희망적으로 이것은 누군가를 도와줍니다.
Reuben Scratton이 제공 한 새로운 답변은 훌륭하고 효율적이지만 windowSoftInputMode를 adjustResize로 설정 한 경우에만 작동합니다. adjustPan으로 설정 한 경우 코드 스 니펫을 사용하여 키보드가 표시되는지 여부를 여전히 감지 할 수 없습니다. 이 문제를 해결하기 위해 위 코드를 약간 수정했습니다.
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...
... do something here
}
}
});
답변
그것은 컴퓨터의 관점에서 영원히 있었지만이 질문은 여전히 믿을 수 없을 정도로 관련이 있습니다!
그래서 위의 답변을 취하여 조금 조합하고 개선했습니다 …
public interface OnKeyboardVisibilityListener {
void onVisibilityChanged(boolean visible);
}
public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
private boolean wasOpened;
private final int DefaultKeyboardDP = 100;
// From @nathanielwolf answer... Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
private final Rect r = new Rect();
@Override
public void onGlobalLayout() {
// Convert the dp to pixels.
int estimatedKeyboardHeight = (int) TypedValue
.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics());
// Conclude whether the keyboard is shown or not.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
boolean isShown = heightDiff >= estimatedKeyboardHeight;
if (isShown == wasOpened) {
Log.d("Keyboard state", "Ignoring global layout change...");
return;
}
wasOpened = isShown;
listener.onVisibilityChanged(isShown);
}
});
}
나를 위해 작동 🙂
참고 :
당신이 알 경우 DefaultKeyboardDP이 값으로 장치 플레이에 적합하고 값을해야하는지 알고 모두에 대한 소감을 게시하지 않습니다 … 결국 우리는 모든 장치에 맞게 올바른 값을 얻을 것이다!
자세한 내용은 Cyborg 의 구현을 확인하십시오.
답변
죄송 후반 대답을하지만, 나는 누군가가 도움이 찾을 것이라고 할 수있다 통지 청취자 및 기타 유용한 것들과 열기 / 닫기 이벤트를 처리하기 위해 약간의 헬퍼 클래스를 생성했다 :
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import java.util.LinkedList;
import java.util.List;
public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {
public interface SoftKeyboardStateListener {
void onSoftKeyboardOpened(int keyboardHeightInPx);
void onSoftKeyboardClosed();
}
private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
private final View activityRootView;
private int lastSoftKeyboardHeightInPx;
private boolean isSoftKeyboardOpened;
public SoftKeyboardStateWatcher(View activityRootView) {
this(activityRootView, false);
}
public SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
this.activityRootView = activityRootView;
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
final Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
isSoftKeyboardOpened = true;
notifyOnSoftKeyboardOpened(heightDiff);
} else if (isSoftKeyboardOpened && heightDiff < 100) {
isSoftKeyboardOpened = false;
notifyOnSoftKeyboardClosed();
}
}
public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
this.isSoftKeyboardOpened = isSoftKeyboardOpened;
}
public boolean isSoftKeyboardOpened() {
return isSoftKeyboardOpened;
}
/**
* Default value is zero {@code 0}.
*
* @return last saved keyboard height in px
*/
public int getLastSoftKeyboardHeightInPx() {
return lastSoftKeyboardHeightInPx;
}
public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.add(listener);
}
public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
listeners.remove(listener);
}
private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardOpened(keyboardHeightInPx);
}
}
}
private void notifyOnSoftKeyboardClosed() {
for (SoftKeyboardStateListener listener : listeners) {
if (listener != null) {
listener.onSoftKeyboardClosed();
}
}
}
}
사용 예 :
final SoftKeyboardStateWatcher softKeyboardStateWatcher
= new SoftKeyboardStateWatcher(findViewById(R.id.activity_main_layout);
// Add listener
softKeyboardStateWatcher.addSoftKeyboardStateListener(...);
// then just handle callbacks
답변
고밀도 장치에서 소프트 키보드의 가시성을 잘못 감지하지 않도록하기위한 몇 가지 개선 사항 :
-
높이 차이의 임계 값은 128 픽셀이 아니라 128dp 로 정의해야합니다 .
참조 지표 및 그리드에 대한 구글 설계 문서 , 48 DP는 터치 개체에 대한 편안 크기이며, 32 DP는 버튼을 최소이다. 일반 소프트 키보드에는 4 행의 키 버튼이 포함되어야하므로 최소 키보드 높이는 32dp * 4 = 128dp 이어야합니다. 즉, 임계 값 크기는 장치 밀도를 곱하여 픽셀로 전송해야합니다. xxxhdpi 장치 (밀도 4)의 경우 소프트 키보드 높이 임계 값은 128 * 4 = 512 픽셀이어야합니다. -
루트 뷰와 해당 가시 영역의 높이 차이 :
루트 뷰 높이-상태 표시 줄 높이-보이는 프레임 높이 = 루트 뷰 하단-보이는 프레임 하단 (상태 표시 줄 높이는 루트 뷰 표시 프레임의 상단과 동일하므로)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; }
답변
나는 이것을 알아 내기 위해 약간의 시간을 사용했다 … 나는 그것을 CastExceptions를 실행했지만 layout.xml의 LinearLayout을 클래스 이름으로 바꿀 수 있다고 생각했다.
이처럼 :
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMaster">
<com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard android:background="@drawable/metal_background"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:id="@+id/rlMaster" >
<LinearLayout android:layout_width="fill_parent"
android:layout_height="1dip" android:background="@drawable/line"></LinearLayout>
....
</com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard>
</LinearLayout>
이렇게하면 캐스트 문제가 발생하지 않습니다.
… 모든 페이지에서이 작업을 수행하지 않으려면 “Android의 MasterPage”를 사용하는 것이 좋습니다. 여기 링크를 참조하십시오 :
http://jnastase.alner.net/archive/2011/01/08/ldquomaster-pagesrdquo-in-android.aspx
답변
WifiKeyboard와 같은 일부 키보드의 높이는 0이므로 요소의 높이를 확인하는 것은 신뢰할 수 없습니다.
대신 showSoftInput () 및 hideSoftInput ()의 콜백 결과를 사용하여 키보드 상태를 확인할 수 있습니다. 자세한 내용 및 예제 코드
https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android