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"скажіть мені, чи це працює ..
Шериф elKhatib

@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
Джозеф Джонсон: Я реалізував ваш метод, він працює добре, коли ми натискаємо верхній текст редагування, але коли ми натискаємо на нижній текст редагування, весь дизайн іде вгору
ranjith

3
На жаль, він не працює на Nexus 7 (2013). Він все ще працює, навіть якщо встановити налаштування нічого.
Ле-рой Стайнс

4
Дивовижна відповідь, дуже дякую. Він працює на Nexus 6, але замість того, щоб використовувати, frameLayoutParams.height = usableHeightSansKeyboard;я повинен використовувати, frameLayoutParams.height = usableHeightNow; якщо я цього не роблю, деякі елементи потрапляють поза екран.
РобертоАлленде

37

Оскільки відповідь вже була підібрана і проблема, яка була помилкою, я подумав, що я додам "Можливу роботу".

Ви можете переключити режим повноекранного режиму, коли відображається м'яка клавіатура. Це дозволяє коректувати "customPan" правильно.

Іншими словами, я все ще використовую @android: style / Theme.Black.NoTitleBar.Fullscreen як частину теми програми та stateVisible | prilagodResize як частина режиму вводу вікна активності, але щоб змусити їх працювати разом, я повинен переключити режим повноекранного режиму до появи клавіатури

Використовуйте наступний код:

Вимкнення повноекранного режиму

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
клавіатура оснащується, роблячи фон клавіатури чорним. Ефект
оснащення

вау спасибі ... це працює для мене дуже добре, комбінуючи Обхід згадується AndroidBug5497Workaround ... Я завантажив комбінований джерело GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master / ...
CrandellWS

23

Я спробував рішення від Джозефа Джонсона , але, як і інші, я зіткнувся з розривом між змістом і клавіатурою. Проблема виникає тому , що режим м'якого введення завжди панорамування при використанні повноекранного режиму. Це панорамування перешкоджає вирішенню Джозефа, коли ви активуєте поле введення, яке було б приховано м'яким входом.

Коли з'являється м'який вхід, вміст спочатку панорумується виходячи з його початкової висоти, а потім змінюється розмір відповідно до макета, який вимагає рішення Йосифа. Змінення розміру та подальший макет не скасовують панорамування, що призводить до розриву. Повний порядок подій:

  1. Слухач глобального планування
  2. Панорамування
  3. Макет вмісту (= фактична зміна змісту)

Не можна відключити панорамування, але можливо змусити зміщення панорами до 0, змінивши висоту вмісту. Це можна зробити у слухача, оскільки він виконується до того, як відбудеться панорамування. Встановлення висоти вмісту на доступну висоту призводить до плавного досвіду користувача, тобто не мерехтіння.

Я також вніс ці зміни. Якщо будь-який із цих питань вводить проблеми, дайте мені знати:

  • Вимкнене визначення доступної висоти для використання getWindowVisibleDisplayFrame. Це Rectсховане в кешованому режимі, щоб запобігти небагато зайвого сміття.
  • Дозвольте видалити слухача також. Це корисно, коли ви повторно використовуєте діяльність для різних фрагментів, що мають різні вимоги на весь екран.
  • Не розрізняйте клавіатуру, показану чи приховану, але завжди встановлюйте висоту вмісту на видиму висоту кадру дисплея.

Він був протестований на Nexus 5 та емуляторах, що працюють на рівнях API 16-24, розміри екрана - від крихітних до великих.

Код був перенесений на Котлін, але перенесення моїх змін на 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. Економили багато сил та часу.
Ікун

@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
Другий метод просто не працює, і я витратив на це багато часу.
Грег Енніс

Дякую, врятуй мій день.
Дені Рохімат

9

Мені довелося зіткнутися і з цією проблемою, і я провів роботу, навколо якої я перевірив HTC один, галактику s1, s2, s3, note та 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;
    }
}

це, мабуть, не є кулезахисним, і, можливо, на деяких пристроях він не працюватиме, але він працював на мене, і сподіваюся, він теж допоможе вам.


1
Потрібні були деякі корективи, але це спрацювало. У Nexus 7 2013 мені довелося зменшити висоту клавіатури (screenHeight / 3) на деякі пікселі. Гарна ідея, дякую!
Жоао Суса

7

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

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

використовує клас, де знаходяться мої редакційні тексти

@Override
public void onStart()
{
    super.onStart();
    AndroidBug5497Workaround.getInstance(getActivity()).setListener();
}

@Override
public void onStop()
{
    super.onStop();
    AndroidBug5497Workaround.getInstance(getActivity()).removeListener();
}

7

Додайте android:fitsSystemWindows="true"до макета, і цей макет змінить розмір.


Ось що це вирішило для мене. Крім того, подумайте, переконайтеся, що ви встановили його в потрібному вигляді. Якщо у вас фон, який повинен знаходитися нижче рядка стану, не встановлюйте його там, а на макеті всередині. Ймовірно, перегляди EditText тощо повинні знаходитися всередині другого макета всередині. Також дивіться цю розмову, оскільки вона робить все більш зрозумілим: youtube.com/watch?v=_mGDMVRO3iE
Стан

Працював і для мене. Завдяки коментарю @Stan, я також зміг змусити його працювати з темою FULLSCREEN, розміщуючи цей атрибут на ViewPager замість макета діяльності / фрагмента.
marcouberti

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

В основному, якщо їх різниця мінус, то це кількість пікселів, яку клавіатура покриває вашим входом. Тож якщо ви налаштуєте свій батьківський дів на це, це має протидіяти цьому.

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


3

Я спробував клас Джозефа Джонсона, і він спрацював, але не зовсім відповідав моїм потребам. Замість того, щоб наслідувати android: windowSoftInputMode = "prilagodResize", мені потрібно було емулювати android: windowSoftInputMode = "коригуватиPan".

