35

I want to know how it's possible to add View on top of Keyboard like WhatsApp and Hangout. In chat screen, they insert emoticons view on top of the opened soft keyboard.

sample image

Does anyone know how to achieve this behavior?

Andrew T.
  • 4,701
  • 8
  • 43
  • 62
and_dev
  • 1,483
  • 3
  • 14
  • 17
  • 1
    I don't think that's what happens in WhatsApp. Clicking the emoticons button only dismisses the soft keyboard and opens the smiley fragment, I guess. – Karthik Balakrishnan Apr 17 '13 at 12:59
  • 1
    it's not dismisses the keyboard for my understanding i think it's draw on top the open keyboard – and_dev Apr 17 '13 at 13:33
  • see these http://androidjayavelu.blogspot.in/2011/12/android-imf-is-designed-to-support.html and http://tutorials-android.blogspot.in/2011/06/create-your-own-custom-keyboard-for.html – Chintan Rathod Apr 17 '13 at 13:48
  • 1
    it's tutorial on how to create your own keyboard, it's not what am looking for – and_dev Apr 17 '13 at 14:02
  • I am doing something similar HERE!!! http://stackoverflow.com/questions/16768930/implementations-of-emoji-emoticon-view-keyboard-layouts – Etienne Lawlor May 27 '13 at 16:55
  • 2
    I can confirm that it doesn't dismiss soft keyboard and instead just draw on top of that perfectly. You can see the notification that the input method is still active while opening the emoticons view. – Andrew T. Jul 04 '14 at 01:13

7 Answers7

21

Well, I have created a sample keyboard for chatting here...

Here, I use popup window for showing popup window and height of popup is calculated dynamically by height of keyboard

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

and height is calculated using this function :

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

                    }

                }
            });

}

Using all these stuff i am able to make a perfect overlapping keyboard....

then i inflate popup window with viewpager and gridview for emoticons.

Also, i use spannable string for showing these emoticons in listview and chat window

Chirag Jain
  • 1,612
  • 13
  • 20
  • I'm interested to see how your project works but I'm not able to clone it using my Android Studio. – Red M Apr 29 '17 at 16:35
13

After a heavy time of research and try-and-error, I've found another solution similar to the one of Chirag Jain above, but using a custom Dialog.

    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;

Despite the fact that Chirag Jain answer seems to be more clean, I'll post this here for have an alternative method.

Parmaia
  • 1,172
  • 1
  • 13
  • 28
  • How to do this if customlayout is a fragment and you are inflating this in your FragmentActivity with this dialog.. it will give you binary inflate error. is not it? – Saty Aug 18 '14 at 05:00
3

As far as I know you can draw on other applications, yes. I myself have designed such an app. As for drawing on an application such as the keyboard or any other application in specific, I guess, you'll have to define a layout with a height that's exactly that of the keyboard. So, that would vary from device to device. So, this isn't possible.

I still stick to my notion that WhatsApp merely dismisses the soft keyboard on pressing the smiley button and calls it's own fragment.

If you would still like to pursue this, here's how you draw a "window" over other applications. These should be it's layout parameters.

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

Albeit, your width will change to an absolute pixel value since you'd like the activity to be over the keyboard only.

If I've misunderstood the question, please correct me.

Karthik Balakrishnan
  • 4,353
  • 6
  • 37
  • 69
  • thanks for your replay, I think this approach is little bit more expensive than WhatsApp did because it's require a permission android:name="android.permission.SYSTEM_ALERT_WINDOW" and WhatsApp didnt you this permission – and_dev Apr 17 '13 at 15:14
  • Exactly, so they're not drawing the smiley fragment over the keyboard :) It's just a simple dismiss command. – Karthik Balakrishnan Apr 17 '13 at 15:20
  • am not sure because they dismisses that keyboard and the native keyboard came in without the animation not to mention that the activity continue to shrink the views while the emoticons keyboard is open – and_dev Apr 17 '13 at 15:23
  • You could always resize the rest of the activity to suit the emoticon tab. I'm sure it's just the design. – Karthik Balakrishnan Apr 17 '13 at 15:25
  • OK thanks for the feedback i'll investigate this approach , and update necessarily – and_dev Apr 17 '13 at 15:28
  • what my thinking is they have created their own keypad for smiles, and on click of smile icon or keypad icon they hiding one smile keypad and showing the normal keypad. – nilesh Aug 29 '13 at 05:18
0

what my thinking is they have created their own keypad for smiles, and on click of smile icon or keypad icon they are hiding smile keypad and showing the normal keypad. there are two scenarios in whats app case 1) if you don't focus 1st time of editext then you can not see the show keypad button,and the height of smile keypad is exactly same as normal keypad,we will get the keypad height only after our view layout is changed, means only after the keypad is shown, that means they are creating their own keypad.. 2) if you focus the edittext and click of smile button then it will show the option of show keypad button Please correct me if i am not right on this

nilesh
  • 175
  • 1
  • 9
0

I recently had to implement a view which would be above a soft keyboard. @Chirag Jain's solution is almost right, but it does not count with the system buttons in the bottom of the screen! This will make the keyboard height incorrect on some devices like NEXUS 6. This solution should work across all devices:

1) create layout which contains your view

<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) keyboard check and view margin settings

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();
}
jirkarrrr
  • 116
  • 1
  • 5
0

@jirkarrr, Why don't you add the keyboardInfoContainer like this:

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

I do as your code, but it cannot show out the keyboardInfoContainer.

0

I use a popup to put view over the keyboard:

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

    }

Then I try to know keyboard's height:

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

You can check this tutorial and this example in GitHub

Cabezas
  • 9,329
  • 7
  • 67
  • 69