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

178

Я много исследовал, чтобы настроить макет, когда софт-клавиатура активна, и я успешно реализовал его, но проблема возникает, когда я использую 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 кнопки были направлены вверх, когда на клавиатуре появляется изображение.

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

Винет Шукла
источник
1
Я думаю, что вы должны добавить кнопки внутри ScrollView и ниже EditText.
Баладжи Хадаке
Я уже перепробовал много вариантов, которые не работают ...
Vineet Shukla
1
поместите ваши кнопки в рамку и установите вес рамки в 1 и, наконец, используйте только android:windowSoftInputMode="adjustPan"скажите мне, если это работает ..
Шериф эль-Хатиб
@ VineetShukla Вы нашли какую-нибудь работу с полным экраном?
Мухаммед Бабар
2
Обратите внимание, что вы не должны использовать adjustResizeи adjustPanв то же время, из Javadoc android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: «Это не может быть объединено с {@link SOFT_INPUT_ADJUST_PAN}»
Денис Княжев

Ответы:

257

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

     AndroidBug5497Workaround.assistActivity(this);

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


public class AndroidBug5497Workaround {

    // For more information, see https://issuetracker.google.com/issues/36911528
    // 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);
    }
}

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

Джозеф Джонсон
источник
8
Спасибо! Я понятия не имею , почему, но мне пришлось заменить return (r.bottom - r.top); с , return r.bottomчтобы он работал на моем HTC One Mini, в противном случае вид деятельности будет зайдет слишком высоко по размеру строки состояния. Я еще не проверял это на другом устройстве все же. Надеюсь, что это может помочь.
Джоан
4
Привет Джозеф Джонсон, я использовал твой код, и он работал отлично. Но сейчас на некоторых небольших устройствах возникает проблема, которая показывает разрыв (пустой экран) между клавиатурой и раскладкой. Есть ли у вас идеи по этому вопросу? Я также пытался вернуть r.bottom.
Панкадж
2
Джозеф Джонсон: Я реализовал ваш метод, он отлично работает, когда мы нажимаем на верхний текст редактирования, но когда мы нажимаем на нижний текст редактирования, весь дизайн идет вверх
ранж с
3
К сожалению, он не работает на Nexus 7 (2013). Это все еще сковывает, даже если настройка Adjust не задана.
Ле-Рой Стейнс
4
Отличный ответ, большое спасибо. Он работает на Nexus 6, но вместо использования frameLayoutParams.height = usableHeightSansKeyboard;я должен использовать frameLayoutParams.height = usableHeightNow; Если я этого не делаю, некоторые элементы выпадают за пределы экрана.
РобертоАльенде
37

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

Вы можете включить полноэкранный режим, когда отображается программная клавиатура. Это позволяет корректно работать «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);

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

ЛЕО
источник
1
Я ценю, что вы уделили время проблеме, +1 за это. Я обязательно опробую этот подход и скоро сообщу, сработал ли он для меня, спасибо.
Vineet Shukla
1
Работает как подозревается! Действительно хорошее решение! +1 с моей стороны.
Майк
1
клавиатура щелкает, делая фон клавиатуры черным. Эффект привязки выглядит не очень хорошо :(
nibz
вау, спасибо ... это работает для меня очень хорошо, объединяя обходной путь, упомянутый AndroidBug5497Workaround ... Я загрузил объединенный источник в GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS
23

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

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

  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 = ViewTreeObserver.OnGlobalLayoutListener { 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
        }
    }
}
Йохан Стуйц
источник
9
Это кажется лучшим ответом. Я портировал на Java здесь gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Заметьте, я получал исключения, что наблюдатель не был жив, и должен был это проверить.
Грег Эннис
О Боже! перебирал всю иерархию системных представлений в поисках этого призрачного пространства. Я был близок к тому, чтобы угробить компьютеры для продовольственного грузовика, но видел ваш ответ в последнюю минуту. Это работает :)
rupps
1
@Greg Ennis Спасибо за порт Java. Сэкономили много сил и времени.
Ikun
@GregEnnis, спасибо, ваше решение работает с onResume (), onPause (), onDestroy () (см. Комментарии в коде GitHub).
CoolMind
Это работает для меня, за исключением того, что вызов removeListener, кажется, не работает. Я ставлю точки останова как внутри possiblyResizeChildOfContentвызова, так и в removeListenerвызове, и даже после достижения removeListenerточки останова possiblyResizeChildOfContentвсе еще вызывается. Кто-нибудь еще с этим вопросом?
Куинн
14

