in my android application I have a chat activity ,I use this code from android-chat-starter
the problem is in the emulator everything works fine , I tested it in many types of emulators (api >18 , api =18 , api <18) but in testing in actual device it behaves like in this image
the emoji view shows above the keyboard
here is the code I use to show the emoji view
private void showEmojiPopup(boolean show) { showingEmoji = show; if (show) { if (emojiView == null) { if (getActivity() == null) { return; } emojiView = new EmojiView(getActivity()); emojiView.setListener(new EmojiView.Listener() { public void onBackspace() { chatEditText1.dispatchKeyEvent(new KeyEvent(0, 67)); } public void onEmojiSelected(String symbol) { int i = chatEditText1.getSelectionEnd(); if (i < 0) { i = 0; } try { CharSequence localCharSequence = Emoji.replaceEmoji(symbol, chatEditText1.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); chatEditText1.setText(chatEditText1.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); chatEditText1.setSelection(j, j); } catch (Exception e) { Log.e(Constants.TAG, "Error showing emoji"); } } }); windowLayoutParams = new WindowManager.LayoutParams(); windowLayoutParams.gravity = Gravity.BOTTOM | Gravity.LEFT; Log.d(TAG ,Build.VERSION.SDK_INT + " "); if (Build.VERSION.SDK_INT >= 21) { windowLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; } else { windowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; windowLayoutParams.token = getActivity().getWindow().getDecorView().getWindowToken(); } windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; Log.d("emoj",WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + ""); } final int currentHeight; if (keyboardHeight <= 0) keyboardHeight = App.getInstance().getSharedPreferences("emoji", 0).getInt("kbd_height", AndroidUtilities.dp(200)); currentHeight = keyboardHeight; WindowManager wm = (WindowManager) App.getInstance().getSystemService(Activity.WINDOW_SERVICE); windowLayoutParams.height = currentHeight; windowLayoutParams.width = AndroidUtilities.displaySize.x; try { if (emojiView.getParent() != null) { wm.removeViewImmediate(emojiView); } } catch (Exception e) { Log.e(Constants.TAG, e.getMessage()); } try { wm.addView(emojiView, windowLayoutParams); } catch (Exception e) { Log.e(Constants.TAG, e.getMessage()); return; } if (!keyboardVisible) { if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); } return; } } else { removeEmojiWindow(); if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.post(new Runnable() { public void run() { if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, 0); } } }); } } } @Override public void onSizeChanged(int height) { Rect localRect = new Rect(); getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); WindowManager wm = (WindowManager) App.getInstance().getSystemService(Activity.WINDOW_SERVICE); if (wm == null || wm.getDefaultDisplay() == null) { return; } if (height > AndroidUtilities.dp(50) && keyboardVisible) { keyboardHeight = height; App.getInstance().getSharedPreferences("emoji", 0).edit().putInt("kbd_height", keyboardHeight).commit(); } if (showingEmoji) { int newHeight = 0; newHeight = keyboardHeight; if (windowLayoutParams.width != AndroidUtilities.displaySize.x || windowLayoutParams.height != newHeight) { windowLayoutParams.width = AndroidUtilities.displaySize.x; windowLayoutParams.height = newHeight; wm.updateViewLayout(emojiView, windowLayoutParams); if (!keyboardVisible) { sizeNotifierRelativeLayout.post(new Runnable() { @Override public void run() { if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, windowLayoutParams.height); sizeNotifierRelativeLayout.requestLayout(); } } }); } } }
my androidmanifest.xml contains
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <activity android:name=".ConversationShowActivity" android:screenOrientation="portrait" android:label="@string/title_activity_conversation_show" android:launchMode="singleTask" android:parentActivityName=".MainActivity" android:theme="@style/AppTheme" android:windowSoftInputMode="adjustResize" > <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.exampel.myapp.MainActivity" /> </activity>
here is my conversation show xml
<com.example.myapp.widgets.SizeNotifierRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:id="@+id/chat_layout" android:layout_height="match_parent" android:background="@color/white" xmlns:fontawesometext="http://schemas.android.com/apk/res-auto" xmlns:bootstrap="http://schemas.android.com/apk/res-auto" tools:context="com.example.myapp.ConversationShowActivity"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/errorLayout" android:layout_gravity="center" android:layout_centerVertical="true" android:visibility="invisible" tools:visibilty="invisible" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="5dp" android:text="Error loading conversation messages, Click here to try again" android:id="@+id/textView3" android:textColor="#ffff4314" android:textSize="20sp" android:textStyle="bold"/> </LinearLayout> <ProgressBar style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/convProgressBar" android:layout_centerVertical="true" android:layout_centerHorizontal="true"/> <RelativeLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:background="@drawable/border_bottom" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/conv_header" android:paddingTop="10dp" android:paddingBottom="10dp" android:paddingRight="10dp" android:paddingLeft="10dp" android:padding="10dp"> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:id="@+id/conv_avatar" android:src="@drawable/blank_avatar4" android:scaleType="fitXY" android:layout_marginRight="10dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Aboudi" android:id="@+id/conv_user_name" android:textColor="#000000" android:textSize="18sp" android:layout_alignTop="@+id/conv_avatar" android:layout_alignLeft="@+id/conv_online" android:layout_alignStart="@+id/conv_online"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="conv_online" android:id="@+id/conv_online" android:layout_below="@+id/conv_user_name" android:layout_toRightOf="@+id/conv_avatar" android:layout_toEndOf="@+id/conv_avatar" android:layout_marginTop="5dp"/> <LinearLayout android:id="@+id/profileFavBtn" android:layout_width="30dp" android:background="@drawable/heart_bg" android:layout_height="30dp" android:gravity="center" android:layout_marginRight="5dp" android:layout_marginLeft="5dp" android:layout_alignParentRight="false" android:layout_toLeftOf="@+id/profilegiftBtn" android:layout_centerVertical="true"> <com.beardedhen.androidbootstrap.FontAwesomeText android:id="@+id/profileFavText" android:layout_width="wrap_content" android:layout_height="wrap_content" fontawesometext:fa_icon="fa-heart-o" android:textColor="#B94309" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:id="@+id/profilegiftBtn" android:layout_width="30dp" android:background="@drawable/accept_btn_bg" android:layout_height="30dp" android:gravity="center" android:layout_marginRight="5dp" android:layout_marginLeft="5dp" android:layout_alignParentRight="false" android:layout_toLeftOf="@+id/profileReportBtn" android:layout_centerVertical="true"> <com.beardedhen.androidbootstrap.FontAwesomeText android:layout_width="wrap_content" android:layout_height="wrap_content" fontawesometext:fa_icon="fa-gift" android:textColor="@color/white" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:id="@+id/profileReportBtn" android:layout_width="30dp" android:background="@drawable/report_btn_bg" android:layout_height="30dp" android:gravity="center" android:layout_marginRight="5dp" android:layout_marginLeft="5dp" android:layout_alignParentRight="false" android:layout_toLeftOf="@+id/profileBlockBtn" android:layout_centerVertical="true"> <com.beardedhen.androidbootstrap.FontAwesomeText android:layout_width="wrap_content" android:layout_height="wrap_content" fontawesometext:fa_icon="fa-info" android:textColor="@color/white" android:textSize="20sp" /> </LinearLayout> <LinearLayout android:id="@+id/profileBlockBtn" android:layout_width="30dp" android:background="@drawable/refuse_btn_bg" android:layout_height="30dp" android:gravity="center" android:layout_marginRight="5dp" android:layout_marginLeft="5dp" android:layout_alignParentRight="true" android:layout_centerVertical="true"> <com.beardedhen.androidbootstrap.FontAwesomeText android:layout_width="wrap_content" android:layout_height="wrap_content" fontawesometext:fa_icon="fa-remove" android:textColor="@color/white" android:textSize="20sp" /> </LinearLayout> </RelativeLayout> <ListView android:id="@+id/chat_list_view" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:divider="@drawable/chat_divider" android:layout_width="match_parent" android:scrollbarStyle="outsideOverlay" android:layout_below="@id/conv_header" android:layout_above="@+id/bottomlayout" android:layout_height="match_parent"></ListView> <LinearLayout android:id="@+id/bottomlayout" android:background="@drawable/profile_footer_border_top" android:orientation="vertical" android:layout_width="match_parent" android:layout_alignParentBottom="true" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/cant_send_text" android:layout_width="match_parent" android:text="You cant contact this member right now" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentBottom="false" android:layout_alignTop="@+id/chat_edit_text1" android:layout_alignBottom="@+id/chat_edit_text1" android:background="#ff4409" android:gravity="center" android:textColor="#ffffff" android:textSize="15sp" android:textStyle="bold"/> <ImageView android:src="@drawable/ic_msg_panel_smiles" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_width="wrap_content" android:id="@+id/emojiButton" android:layout_alignBottom="@+id/chat_edit_text1" android:layout_marginBottom="8dp" android:layout_height="wrap_content" /> <EditText android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:id="@+id/chat_edit_text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollHorizontally="false" android:layout_toLeftOf="@+id/enter_chat1" android:layout_toRightOf="@id/emojiButton" android:layout_toEndOf="@id/emojiButton" android:layout_toStartOf="@+id/enter_chat1" android:hint="Type your message here .." android:singleLine="false" android:inputType="textCapSentences" android:textSize="18sp" android:paddingLeft="4dp" /> <ImageView android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:id="@+id/enter_chat1" android:layout_width="wrap_content" android:layout_marginBottom="8dp" android:layout_height="wrap_content" android:layout_alignBottom="@id/chat_edit_text1" android:paddingLeft="13dp" android:paddingStart="13dp" android:paddingRight="17dp" android:paddingEnd="17dp" android:src="@drawable/ic_chat_send" /> </RelativeLayout> </LinearLayout> </com.example.myapp.widgets.SizeNotifierRelativeLayout >
here is my emojiview
public class EmojiView extends LinearLayout { private ArrayList<EmojiGridAdapter> adapters = new ArrayList<EmojiGridAdapter>(); private int[] icons = { R.drawable.ic_emoji_recent, R.drawable.ic_emoji_smile, R.drawable.ic_emoji_flower, R.drawable.ic_emoji_bell, R.drawable.ic_emoji_car, R.drawable.ic_emoji_symbol }; private Listener listener; private ViewPager pager; private FrameLayout recentsWrap; private ArrayList<GridView> views = new ArrayList<GridView>(); public EmojiView(Context paramContext) { super(paramContext); init(); } public EmojiView(Context paramContext, AttributeSet paramAttributeSet) { super(paramContext, paramAttributeSet); init(); } public EmojiView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) { super(paramContext, paramAttributeSet, paramInt); init(); } private void addToRecent(long paramLong) { if (this.pager.getCurrentItem() == 0) { return; } ArrayList<Long> localArrayList = new ArrayList<Long>(); long[] currentRecent = Emoji.data[0]; boolean was = false; for (long aCurrentRecent : currentRecent) { if (paramLong == aCurrentRecent) { localArrayList.add(0, paramLong); was = true; } else { localArrayList.add(aCurrentRecent); } } if (!was) { localArrayList.add(0, paramLong); } Emoji.data[0] = new long[Math.min(localArrayList.size(), 50)]; for (int q = 0; q < Emoji.data[0].length; q++) { Emoji.data[0][q] = localArrayList.get(q); } adapters.get(0).data = Emoji.data[0]; adapters.get(0).notifyDataSetChanged(); saveRecents(); } private String convert(long paramLong) { String str = ""; for (int i = 0; ; i++) { if (i >= 4) { return str; } int j = (int)(0xFFFF & paramLong >> 16 * (3 - i)); if (j != 0) { str = str + (char)j; } } } private void init() { setOrientation(LinearLayout.VERTICAL); for (int i = 0; i < Emoji.data.length; i++) { GridView gridView = new GridView(getContext()); // if (AndroidUtilities.isTablet()) { // gridView.setColumnWidth(AndroidUtilities.dp(60)); // } else { gridView.setColumnWidth(AndroidUtilities.dp(45)); // } gridView.setNumColumns(-1); views.add(gridView); EmojiGridAdapter localEmojiGridAdapter = new EmojiGridAdapter(Emoji.data[i]); gridView.setAdapter(localEmojiGridAdapter); // AndroidUtilities.setListViewEdgeEffectColor(gridView, 0xff999999); adapters.add(localEmojiGridAdapter); } setBackgroundColor(0xff222222); pager = new ViewPager(getContext()); pager.setAdapter(new EmojiPagesAdapter()); PagerSlidingTabStrip tabs = new PagerSlidingTabStrip(getContext()); tabs.setViewPager(pager); tabs.setShouldExpand(true); tabs.setIndicatorColor(0xff33b5e5); tabs.setIndicatorHeight(AndroidUtilities.dp(2.0f)); tabs.setUnderlineHeight(AndroidUtilities.dp(2.0f)); tabs.setUnderlineColor(0x66000000); tabs.setTabBackground(0); LinearLayout localLinearLayout = new LinearLayout(getContext()); localLinearLayout.setOrientation(LinearLayout.HORIZONTAL); localLinearLayout.addView(tabs, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f)); ImageView localImageView = new ImageView(getContext()); localImageView.setImageResource(R.drawable.ic_emoji_backspace); localImageView.setScaleType(ImageView.ScaleType.CENTER); localImageView.setBackgroundResource(R.drawable.bg_emoji_bs); localImageView.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (EmojiView.this.listener != null) { EmojiView.this.listener.onBackspace(); } } }); localLinearLayout.addView(localImageView, new LinearLayout.LayoutParams(AndroidUtilities.dp(61), LayoutParams.MATCH_PARENT)); recentsWrap = new FrameLayout(getContext()); recentsWrap.addView(views.get(0)); TextView localTextView = new TextView(getContext()); localTextView.setText(getContext().getString(R.string.NoRecent)); localTextView.setTextSize(18.0f); localTextView.setTextColor(-7829368); localTextView.setGravity(17); recentsWrap.addView(localTextView); views.get(0).setEmptyView(localTextView); addView(localLinearLayout, new LinearLayout.LayoutParams(-1, AndroidUtilities.dp(48.0f))); addView(pager); loadRecents(); if (Emoji.data[0] == null || Emoji.data[0].length == 0) { pager.setCurrentItem(1); } } private void saveRecents() { ArrayList<Long> localArrayList = new ArrayList<Long>(); long[] arrayOfLong = Emoji.data[0]; int i = arrayOfLong.length; for (int j = 0; ; j++) { if (j >= i) { getContext().getSharedPreferences("emoji", 0).edit().putString("recents", TextUtils.join(",", localArrayList)).commit(); return; } localArrayList.add(arrayOfLong[j]); } } public void loadRecents() { String str = getContext().getSharedPreferences("emoji", 0).getString("recents", ""); String[] arrayOfString = null; if ((str != null) && (str.length() > 0)) { arrayOfString = str.split(","); Emoji.data[0] = new long[arrayOfString.length]; } if (arrayOfString != null) { for (int i = 0; i < arrayOfString.length; i++) { Emoji.data[0][i] = Long.parseLong(arrayOfString[i]); } adapters.get(0).data = Emoji.data[0]; adapters.get(0).notifyDataSetChanged(); } } public void onMeasure(int paramInt1, int paramInt2) { super.onMeasure(View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(paramInt1), MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(paramInt2), MeasureSpec.EXACTLY)); } public void setListener(Listener paramListener) { this.listener = paramListener; } public void invalidateViews() { for (GridView gridView : views) { if (gridView != null) { gridView.invalidateViews(); } } } private class EmojiGridAdapter extends BaseAdapter { long[] data; public EmojiGridAdapter(long[] arg2) { this.data = arg2; } public int getCount() { return data.length; } public Object getItem(int i) { return null; } public long getItemId(int i) { return data[i]; } public View getView(int i, View view, ViewGroup paramViewGroup) { ImageView imageView = (ImageView)view; if (imageView == null) { imageView = new ImageView(EmojiView.this.getContext()) { public void onMeasure(int paramAnonymousInt1, int paramAnonymousInt2) { setMeasuredDimension(View.MeasureSpec.getSize(paramAnonymousInt1), View.MeasureSpec.getSize(paramAnonymousInt1)); } }; imageView.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { if (EmojiView.this.listener != null) { EmojiView.this.listener.onEmojiSelected(EmojiView.this.convert((Long)view.getTag())); } EmojiView.this.addToRecent((Long)view.getTag()); } }); imageView.setBackgroundResource(R.drawable.list_selector); imageView.setScaleType(ImageView.ScaleType.CENTER); } imageView.setImageDrawable(Emoji.getEmojiBigDrawable(data[i])); imageView.setTag(data[i]); return imageView; } @Override public void unregisterDataSetObserver(DataSetObserver observer) { if (observer != null) { super.unregisterDataSetObserver(observer); } } } private class EmojiPagesAdapter extends PagerAdapter implements PagerSlidingTabStrip.IconTabProvider { public void destroyItem(ViewGroup paramViewGroup, int paramInt, Object paramObject) { View localObject; if (paramInt == 0) { localObject = recentsWrap; } else { localObject = views.get(paramInt); } paramViewGroup.removeView(localObject); } public int getCount() { return views.size(); } public int getPageIconResId(int paramInt) { return icons[paramInt]; } public Object instantiateItem(ViewGroup paramViewGroup, int paramInt) { View localObject; if (paramInt == 0) { localObject = recentsWrap; } else { localObject = views.get(paramInt); } paramViewGroup.addView(localObject); return localObject; } public boolean isViewFromObject(View paramView, Object paramObject) { return paramView == paramObject; } @Override public void unregisterDataSetObserver(DataSetObserver observer) { if (observer != null) { super.unregisterDataSetObserver(observer); } } } public static abstract interface Listener { public abstract void onBackspace(); public abstract void onEmojiSelected(String paramString); } }
the problem happens when the keyboard is visible ,but if it's not visible the emoji view works fine
After research I figured out that to work in some cases parent layout has to be set android:fitsSystemWindows="true" . Then native functionality of scrolling EditText above scrollbar working like a charm. Show activity on this post. Simply setting android:fitsSystemWindows="true" in the layout xml worked for me.
The soft keyboard (also called the onscreen keyboard) is the main input method on Android devices, and almost every Android developer needs to work with this component at some point.
Unfortunately, as far for Android 5.0 (dont know after) theres no way to get the keyboard height. So you can't use this value to position your View.
But, you can use the softKeyboard relayout to do what you want, by using softKeyboard (at the Activity manifest) with a value of "resize" will make your root layout View to be resized to the size of the remaining screen space. By positioning your view at the bottom will make it exactly on top of the keyboard.
PS: Also, your root view needs its height value to be match_parent instead of anything else (or you will need to deal in hard other ways)
Maybe you mean you want to replace the keyboard location instead of being on "top of it" (NORTH?), in this case, you should use a CustomView that extends View and not use the EditText that does open the keyboard for you
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With