НОВЫЙ ОТВЕТ добавлено 25 января 2012
С момента написания ответа ниже кто-то рассказал мне о существовании ViewTreeObserver и друзей, API, которые скрывались в SDK начиная с версии 1.
Вместо того, чтобы требовать пользовательский тип макета, гораздо более простое решение состоит в том, чтобы дать корневому представлению вашей деятельности известный идентификатор, скажем @+id/activityRoot
, подключить GlobalLayoutListener к ViewTreeObserver и оттуда вычислить разницу в размерах между корнем представления вашей деятельности и размер окна:
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 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
}
...
}