Как нарисовать вид поверх мягкой клавиатуры, например, WhatsApp?

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

образец изображения

Кто-нибудь знает, как добиться такого поведения?

8 ответов

Ну, я создал образец клавиатуры для чата здесь...

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

// Initially defining default height of keyboard which is equal to 230 dip
        final float popUpheight = getResources().getDimension(
                R.dimen.keyboard_height);
        changeKeyboardHeight((int) popUpheight);

// Creating a pop window for emoticons keyboard
    popupWindow = new PopupWindow(popUpView, LayoutParams.MATCH_PARENT,
            (int) keyboardHeight, false);

и высота рассчитывается с помощью этой функции:

/**
 * Checking keyboard height and keyboard visibility
 */
int previousHeightDiffrence = 0;
private void checkKeyboardHeight(final View parentLayout) {

    parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {

                    Rect r = new Rect();
                    parentLayout.getWindowVisibleDisplayFrame(r);

                    int screenHeight = parentLayout.getRootView()
                            .getHeight();
                    int heightDifference = screenHeight - (r.bottom);

                    if (previousHeightDiffrence - heightDifference > 50) {                          
                        popupWindow.dismiss();
                    }

                    previousHeightDiffrence = heightDifference;
                    if (heightDifference > 100) {

                        isKeyBoardVisible = true;
                        changeKeyboardHeight(heightDifference);

                    } else {

                        isKeyBoardVisible = false;

                    }

                }
            });

}

Используя все эти вещи, я могу сделать идеальную клавиатуру с перекрытием....

Затем я надуваю всплывающее окно с viewpager и gridview для смайликов.

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

После долгих исследований и проб и ошибок я нашел другое решение, похожее на приведенное выше Chirag Jain, но с использованием собственного диалога.

    mDialogKeyboard = new Dialog(this,android.R.style.Theme_NoTitleBar);
    mDialogKeyboard.setContentView(R.layout.your_custom_layout);
    mDialogKeyboard.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
    mDialogKeyboard.getWindow().setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
    mDialogKeyboard.getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    mDialogKeyboard.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

    WindowManager.LayoutParams lp=mDialogKeyboard.getWindow().getAttributes();    
    lp.width=WindowManager.LayoutParams.MATCH_PARENT;
    lp.height=mSoftKeyboardHeight;
    lp.gravity=Gravity.BOTTOM | Gravity.LEFT;
    lp.dimAmount=0;

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

Я застрял на той же проблеме. Мне наконец удалось решить эту проблему, используя PopupWindow поверх программной клавиатуры. Я загрузил свое решение в виде проекта на github: https://github.com/ankushsachdeva/emojicon

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

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

Если вы все еще хотите продолжить, вот как вы рисуете "окно" поверх других приложений. Это должны быть параметры макета.

params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSLUCENT);

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

Если я неправильно понял вопрос, поправьте меня.

Я думаю, что они создали свою собственную клавиатуру для улыбок, и по щелчку значка улыбки или значка клавиатуры они скрывают клавиатуру улыбки и показывают обычную клавиатуру. в случае приложения Whats есть два сценария: 1) если вы не фокусируете 1-й раз при редактировании текста, то вы не можете видеть кнопку показа клавиатуры, а высота клавиатуры улыбки точно такая же, как у обычной клавиатуры, мы получим только высоту клавиатуры после того, как изменилось расположение нашего вида, это означает, что только после того, как клавиатура показана, это означает, что они создают свою собственную клавиатуру. 2) Если вы сфокусируете текст редактирования и нажмете кнопку улыбки, то появится опция показа кнопки клавиатуры. Пожалуйста, исправьте меня если я не прав в этом

@jirkarrr, почему бы вам не добавить keyboardInfoContainer следующим образом:

WindowManager wm = getWindowManager();
WindowManager.LayoutParams lps = new WindowManager.LayoutParams();
lps.x = 0; lps.y = keyboardHeight;
wm.addView(keyboardInfoContainer, lps);

Я делаю как твой код, но он не может показать клавиатура InfoContainer.

