Android Как настроить макет в полноэкранном режиме, когда видна клавиатура

Я много исследовал, чтобы настроить макет, когда softkeyboard активен, и я успешно его реализовал, но проблема возникает, когда я использую android:theme="@android:style/Theme.NoTitleBar.Fullscreen" это в теге активности в файле манифеста ,

Для этого я использовал android:windowSoftInputMode="adjustPan|adjustResize|stateHidden" с разными параметрами, но не повезло.

После этого я реализовал FullScreen программно и попробовал различные макеты для работы с FullScreen но все напрасно.

Я упомянул эти ссылки и посмотрел много сообщений, связанных с этой проблемой:

http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html

http://davidwparker.com/2011/08/30/android-how-to-float-a-row-above-keyboard/

Вот код xml:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/masterContainerView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ffffff"> <ScrollView android:id="@+id/parentScrollView" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/setup_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Setup - Step 1 of 3" android:textColor="@color/top_header_txt_color" android:textSize="20dp" android:padding="8dp" android:gravity="center_horizontal" /> <TextView android:id="@+id/txt_header" android:layout_width="fill_parent" android:layout_height="40dp" android:text="AutoReply:" android:textColor="@color/top_header_txt_color" android:textSize="14dp" android:textStyle="bold" android:padding="10dp" android:layout_below="@+id/setup_txt" /> <EditText android:id="@+id/edit_message" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Some text here." android:textSize="16dp" android:textColor="@color/setting_editmsg_color" android:padding="10dp" android:minLines="5" android:maxLines="6" android:layout_below="@+id/txt_header" android:gravity="top" android:scrollbars="vertical" android:maxLength="132" /> <ImageView android:id="@+id/image_bottom" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/edit_message" /> </LinearLayout> </ScrollView> <RelativeLayout android:id="@+id/scoringContainerView" android:layout_width="fill_parent" android:layout_height="50px" android:orientation="vertical" android:layout_alignParentBottom="true" android:background="#535254"> <Button android:id="@+id/btn_save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginTop="7dp" android:layout_marginRight="15dp" android:layout_below="@+id/edit_message" android:text = "Save" /> <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="7dp" android:layout_marginRight="10dp" android:layout_below="@+id/edit_message" android:layout_toLeftOf="@+id/btn_save" android:text = "Cancel" /> </RelativeLayout> </RelativeLayout> 

Введите описание изображения здесь

Я хочу, чтобы нижние 2 кнопки поднимались вверх, когда на экран поступает экранная клавиатура.

Введите описание изображения здесь

Solutions Collecting From Web of "Android Как настроить макет в полноэкранном режиме, когда видна клавиатура"

Основываясь на обходном пути yghm, я закодировал класс удобства, который позволяет мне решить проблему с помощью однострочного (конечно, добавив новый класс к исходному коду). Однострочный:

  AndroidBug5497Workaround.assistActivity(this); 

И класс реализации:

 public class AndroidBug5497Workaround { // For more information, see https://code.google.com/p/android/issues/detail?id=5497 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. public static void assistActivity (Activity activity) { new AndroidBug5497Workaround(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } } 

Надеюсь, это поможет кому-то.

Поскольку ответ уже выбран и проблема известна как ошибка, я подумал, что добавлю «Возможная работа вокруг».

Вы можете переключать полноэкранный режим, когда отображается мягкая клавиатура. Это позволяет правильной работе «adjustPan».

Другими словами, я все еще использую @android: style / Theme.Black.NoTitleBar.Fullscreen как часть темы приложения и stateVisible | adjustResize как часть режима мягкого ввода окна активности, но чтобы заставить их работать вместе, я должен переключать полноэкранный режим Перед клавиатурой.

Используйте следующий код:

Выключение полноэкранного режима

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

Включение полноэкранного режима

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 

Примечание – вдохновение исходило из: Скрытие заголовка в полноэкранном режиме

Мне тоже пришлось столкнуться с этой проблемой, и у меня была работа, на которой я проверил HTC one, галактику s1, s2, s3, заметку и ощущение HTC.

Поместите глобальный приемник макета в корневой вид вашего макета

 mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){ public void onGlobalLayout() { checkHeightDifference(); } }); 