Я только что нашел простое и надежное решение, если вы используете системный интерфейс ( 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когда мы пытаемся рисовать за строкой состояния, мы можем создать макет, который игнорирует только верхнюю вставку и применяет нижнюю вставку, которая учитывает программную клавиатуру.

Вот мой обычай 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 + для рисования за строкой состояния, поэтому в этом случае это лучшее решение.)

Хай чжан
источник
@Dilip Работает на API 16+ при условии соблюдения вышеупомянутых условий.
Хай Чжан
10

Обратите внимание, что 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 и выше.

Абхинав Чаухан
источник
@AnshulTyagi method-2 работает только в Android 4.1 и выше.
Абхинав Чаухан
4
Проверено на 5.0 и 4.4.2, Nexus 9 и Samsung s4 соответственно, 2-й способ не работает.
RobVoisey
1
2-й метод просто не работает, и я потратил на это много времени.
Грег Эннис
Спасибо, спаси мой день.
Дени Рохимат
9

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

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

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;
    }
}

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

yghm
источник
1
Требовались некоторые корректировки, но это работало. В Nexus 7 2013 мне пришлось уменьшить высоту клавиатуры (screenHeight / 3) на несколько пикселей. Хорошая идея, спасибо!
Жоао Соуза
7

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

    //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();
}
Visionix Visionix
источник
7

Добавьте android:fitsSystemWindows="true"к макету, и этот макет изменит размер.

Зайн
источник
Вот что решило это для меня. Кроме того, подумайте, убедитесь, что вы установили его на правильный вид. Если у вас есть фон, который должен находиться ниже строки состояния, не устанавливайте его там, а на макете внутри. Вероятно, представления EditText и т. Д. Должны быть внутри этого второго макета внутри. Также посмотрите этот доклад, так как он проясняет ситуацию: youtube.com/watch?v=_mGDMVRO3iE
Стэн
У меня тоже сработало. Благодаря комментарию @Stan я также смог заставить его работать с темой FULLSCREEN, поместив этот атрибут в ViewPager вместо макета действия / фрагмента.
Маркуберти
5

Чтобы заставить его работать с 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');
}

В основном, если разница между ними равна минус, то это количество пикселей, которое клавиатура покрывает вашим вводом. Так что если вы подстроите свой родительский div этим, это должно противодействовать этому.

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

tyler_mitchell
источник
3

Я попробовал класс Джозефа Джонсона, и он работал, но не вполне соответствовал моим потребностям. Вместо того, чтобы эмулировать 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());
    }

}
BuvinJ
источник
кажется, что мне нужно, не могли бы вы добавить полный образец? спасибо за вашу работу!
vilicvane
Я не хотел публиковать весь проект. То, что я предоставил, приведет вас к очень эффективному решению. Что вы должны определить сами: создайте класс «JavaScriptObject» и внедрите его в свое веб-представление в качестве интерфейса js (см. Документацию веб-просмотра для этого). Есть хороший шанс, что вы уже сделали это, если пишете что-то, что использует веб-просмотр всесторонним образом. Добавьте JavaScript в веб-представление для прослушивания событий фокуса и подачи данных в ваш класс JavaScriptObject о позиционировании элемента фокуса.
BuvinJ
2

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

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

Арнаб Чакраборты
источник
2

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

Это прекрасно работает для меня.

Баладжи Хадаке
источник
У меня нет проблем ... Я попробовал и ваш XML. Этот также работает .. я использую версию Os 2.2
Balaji Khadake
Я пробовал только в полноэкранном режиме ... Я тестирую его на своих Nexus One и Nexus S .... Это работает.
Баладжи Хадаке
1
Я пробовал с Galaxy S, HTC Wildfire, HTC Hero, Motorola Deify и Sony XPeria. Не работает ни на одном устройстве.
Vineet Shukla
давайте продолжим это обсуждение в чате
Баладжи Хадаке
2