Я использую всплывающее окно, чтобы поместить вид на клавиатуру:

public void showPopUpKeyboard() {
        mIsPopupVisible = true;
        // Initialize a new instance of LayoutInflater service
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

        // Inflate the custom layout/view
        View customView = inflater.inflate(R.layout.popup_in_keyboard, null);


        mScrollView = (ScrollView) customView.findViewById(R.id.keyboard_layout_view);
        // Initialize a new instance of popup window
        mPopupWindow = new PopupWindow(
                customView,
                RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.MATCH_PARENT
        );


        setSizeForSoftKeyboard();

        // Get a reference for the custom view close button
        Button closeButton = (Button) customView.findViewById(R.id.ib_close);

        // Set a click listener for the popup window close button
        closeButton.setOnClickListener((View view) -> {
                // Dismiss the popup window
                mIsPopupVisible = false;
                mPopupWindow.dismiss();
        });
        mPopupWindow.showAtLocation(mParentLayout, Gravity.CENTER, 0, 0);

    }

Затем я пытаюсь узнать высоту клавиатуры:

mParentLayout.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
                Rect r = new Rect();

                mParentLayout.getWindowVisibleDisplayFrame(r);

                int heightDiff = mParentLayout.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) {
                    //enter your code here
                    if (mIsPopupVisible) {
                        keepKeyboard();
                        mIsPopupVisible = false;
                        mPopupWindow.dismiss();
                    }
                } else {
                    //enter code for hid
                }
        }); 

Вы можете проверить этот учебник и этот пример в GitHub

Недавно мне пришлось реализовать вид, который будет выше мягкой клавиатуры. Решение @Chirag Jain почти правильное, но оно не учитывает системные кнопки в нижней части экрана! Это приведет к неправильной высоте клавиатуры на некоторых устройствах, таких как NEXUS 6. Это решение должно работать на всех устройствах:

1) создать макет, который содержит ваш вид

<RelativeLayout
        android:id="@+id/keyboard_info_container"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true"
        android:background="@color/C12"
        android:padding="10dp"
        android:visibility="invisible">

           ....

    </RelativeLayout>

2) Bind view

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootview = inflater.inflate(R.layout.notifications_email_settings_fragment, container, false);

    ButterKnife.bind(this, rootview);

    checkKeyboardHeight(rootview);

3) проверка клавиатуры и просмотр настроек полей

private void checkKeyboardHeight(final View parentLayout) {

    parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {

                int previousHeightDiffrence = 0;
                int systemBarHigh = 999999;

                @Override
                public void onGlobalLayout() {


                    Rect r = new Rect();
                    parentLayout.getWindowVisibleDisplayFrame(r);

                    int screenHeight = parentLayout.getRootView()
                            .getHeight();
                    int keyboardHeight = screenHeight - (r.bottom);

                    if(systemBarHigh > keyboardHeight) {
                        systemBarHigh = keyboardHeight;
                    }

                    if (keyboardHeight > 250) {

                        int keyboardHightWithoutSystemBar = keyboardHeight - systemBarHigh;
                        // no need to update when the keyboard goes down
                        if (previousHeightDiffrence != keyboardHightWithoutSystemBar) { // if (Math.abs(previousHeightDiffrence - keyboardHeight) > 10) {
                            adjustKeyboard(keyboardHightWithoutSystemBar);
                        }

                        keyboardInfoContainer.setVisibility(View.VISIBLE);
                        isKeyBoardVisible = true;
                        previousHeightDiffrence = keyboardHightWithoutSystemBar;

                    } else {
                        isKeyBoardVisible = false;
                        if (keyboardInfoContainer != null) {
                            keyboardInfoContainer.setVisibility(View.INVISIBLE);
                        }
                    }
                }
            });
}

private void adjustKeyboard(int keyboardHeight) {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) keyboardInfoContainer.getLayoutParams();
    lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
    lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    lp.bottomMargin = keyboardHeight;
    keyboardInfoContainer.requestLayout();
}
Другие вопросы по тегам