И там я проверил разницу в высоте, и если разность высот экрана больше, чем третья на высоте экрана, мы можем предположить, что клавиатура открыта. Взял его из этого ответа .

 private void checkHeightDifference(){ // get screen frame rectangle Rect r = new Rect(); mRootView.getWindowVisibleDisplayFrame(r); // get screen height int screenHeight = mRootView.getRootView().getHeight(); // calculate the height difference int heightDifference = screenHeight - (r.bottom - r.top); // if height difference is different then the last height difference and // is bigger then a third of the screen we can assume the keyboard is open if (heightDifference > screenHeight/3 && heightDifference != mLastHeightDifferece) { // keyboard visiblevisible // get root view layout params FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams(); // set the root view height to screen height minus the height difference lp.height = screenHeight - heightDifference; // call request layout so the changes will take affect .requestLayout(); // save the height difference so we will run this code only when a change occurs. mLastHeightDifferece = heightDifference; } else if (heightDifference != mLastHeightDifferece) { // keyboard hidden PFLog.d("[ChatroomActivity] checkHeightDifference keyboard hidden"); // get root view layout params and reset all the changes we have made when the keyboard opened. FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams(); lp.height = screenHeight; // call request layout so the changes will take affect mRootView.requestLayout(); // save the height difference so we will run this code only when a change occurs. mLastHeightDifferece = heightDifference; } } 

Это, вероятно, не доказательство пули и, возможно, на некоторых устройствах это не сработает, но это сработало для меня и надеюсь, что это тоже поможет.

Используйте только android:windowSoftInputMode="adjustResize|stateHidden когда вы используете AdjustPan, тогда он отключает свойство изменения размера

Чтобы заставить его работать с FullScreen:

Используйте плагин ионной клавиатуры. Это позволяет слушать, когда клавиатура появляется и исчезает.

OnDeviceReady добавить эти прослушиватели событий:

 // Allow Screen to Move Up when Keyboard is Present window.addEventListener('native.keyboardshow', onKeyboardShow); // Reset Screen after Keyboard hides window.addEventListener('native.keyboardhide', onKeyboardHide); 

Логика:

 function onKeyboardShow(e) { // Get Focused Element var thisElement = $(':focus'); // Get input size var i = thisElement.height(); // Get Window Height var h = $(window).height() // Get Keyboard Height var kH = e.keyboardHeight // Get Focused Element Top Offset var eH = thisElement.offset().top; // Top of Input should still be visible (30 = Fixed Header) var vS = h - kH; i = i > vS ? (vS - 30) : i; // Get Difference var diff = (vS - eH - i); if (diff < 0) { var parent = $('.myOuter-xs.myOuter-md'); // Add Padding var marginTop = parseInt(parent.css('marginTop')) + diff - 25; parent.css('marginTop', marginTop + 'px'); } } function onKeyboardHide(e) { // Remove All Style Attributes from Parent Div $('.myOuter-xs.myOuter-md').removeAttr('style'); } й function onKeyboardShow(e) { // Get Focused Element var thisElement = $(':focus'); // Get input size var i = thisElement.height(); // Get Window Height var h = $(window).height() // Get Keyboard Height var kH = e.keyboardHeight // Get Focused Element Top Offset var eH = thisElement.offset().top; // Top of Input should still be visible (30 = Fixed Header) var vS = h - kH; i = i > vS ? (vS - 30) : i; // Get Difference var diff = (vS - eH - i); if (diff < 0) { var parent = $('.myOuter-xs.myOuter-md'); // Add Padding var marginTop = parseInt(parent.css('marginTop')) + diff - 25; parent.css('marginTop', marginTop + 'px'); } } function onKeyboardHide(e) { // Remove All Style Attributes from Parent Div $('.myOuter-xs.myOuter-md').removeAttr('style'); } 

В основном, если они отличаются минусом, то это количество пикселей, которые клавиатура покрывает ваш вход. Поэтому, если вы настроите свой родительский div на это, чтобы противодействовать этому.

Добавление тайм-аутов к логике означает, что 300 мс также должны оптимизировать производительность (поскольку это позволит отображать время клавиатуры.

Я реализовал решение Джозефа Джонсона, и он работал хорошо, я заметил, что после использования этого решения иногда ящик приложения не будет закрываться должным образом. Я добавил функциональность для удаления слушателя removeOnGlobalLayoutListener, когда пользователь закрывает фрагмент, где находятся edittexts.

  //when the application uses full screen theme and the keyboard is shown the content not scrollable! //with this util it will be scrollable once again //http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible public class AndroidBug5497Workaround { private static AndroidBug5497Workaround mInstance = null; private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private ViewTreeObserver.OnGlobalLayoutListener _globalListener; // For more information, see https://code.google.com/p/android/issues/detail?id=5497 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. public static AndroidBug5497Workaround getInstance (Activity activity) { if(mInstance==null) { synchronized (AndroidBug5497Workaround.class) { mInstance = new AndroidBug5497Workaround(activity); } } return mInstance; } private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); _globalListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }; } public void setListener() { mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(_globalListener); } public void removeListener() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mChildOfContent.getViewTreeObserver().removeOnGlobalLayoutListener(_globalListener); } else { mChildOfContent.getViewTreeObserver().removeGlobalOnLayoutListener(_globalListener); } } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } } 

Использует класс, где расположены мои edittexts

 @Override public void onStart() { super.onStart(); AndroidBug5497Workaround.getInstance(getActivity()).setListener(); } @Override public void onStop() { super.onStop(); AndroidBug5497Workaround.getInstance(getActivity()).removeListener(); } слушателя @Override public void onStart() { super.onStart(); AndroidBug5497Workaround.getInstance(getActivity()).setListener(); } @Override public void onStop() { super.onStop(); AndroidBug5497Workaround.getInstance(getActivity()).removeListener(); } 

Обратите внимание android:windowSoftInputMode="adjustResize" не работает, если для активности задано WindowManager.LayoutParams.FLAG_FULLSCREEN . У вас есть два варианта.

  1. Либо отключите полноэкранный режим для вашей деятельности. Активность не изменяется в полноэкранном режиме. Вы можете сделать это либо в xml (путем изменения темы активности), либо в Java-коде. Добавьте следующие строки в свой метод onCreate ().

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);` 

ИЛИ

  1. Используйте альтернативный способ достижения полноэкранного режима. Добавьте следующий код в свой метод onCreate ().

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); View decorView = getWindow().getDecorView(); // Hide the status bar. int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions);` 

Обратите внимание, что метод-2 работает только в Android 4.1 и выше.

Я попробовал решение от Джозефа Джонсона , но, как и другие, я столкнулся с проблемой разрыва между контентом и клавиатурой. Проблема возникает из-за того, что режим мягкого ввода всегда используется для панорамирования при использовании полноэкранного режима. Это панорамирование мешает решению Джозефа, когда вы активируете поле ввода, которое будет скрыто с помощью мягкого ввода.

Когда появляется мягкий вход, содержимое сначала запускается на основе его первоначальной высоты, а затем изменяется по размеру, заданному решением Джозефа. Изменение размера и последующая компоновка не отменят панорамирование, что приводит к разрыву. Полный порядок событий:

  1. Глобалист
  2. Мытье
  3. Макет содержимого (= фактическое изменение размера контента)

Невозможно отключить панорамирование, но можно заставить сдвиг панорамирования быть 0, изменив высоту содержимого. Это можно сделать в слушателе, потому что оно выполняется до начала панорамирования. Установка высоты содержимого на доступную высоту приводит к плавному пользователю, т. Е. Не мерцает.

Я также внес эти изменения. Если какой-либо из этих вопросов возникнет, сообщите мне:

  • Коммутируемое определение доступной высоты для использования getWindowVisibleDisplayFrame . Rect кэшируется, чтобы предотвратить небольшое количество ненужного мусора.
  • Разрешить удалять слушателя. Это полезно при повторном использовании действий для разных фрагментов, имеющих разные полноэкранные требования.
  • Не различайте отображаемую или скрытую клавиатуру, но всегда устанавливайте высоту содержимого на видимую высоту кадра дисплея.

Он был протестирован на Nexus 5 и эмуляторах с уровнями API 16-24 с размерами экрана от крошечного до большого.

Код был перенесен в Kotlin, но перенос моих изменений обратно на Java прост. Дайте мне знать, если вам нужна помощь:

 class AndroidBug5497Workaround constructor(activity: Activity) { private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup private val rootView = contentContainer.getChildAt(0) private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams private val viewTreeObserver = rootView.viewTreeObserver private val listener = { possiblyResizeChildOfContent() } private val contentAreaOfWindowBounds = Rect() private var usableHeightPrevious = 0 // I call this in "onResume()" of my fragment fun addListener() { viewTreeObserver.addOnGlobalLayoutListener(listener) } // I call this in "onPause()" of my fragment fun removeListener() { viewTreeObserver.removeOnGlobalLayoutListener(listener) } private fun possiblyResizeChildOfContent() { contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds) val usableHeightNow = contentAreaOfWindowBounds.height() if (usableHeightNow != usableHeightPrevious) { rootViewLayout.height = usableHeightNow // Change the bounds of the root view to prevent gap between keyboard and content, and top of content positioned above top screen edge. rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom) rootView.requestLayout() usableHeightPrevious = usableHeightNow } } } 

Действительно, внешний вид мягкой клавиатуры, по-видимому, никак не влияет на Activity , независимо от того, какой windowSoftInputMode я выбираю в режиме FullScreen .

Хотя я не мог найти много документации по этому свойству, я думаю, что режим FullScreen был разработан для игрового приложения, которое не требует особого использования мягкой клавиатуры. Если ваш – это действие, которое требует взаимодействия с пользователем с помощью мягкой клавиатуры, передумайте, используя тему не FullScreen. Вы можете отключить TitleBar, используя тему NoTitleBar . Почему вы хотите скрыть панель уведомлений?

Я пробовал класс Джозефа Джонсона, и это сработало, но не вполне соответствовало моим потребностям. Вместо эмуляции android: windowSoftInputMode = "adjustResize", мне нужно было эмулировать android: windowSoftInputMode = "adjustPan".

Я использую это для полноэкранного просмотра. Чтобы панорамировать представление содержимого в нужную позицию, мне нужно использовать интерфейс javascript, который содержит сведения о позиции элемента страницы, который имеет фокус, и, таким образом, получает ввод с клавиатуры. Я опустил эти подробности, но предоставил переписку с классом Джозефа Джонсона. Это обеспечит очень прочную основу для реализации пользовательского панорамирования по сравнению с его изменением размера.

 package some.package.name; import some.package.name.JavaScriptObject; import android.app.Activity; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; //------------------------------------------------------- // ActivityPanner Class // // Convenience class to handle Activity attributes bug. // Use this class instead of windowSoftInputMode="adjustPan". // // To implement, call enable() and pass a reference // to an Activity which already has its content view set. // Example: // setContentView( R.layout.someview ); // ActivityPanner.enable( this ); //------------------------------------------------------- // // Notes: // // The standard method for handling screen panning // when the virtual keyboard appears is to set an activity // attribute in the manifest. // Example: // <activity // ... // android:windowSoftInputMode="adjustPan" // ... > // Unfortunately, this is ignored when using the fullscreen attribute: // android:theme="@android:style/Theme.NoTitleBar.Fullscreen" // //------------------------------------------------------- public class ActivityPanner { private View contentView_; private int priorVisibleHeight_; public static void enable( Activity activity ) { new ActivityPanner( activity ); } private ActivityPanner( Activity activity ) { FrameLayout content = (FrameLayout) activity.findViewById( android.R.id.content ); contentView_ = content.getChildAt( 0 ); contentView_.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { panAsNeeded(); } }); } private void panAsNeeded() { // Get current visible height int currentVisibleHeight = visibleHeight(); // Determine if visible height changed if( currentVisibleHeight != priorVisibleHeight_ ) { // Determine if keyboard visiblity changed int screenHeight = contentView_.getRootView().getHeight(); int coveredHeight = screenHeight - currentVisibleHeight; if( coveredHeight > (screenHeight/4) ) { // Keyboard probably just became visible // Get the current focus elements top & bottom // using a ratio to convert the values // to the native scale. float ratio = (float) screenHeight / viewPortHeight(); int elTop = focusElementTop( ratio ); int elBottom = focusElementBottom( ratio ); // Determine the amount of the focus element covered // by the keyboard int elPixelsCovered = elBottom - currentVisibleHeight; // If any amount is covered if( elPixelsCovered > 0 ) { // Pan by the amount of coverage int panUpPixels = elPixelsCovered; // Prevent panning so much the top of the element // becomes hidden panUpPixels = ( panUpPixels > elTop ? elTop : panUpPixels ); // Prevent panning more than the keyboard height // (which produces an empty gap in the screen) panUpPixels = ( panUpPixels > coveredHeight ? coveredHeight : panUpPixels ); // Pan up contentView_.setY( -panUpPixels ); } } else { // Keyboard probably just became hidden // Reset pan contentView_.setY( 0 ); } // Save usabale height for the next comparison priorVisibleHeight_ = currentVisibleHeight; } } private int visibleHeight() { Rect r = new Rect(); contentView_.getWindowVisibleDisplayFrame( r ); return r.bottom - r.top; } // Customize this as needed... private int viewPortHeight() { return JavaScriptObject.viewPortHeight(); } private int focusElementTop( final float ratio ) { return (int) (ratio * JavaScriptObject.focusElementTop()); } private int focusElementBottom( final float ratio ) { return (int) (ratio * JavaScriptObject.focusElementBottom()); } } 

Просто держите в качестве android:windowSoftInputMode="adjustResize" . Потому что ему дается сохранить только один из "adjustResize" и "adjustPan" (Режим настройки окна задается с помощью либо adjustResize, либо adjustPan. Настоятельно рекомендуется всегда указывать одно или другое). Вы можете найти это здесь: http://developer.android.com/resources/articles/on-screen-inputs.html

Он отлично работает для меня.

Я просто нашел простое и надежное решение, если вы используете подход к системному интерфейсу ( https://developer.android.com/training/system-ui/immersive.html ).

Он работает в том случае, если вы используете View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN , например, если вы используете CoordinatorLayout .

Он не будет работать для WindowManager.LayoutParams.FLAG_FULLSCREEN (тот, который вы также можете задать в теме с помощью android:windowFullscreen ), но вы можете добиться подобного эффекта с помощью SYSTEM_UI_FLAG_LAYOUT_STABLE (который «имеет тот же визуальный эффект» в соответствии с документами ), и это Решение должно работать снова.

 getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION /* If you want to hide navigation */ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE) 

Я тестировал его на своем устройстве, работающем с Marshmallow.

Ключ состоит в том, что мягкие клавиатуры также являются одним из системных окон (например, строка состояния и панель навигации), поэтому WindowInsets отправленные системой, содержат точную и надежную информацию об этом.

В случае использования, например, в DrawerLayout где мы пытаемся DrawerLayout от строки состояния, мы можем создать макет, который игнорирует только верхнюю вставку, и применяет нижнюю вставку, которая учитывает мягкую клавиатуру.

Вот мой пользовательский FrameLayout :

 /** * Implements an effect similar to {@code android:fitsSystemWindows="true"} on Lollipop or higher, * except ignoring the top system window inset. {@code android:fitsSystemWindows="true"} does not * and should not be set on this layout. */ public class FitsSystemWindowsExceptTopFrameLayout extends FrameLayout { public FitsSystemWindowsExceptTopFrameLayout(Context context) { super(context); } public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setPadding(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()); return insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(), 0, 0); } else { return super.onApplyWindowInsets(insets); } } } 