В настоящее время я использую этот подход, и он работает как шарм. Хитрость в том, что мы получаем высоту клавиатуры из различных методов 21 сверху и снизу, а затем используем ее в качестве нижнего отступа нашего корневого представления в нашей деятельности. Я предположил, что ваш макет не нуждается в верхнем заполнении (идет ниже строки состояния), но если вы это сделаете, сообщите мне, чтобы обновить мой ответ.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RelativeLayout mainLayout = findViewById(R.id.main_layout);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ViewCompat.setOnApplyWindowInsetsListener(mainLayout , new OnApplyWindowInsetsListener() {
                @Override
                public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                    v.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
                    return insets;
                }
            });
        } else {
            View decorView = getWindow().getDecorView();
            final View contentView = mainLayout;
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    Rect r = new Rect();
                    //r will be populated with the coordinates of your view that area still visible.
                    decorView.getWindowVisibleDisplayFrame(r);

                    //get screen height and calculate the difference with the useable area from the r
                    int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                    int diff = height - r.bottom;

                    //if it could be a keyboard add the padding to the view
                    if (diff != 0) {
                        // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                        //check if the padding is 0 (if yes set the padding for the keyboard)
                        if (contentView.getPaddingBottom() != diff) {
                            //set the padding of the contentView for the keyboard
                            contentView.setPadding(0, 0, 0, diff);
                        }
                    } else {
                        //check if the padding is != 0 (if yes reset the padding)
                        if (contentView.getPaddingBottom() != 0) {
                            //reset the padding of the contentView
                            contentView.setPadding(0, 0, 0, 0);
                        }
                    }
                }
            });
        }
    }
...
}

Не забудьте указать свой корневой вид с идентификатором:

activity_main.xml

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

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

Sdghasemi
источник
1
Не могу понять, почему этот ответ до сих пор не в топе. Что у других глюки, вспышки, но этот блестящий, особенно если у вас 5+ api.
Антон Шкуренко
1

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

Мохаммед Ажаруддин Шейх
источник
Я тоже его использовал .... пожалуйста, сделайте так, чтобы вы делали это в полноэкранном режиме и на каком устройстве вы тестируете?
Vineet Shukla
HTC NEXUS один, хорошо, я не могу добавить полный экран
Мохаммед Ажаруддин Шейх
Вы можете использовать getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () вместо использования темы?
Мохаммед Ажаруддин Шейх
10
Приведенный выше код работает нормально без полноэкранного режима, но при добавлении полноэкранного режима из xml или из кода ... Не работает ... Пожалуйста, внимательно прочитайте вопрос.
Vineet Shukla
1

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

 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);
  }
 }
}
Venkat
источник
1

основанный на https://stackoverflow.com/a/19494006/1815624 и желание сделать это ...

обновленная идея


объединяя ответы от

Соответствующий код:

        if (heightDifference > (usableHeightSansKeyboard / 4)) {

            // keyboard probably just became visible
            frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {

            // keyboard probably just became hidden
            if(usableHeightPrevious != 0) {
                frameLayoutParams.height = usableHeightSansKeyboard;
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

            }

Полный источник на https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

старая идея

Создайте статическое значение высоты контейнеров перед открытием клавиатуры. Установите высоту контейнера в зависимости от того, usableHeightSansKeyboard - heightDifferenceкогда клавиатура открывается, и установите ее обратно в сохраненное значение, когда она закрывается.

if (heightDifference > (usableHeightSansKeyboard / 4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                int mStatusHeight = getStatusBarHeight();
                frameLayoutParams.topMargin = mStatusHeight;
                ((MainActivity)activity).setMyMainHeight(usableHeightSansKeyboard - heightDifference);

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became visible");
                }
            } else {
                // keyboard probably just became hidden
                if(usableHeightPrevious != 0) {
                    frameLayoutParams.height = usableHeightSansKeyboard;
                    ((MainActivity)activity).setMyMainHeight();    
                }
                frameLayoutParams.topMargin = 0;

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became hidden");
                }
            }

Методы в MainActivity

public void setMyMainHeight(final int myMainHeight) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = myMainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

int mainHeight = 0;
public void setMyMainHeight() {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = mainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

Пример контейнера XML

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
        <android.support.constraint.ConstraintLayout
            android:id="@+id/my_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintHeight_percent=".8">

Аналогичным образом можно добавить поля при необходимости ...

Другим соображением является использование padding. Пример этого можно найти по адресу:

https://github.com/mikepenz/MaterialDrawer/issues/95#issuecomment-80519589

CrandellWS
источник
1

1) Создать KeyboardHeightHelper:

public class KeyboardHeightHelper {

    private final View decorView;
    private int lastKeyboardHeight = -1;

    public KeyboardHeightHelper(Activity activity, View activityRootView, OnKeyboardHeightChangeListener listener) {
        this.decorView = activity.getWindow().getDecorView();
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            int keyboardHeight = getKeyboardHeight();
            if (lastKeyboardHeight != keyboardHeight) {
                lastKeyboardHeight = keyboardHeight;
                listener.onKeyboardHeightChange(keyboardHeight);
            }
        });
    }

    private int getKeyboardHeight() {
        Rect rect = new Rect();
        decorView.getWindowVisibleDisplayFrame(rect);
        return decorView.getHeight() - rect.bottom;
    }

    public interface OnKeyboardHeightChangeListener {
        void onKeyboardHeightChange(int keyboardHeight);
    }
}