Я використовую це для повноекранного перегляду веб-сторінок. Щоб змінити перегляд вмісту на правильне положення, мені потрібно використовувати інтерфейс 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());
    }

}

здається, що мені потрібно, чи не могли б ви додати повний зразок? дякую за вашу роботу!
vilicvane

Я не хотів публікувати весь проект. Я запропонував вам дуже довгий шлях, але до ідеально працюючого рішення. Що потрібно визначити самому: Створіть клас "JavaScriptObject" та вставте його у свій веб-перегляд у вигляді js-інтерфейсу (Перевірте це на документацію веб-перегляду). Ви вже добре зробили це, якщо написати щось, що використовує веб-перегляд всебічно. Додайте JavaScript у веб-перегляд, щоб слухати події фокусування та подавати дані у свій клас JavaScriptObject про розміщення елементів фокусу.
BuvinJ

2

Дійсно, зовнішній вигляд м’якої клавіатури нічим не впливає на Activityте, що windowSoftInputModeя вибираю в FullScreenрежимі.

Хоча я не міг знайти багато документації щодо цього властивості, я думаю, що FullScreenрежим був розроблений для ігрових додатків, які не потребують великого використання м'якої клавіатури. Якщо ваша - це діяльність, яка вимагає взаємодії з користувачем через м'яку клавіатуру, будь ласка, перегляньте, використовуючи тему, що не є повноекранною. Ви можете вимкнути TitleBar за допомогою NoTitleBarтеми. Чому ви хочете приховати панель сповіщень?


2

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

Це прекрасно працює для мене.


У мене не виникає жодних проблем ... Я також спробував ваш XML. Цей також працює. Я використовую ОС версії 2.2
Баладжі Хадаке

Я спробував лише в повноекранному режимі ... тестую його на своїх 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">

Сподіваюся, це комусь допоможе.


1
Не можу зрозуміти, чому ця відповідь досі не вгорі. Що інші ті глючать, спалахують, але цей - блискучий, особливо якщо у вас є 5+ апі.
Антон Шкуренко

1

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


Я також його використав .... будь ласка, змусьте це робити у повноекранному режимі та на якому пристрої ви тестуєте?
Vineet Shukla

HTC NEXUS one, нормально, я додаю повний екран
Mohammed Azharuddin Shaikh

чи можете ви використовувати 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);
  }
 }
}

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

аналогічно поля можуть бути додані за потреби ...

Інший розгляд - використання прокладки, приклад цього можна знайти за адресою:

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


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

Отже , щоразу, коли клавіатура з’явиться на екрані - нижня підкладка для вашого перегляду буде змінюватися, а вміст буде переставлено.


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, візьме те, що залишилося від подання після відображення верхньої / нижньої панелі та клавіатури. Дайте мені знати, чи працює він і для вас.


1
Дуже дивно, як це працювало в моїх додатках кілька разів. До речі, RelativeLayout не має орієнтації, тому ви можете видалити ці атрибути у своєму коді. Я щойно визнав, що міг би вирізати фрагмент коду до рядка: android: layout_below = "@ + id / scoringContainerView", який потрібно додати до свого ScrollView
banzai86

Повноекранний? Ви маєте на увазі без макету вгорі?
banzai86

ні ... я маю на увазі відсутність рядка стану, на якому відображатиметься час роботи акумулятора, підключення до пристрою тощо ....
Vineet Shukla,

ні, панель стану відображається в моєму додатку. чи можете ви спробувати змінити порядок своїх макетів, це означає, що ви кладете код для свого макета кнопками над іншим кодом, а потім спробуйте ще раз? можливо, вам доведеться спочатку їх визначити, щоб скористатися layout_below
banzai86

1
будь ласка, уважно прочитайте питання ...... Я вже згадував, що у мене проблеми з режимом
повноекранного

0

Дякую Джозефу за вашу відповідь. Однак у методі можливоResizeChildOfContent (), частина

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

не працювало для мене, оскільки нижня частина зору стала прихованою. Тому мені довелося взяти глобальну змінну RestoHeight, і в конструктор я вставив останній рядок

restoreHeight = frameLayoutParams.height;

а потім я замінив колишню згадану частину на

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

Але я поняття не маю, чому ваш код не працював для мене. Було б дуже корисно, якщо хтось може пролити світло на це.


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();

Це працює як шарм. Єдиним недоліком є ​​те, що рядок стану відображається під час завантаження програми. Для моїх потреб це не було проблемою.


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 пікселів до різниці, оскільки між вершиною екрана та зоною вмісту з полем є невеликий пробіл. І я не знаю, звідки це з'являється, тому я вирішив просто зменшити націнки, і тепер він працює саме так, як мені потрібно.


0

Сьогодні не працює налаштуванняResize у повноекранному питанні актуально для 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)
    }

-1

У моєму випадку ця проблема почалася, коли я додав Crosswalk до своєї програми Кордова. Моя програма не використовується в повноекранному режимі та андроїді: windowSoftInputMode = "коригуватиPan".

У мене в додатку вже був плагін іонної клавіатури, тому виявити, чи була клавіатура вгору чи вниз, завдяки їй було легко:

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

Сподіваюся, це заощадить вам кілька днів, які я витратив на це. :)


Я використовую кросворд з cordova, а також з android: windowSoftInputMode = "prilagodPan". Однак це не працює. Я бачу, що клас додається до html-елемента, але css не впливає на екран. Чи є у вас інші налаштування, які дозволяють переміщувати екран?
сміття

Мені потрібно встановити перетворення add: translateY (0px), щоб воно працювало. Однак прокрутка зовсім не працює. Будь-які ідеї?
сміливість
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.