И использовать его:

 <com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Your original layout here --> </com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout> 

Это теоретически должно работать на любом устройстве без безумной модификации, намного лучше, чем любой хак, который пытается использовать случайный 1/3 или 1/4 размер экрана в качестве ссылки.

(Для этого требуется API 16+, но я использую полноэкранный режим только на Lollipop + для рисования за панель состояния, поэтому это лучшее решение в этом случае.)

Вы хотите, чтобы нижняя панель придерживалась нижней части представления, но когда клавиатура отображается, они должны перемещаться вверх, чтобы быть размещены над клавиатурой, правильно?

You can try this code snippet:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...> <RelativeLayout android:id="@+id/RelativeLayoutTopBar" ...> </RelativeLayout> <LinearLayout android:id="@+id/LinearLayoutBottomBar" android:layout_alignParentBottom = true ...> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="390dp" android:orientation="vertical" android:layout_above="@+id/LinearLayoutBottomBar" android:layout_below="@+id/RelativeLayoutTopBar"> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:id="@+id/ScrollViewBackground"> ... </ScrollView> </LinearLayout> </RelativeLayout> 

The BottomBar will stick to the bottom of the view and the LinearLayout containing the ScrollView will take what's left of the view after the top/bottom bar and the keyboard are displayed. Let me know if it works for you as well.