2) Пусть ваша деятельность будет на весь экран:

activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

3) Прослушайте изменения высоты клавиатуры и добавьте нижний отступ для вашего вида:

View rootView = activity.findViewById(R.id.root); // your root view or any other you want to resize
KeyboardHeightHelper effectiveHeightHelper = new KeyboardHeightHelper(
        activity, 
        rootView,
        keyboardHeight -> rootView.setPadding(0, 0, 0, keyboardHeight));

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

repitch
источник
0

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

Вы можете попробовать этот фрагмент кода:

<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>

BottomBar будет придерживаться нижней части представления, а LinearLayout, содержащий ScrollView, займет то, что осталось от представления после отображения верхней / нижней панели и клавиатуры. Дайте мне знать, если это работает и для вас.

banzai86
источник
1
Очень странно, поскольку это работало в моих приложениях несколько раз. Кстати, RelativeLayout не имеет ориентации, поэтому вы можете удалить эти атрибуты в своем коде. Я только что узнал, что мог бы сократить фрагмент кода до строки: android: layout_below = "@ + id / scoringContainerView", которую вы должны добавить в свой ScrollView
banzai86
Полноэкранный? Вы имеете в виду без макета вверху?
banzai86
нет ..... я имею в виду отсутствие строки состояния, которая показывает время автономной работы, подключения для устройства и т. д ....
Vineet Shukla
нет, строка состояния отображается в моем приложении. Можете ли вы попробовать изменить порядок ваших макетов, то есть вы поместите код для своего макета с помощью кнопок над другим кодом, а затем повторите попытку? может быть, вы должны сначала определить их, чтобы использовать layout_below
banzai86
1
Пожалуйста, внимательно прочитайте вопрос ...... Я уже упоминал, что у меня проблемы с полноэкранным режимом ......
Vineet Shukla
0

Спасибо, Джозеф, за твой ответ. Тем не менее, в методе возможно ResizeChildOfContent (), часть

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

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

restoreHeight = frameLayoutParams.height;

а затем я заменил ранее упомянутую часть

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

Но я понятия не имею, почему ваш код не работает для меня. Было бы очень полезно, если бы кто-то мог пролить свет на это.

Debanjan
источник
0

Я только использовал полноэкранный режим, чтобы скрыть строку состояния. Тем не менее, я хочу, чтобы приложение изменило размеры при отображении клавиатуры. Все другие решения (вероятно, из-за возраста должности) были сложными или невозможными для моего использования (хочу избежать изменения кода Java для мешка PhoneGap Build).

Вместо использования полноэкранного режима я изменил конфигурацию для Android, чтобы она не была полноэкранной:

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

И добавил cordova-plugin-statusbarчерез командную строку:

cordova plugin add cordova-plugin-statusbar

Когда приложение загрузилось, я просто вызываю метод на плагине, чтобы скрыть себя, например:

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

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

raider33
источник
0

Я опробовал все возможные ответы от stackOverflow, наконец, я решил после недельного долгого поиска. Я использовал расположение координат, и я изменил это с помощью linearLayout, и моя проблема исправлена. Я не знаю, возможно, в координатной компоновке есть ошибки или что-то еще, моя ошибка.

Юбарадж Пудель
источник
0

Я испробовал множество решений, в том числе Джозефа Джонсона и Йохана Стейтса. Но в результате я получил пробел между контентом и клавиатурой на некоторых устройствах (например, Lenovo s820) во всех случаях. Поэтому я внес некоторые изменения в их коды и, наконец, получил рабочее решение.

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

contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
    int usableHeightNow = contentAreaOfWindowBounds.height();

    if (usableHeightNow != usableHeightPrevious) {

        int difference = usableHeightNow - usableHeightPrevious;

        if (difference < 0 && difference < -150) {
            keyboardShowed = true;
            rootViewLayout.topMargin -= difference + 30;
            rootViewLayout.bottomMargin += 30;
        }
        else if (difference < 0 && difference > -150){
            rootViewLayout.topMargin -= difference + 30;
        }
        else if (difference > 0 && difference > 150) {
            keyboardShowed = false;
            rootViewLayout.topMargin = 0;
            rootViewLayout.bottomMargin = 0;
        }

        rootView.requestLayout();

        Log.e("Bug Workaround", "Difference: " + difference);

        usableHeightPrevious = usableHeightNow;
}

Как видите, я добавляю 30 px к разнице, потому что между верхней частью экрана и областью содержимого с полем есть небольшое белое пространство. И я не знаю, откуда это появляется, поэтому я решил просто уменьшить поля, и теперь все работает именно так, как мне нужно.

IDmikael
источник
0

Сегодня не работает AdjustResize на полноэкранном режиме, проблема актуальна для Android SDK.

Из ответов, которые я нашел:
решение - но решение показывает это на изображении:

Затем я нашел решение и удалил одно ненужное действие:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Итак, посмотрите мой фиксированный код решения на Kotlin:

class AndroidBug5497Workaround constructor(val activity: Activity) {

    private val content = activity.findViewById<View>(android.R.id.content) as FrameLayout

    private val mChildOfContent = content.getChildAt(0)
    private var usableHeightPrevious: Int = 0
    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 listener = {
        possiblyResizeChildOfContent()
    }

    fun addListener() {
        mChildOfContent.apply {
            viewTreeObserver.addOnGlobalLayoutListener(listener)

        }
    }

    fun removeListener() {
        mChildOfContent.apply {
            viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }
    }

    private fun possiblyResizeChildOfContent() {
        val contentAreaOfWindowBounds = Rect()
        mChildOfContent.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
        val usableHeightNow = contentAreaOfWindowBounds.height()

        if (usableHeightNow != usableHeightPrevious) {
            rootViewLayout.height = usableHeightNow
            rootView.layout(contentAreaOfWindowBounds.left,
                    contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
            mChildOfContent.requestLayout()
            usableHeightPrevious = usableHeightNow
        }
    }
}

Мой код для исправления ошибок:

 class LeaveDetailActivity : BaseActivity(){

    private val keyBoardBugWorkaround by lazy {
        AndroidBug5497Workaround(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    override fun onResume() {
        keyBoardBugWorkaround.addListener()
        super.onResume()
    }

    override fun onPause() {
        keyBoardBugWorkaround.removeListener()
        super.onPause()
    }
}
Серг Бурлака
источник
0

Не используйте:

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

потому что работает плохо. Вместо этого используйте:

fun setFullScreen(fullScreen: Boolean) {
        val decorView = getWindow().getDecorView()
        val uiOptions : Int
        if(fullScreen){
            uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN // this hide statusBar
            toolbar.visibility = View.GONE // if you use toolbar
            tabs.visibility = View.GONE // if you use tabLayout
        } else {
            uiOptions = View.SYSTEM_UI_FLAG_VISIBLE // this show statusBar
            toolbar.visibility = View.VISIBLE
            tabs.visibility = View.VISIBLE
        }
        decorView.setSystemUiVisibility(uiOptions)
    }
Alberto
источник
-1

В моем случае эта проблема начала возникать, когда я добавил Crosswalk в свое приложение Cordova. Мое приложение не используется в полноэкранном режиме и Android: windowSoftInputMode = "AdjustPan".

У меня уже был плагин для ионной клавиатуры в приложении, поэтому определить, была ли клавиатура вверх или вниз, было легко благодаря этому:

// 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');
}

Я перепробовал все вышеперечисленные исправления, но простой строкой, которая в итоге сделала это для меня, было следующее: css:

&.keyboardUp {
        overflow-y: scroll;
}

Надеюсь, это спасет вас от нескольких дней, которые я потратил на это. :)

JR
источник
Я использую переход с Cordova, а также с Android: windowSoftInputMode = "AdjustPan". Тем не менее, это не работает. Я вижу, что класс добавляется в элемент HTML, но CSS не влияет на экран. Есть ли у вас другие настройки, позволяющие перемещать экран?
darewreck
Я должен установить add transform: translateY (0px), чтобы он работал. Тем не менее, прокрутка не работает вообще. Любые идеи?
darewreck