Thank you Joseph for your answer. However, in the method possiblyResizeChildOfContent(), the portion

 else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } 

was not working for me, as the lower portion of view became hidden. So I had to take a global variable restoreHeight, and in the constructor, I inserted the last line

 restoreHeight = frameLayoutParams.height; 

and then I replaced the former mentioned part with

 else { // keyboard probably just became hidden frameLayoutParams.height = restoreHeight; } 

But I have no idea why your code didn't work for me. It would be of great help, if someone can shed light on this.

I was only using full screen mode to hide the status bar. However, I want the app to resize when keyboard is shown. All of the other solutions (likely due to age of post) were complicated or not possible for my use (want to avoid change Java code for sack of PhoneGap Build).

Instead of using Full screen, I modified my configure for Android to be non-fullscreen:

  <preference name="fullscreen" value="false" /> 

And added the cordova-plugin-statusbar , via command line:

 cordova plugin add cordova-plugin-statusbar 

When app has loaded, I simple call a method on the plugin to hide itself, like:

  if (window.cordova && window.cordova.platformId == 'android' && window.StatusBar) window.StatusBar.hide(); 

Это работает как шарм. Only real downside is that the status bar is breifly visible while the app loads. For my needs, that wasn't an issue.

I have tried out all the possible answers from stackOverflow, finally i solved after a week Long search . I have used the coordinate layout and i changed this with linearLayout and my problem is fixed. I dont know possibly the coordinate layout has bugs or anything my mistake.

In my case, this issue started happening once I added Crosswalk to my Cordova application. My app is not used in fullscreen and android:windowSoftInputMode="adjustPan".

I already had the ionic keyboard plugin in the application, so detecting if the keyboard was up or down was easy thanks to it:

 // Listen for events to when the keyboard is opened and closed window.addEventListener("native.keyboardshow", keyboardUp, false); window.addEventListener('native.keyboardhide', keyboardDown, false); function keyboardUp() { $('html').addClass('keyboardUp'); } function keyboardDown() { $('html').removeClass('keyboardUp'); } 

I tried all of the fixes above but the simple line that ended up doing it for me was this bit of css:

 &.keyboardUp { overflow-y: scroll; } 

Hope this saves you the few days I spent on this. 🙂

I used Joseph Johnson created AndroidBug5497Workaround class but getting black space between softkeyboard and the view. I referred this link Greg Ennis . After doing some changes to the above this is my final working code.

  public class SignUpActivity extends Activity { private RelativeLayout rlRootView; // this is my root layout private View rootView; private ViewGroup contentContainer; private ViewTreeObserver viewTreeObserver; private ViewTreeObserver.OnGlobalLayoutListener listener; private Rect contentAreaOfWindowBounds = new Rect(); private FrameLayout.LayoutParams rootViewLayout; private int usableHeightPrevious = 0; private View mDecorView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); mDecorView = getWindow().getDecorView(); contentContainer = (ViewGroup) this.findViewById(android.R.id.content); listener = new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }; rootView = contentContainer.getChildAt(0); rootViewLayout = (FrameLayout.LayoutParams) rootView.getLayoutParams(); rlRootView = (RelativeLayout) findViewById(R.id.rlRootView); rlRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rlRootView.getRootView().getHeight() - rlRootView.getHeight(); if (heightDiff > Util.dpToPx(SignUpActivity.this, 200)) { // if more than 200 dp, it's probably a keyboard... // Logger.info("Soft Key Board ", "Key board is open"); } else { Logger.info("Soft Key Board ", "Key board is CLOSED"); hideSystemUI(); } } }); } // This snippet hides the system bars. protected void hideSystemUI() { // Set the IMMERSIVE flag. // Set the content to appear under the system bars so that the content // doesn't resize when the system bars hide and show. mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } @Override protected void onPause() { super.onPause(); if (viewTreeObserver.isAlive()) { viewTreeObserver.removeOnGlobalLayoutListener(listener); } } @Override protected void onResume() { super.onResume(); if (viewTreeObserver == null || !viewTreeObserver.isAlive()) { viewTreeObserver = rootView.getViewTreeObserver(); } viewTreeObserver.addOnGlobalLayoutListener(listener); } @Override protected void onDestroy() { super.onDestroy(); rootView = null; contentContainer = null; viewTreeObserver = null; } private void possiblyResizeChildOfContent() { contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds); int usableHeightNow = contentAreaOfWindowBounds.height(); if (usableHeightNow != usableHeightPrevious) { rootViewLayout.height = usableHeightNow; rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom); rootView.requestLayout(); usableHeightPrevious = usableHeightNow; } else { this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } } } 

Full screen please use

“`java

 View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions); 

“ `