Commit 2b3858b1 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Move emoji keyboard from fragment approach to popup approach.

parent bc77daa5
......@@ -37,19 +37,22 @@
<activity
android:name=".main.ui.MainActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
<activity
android:name=".webview.WebViewActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
<activity
android:name=".chatroom.ui.ChatRoomActivity"
android:windowSoftInputMode="adjustPan"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
<activity
android:name=".chatroom.ui.PinnedMessagesActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
<receiver
......
......@@ -302,10 +302,6 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
}
}
fun dispatchRestoreUIState() {
view.restoreUIState()
}
private suspend fun listenMessages(roomId: String) {
launch(CommonPool + strategy.jobs) {
for (message in client.messagesChannel) {
......
......@@ -97,9 +97,4 @@ interface ChatRoomView : LoadingView, MessageView {
fun clearMessageComposition()
fun showInvalidFileSize(fileSize: Int, maxFileSize: Int)
/**
* Restore UI state.
*/
fun restoreUIState()
}
\ No newline at end of file
......@@ -5,10 +5,8 @@ import android.content.Intent
import android.os.Bundle
import android.support.v4.app.Fragment
import chat.rocket.android.R
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.widget.emoji.EmojiFragment
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
......@@ -67,14 +65,7 @@ class ChatRoomActivity : SwipeBackActivity(), HasSupportFragmentInjector {
}
override fun onBackPressed() {
val frag = supportFragmentManager.findFragmentByTag(EmojiFragment.TAG) as EmojiFragment?
if (frag != null && frag.isExpanded()) {
frag.collapse()
} else {
KeyboardHelper.hideSoftKeyboard(this)
finishActivity()
super.onBackPressed()
}
finishActivity()
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
......
......@@ -96,7 +96,6 @@ class ChatRoomAdapter(private val roomType: String,
setChecked(isPinned)
}
val adapter = ActionListAdapter(menuItems, this@ViewHolder)
presenter.dispatchRestoreUIState()
BottomSheetMenu(adapter).show(it.context)
}
}
......
......@@ -24,7 +24,7 @@ import chat.rocket.android.helper.MessageParser
import chat.rocket.android.util.extensions.*
import chat.rocket.android.widget.emoji.ComposerEditText
import chat.rocket.android.widget.emoji.Emoji
import chat.rocket.android.widget.emoji.EmojiFragment
import chat.rocket.android.widget.emoji.EmojiKeyboardPopup
import chat.rocket.android.widget.emoji.EmojiParser
import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.CompositeDisposable
......@@ -52,7 +52,7 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
private const val BUNDLE_IS_CHAT_ROOM_READ_ONLY = "is_chat_room_read_only"
private const val REQUEST_CODE_FOR_PERFORM_SAF = 42
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardPopup.Listener {
@Inject lateinit var presenter: ChatRoomPresenter
@Inject lateinit var parser: MessageParser
private lateinit var adapter: ChatRoomAdapter
......@@ -60,6 +60,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
private lateinit var chatRoomId: String
private lateinit var chatRoomName: String
private lateinit var chatRoomType: String
private lateinit var emojiKeyboardPopup: EmojiKeyboardPopup
private var isChatRoomReadOnly: Boolean = false
private lateinit var actionSnackbar: ActionSnackbar
......@@ -106,8 +107,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
attachOrGetEmojiFragment()
text_message.addTextChangedListener(EmojiFragment.EmojiTextWatcher(text_message))
text_message.addTextChangedListener(EmojiKeyboardPopup.EmojiTextWatcher(text_message))
}
override fun onDestroyView() {
......@@ -212,10 +212,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
adapter.removeItem(msgId)
}
override fun restoreUIState() {
hideAllKeyboards()
}
override fun showReplyingAction(username: String, replyMarkdown: String, quotedMessage: String) {
activity?.apply {
citation = replyMarkdown
......@@ -269,27 +265,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
}
}
override fun onEmojiPanelCollapsed() {
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
override fun onEmojiPanelExpanded() {
}
private fun setReactionButtonIcon(@DrawableRes drawableId: Int) {
button_add_reaction.setImageResource(drawableId)
button_add_reaction.setTag(drawableId)
}
private fun hideAllKeyboards() {
activity?.let {
KeyboardHelper.hideSoftKeyboard(it)
attachOrGetEmojiFragment()?.collapse()
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
}
override fun showFileSelection(filter: Array<String>) {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
......@@ -329,28 +309,21 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
input_container.setVisible(false)
} else {
subscribeTextMessage()
emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container))
emojiKeyboardPopup.listener = this
text_message.listener = object : ComposerEditText.ComposerEditTextListener {
override fun onKeyboardOpened() {
activity?.let {
val fragment = EmojiFragment.getOrAttach(it, R.id.emoji_fragment_placeholder, composer)
if (fragment.isCollapsed()) {
fragment.expandHidden()
}
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
}
override fun onKeyboardClosed() {
activity?.let {
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
val fragment = EmojiFragment.getOrAttach(it, R.id.emoji_fragment_placeholder, composer)
if (fragment.isCollapsed()) {
if (!emojiKeyboardPopup.isKeyboardOpen) {
it.onBackPressed()
} else {
hideAllKeyboards()
}
KeyboardHelper.hideSoftKeyboard(it)
emojiKeyboardPopup.dismiss()
}
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
}
......@@ -358,11 +331,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
var textMessage = citation ?: ""
textMessage += text_message.textContent
sendMessage(textMessage)
attachOrGetEmojiFragment()?.let {
if (it.softKeyboardVisible) {
it.collapse()
}
}
clearMessageComposition()
}
......@@ -370,7 +339,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
if (layout_message_attachment_options.isShown) {
hideAttachmentOptions()
} else {
hideAllKeyboards()
showAttachmentOptions()
}
}
......@@ -390,33 +358,29 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiFragment.Listener {
}
button_add_reaction.setOnClickListener { view ->
activity?.let {
val editor = text_message
val emojiFragment = attachOrGetEmojiFragment()!!
val tag = if (view.tag == null) R.drawable.ic_reaction_24dp else view.tag as Int
when (tag) {
R.drawable.ic_reaction_24dp -> {
KeyboardHelper.hideSoftKeyboard(it)
if (!emojiFragment.isExpanded()) {
emojiFragment.show()
}
setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp)
}
R.drawable.ic_keyboard_black_24dp -> {
KeyboardHelper.showSoftKeyboard(editor)
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
}
}
openEmojiKeyboardPopup()
}
}
}
private fun attachOrGetEmojiFragment(): EmojiFragment? {
return activity?.let {
val frag = EmojiFragment.getOrAttach(it, R.id.emoji_fragment_placeholder, composer)
frag.listener = this
frag
private fun openEmojiKeyboardPopup() {
if (!emojiKeyboardPopup.isShowing()) {
// If keyboard is visible, simply show the popup
if (emojiKeyboardPopup.isKeyboardOpen) {
emojiKeyboardPopup.showAtBottom()
} else {
// Open the text keyboard first and immediately after that show the emoji popup
text_message.setFocusableInTouchMode(true)
text_message.requestFocus()
emojiKeyboardPopup.showAtBottomPending()
KeyboardHelper.showSoftKeyboard(text_message)
}
setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp)
} else {
// If popup is showing, simply dismiss it to show the undelying text keyboard
emojiKeyboardPopup.dismiss()
setReactionButtonIcon(R.drawable.ic_reaction_24dp)
}
}
......
package chat.rocket.android.helper
import android.graphics.Rect
import android.view.View
import android.content.Context.INPUT_METHOD_SERVICE
import android.app.Activity
import android.content.Context
import android.graphics.Rect
import android.view.View
import android.view.inputmethod.InputMethodManager
......@@ -36,7 +35,7 @@ object KeyboardHelper {
val currentFocus = activity.currentFocus
if (currentFocus != null) {
val inputMethodManager = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(currentFocus.windowToken, 0)
inputMethodManager.hideSoftInputFromWindow(currentFocus.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
}
}
......@@ -48,14 +47,7 @@ object KeyboardHelper {
fun showSoftKeyboard(view: View) {
if (view.requestFocus()) {
val inputMethodManager = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
}
}
fun restart(view: View) {
if (view.requestFocus()) {
val inputMethodManager = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.restartInput(view)
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.SHOW_IMPLICIT)
}
}
}
\ No newline at end of file
......@@ -9,9 +9,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.widget.emoji.EmojiFragment.Listener
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.async
import chat.rocket.android.widget.emoji.EmojiKeyboardPopup.Listener
import java.util.*
class CategoryPagerAdapter(val listener: Listener) : PagerAdapter() {
......
package chat.rocket.android.widget.emoji
import android.graphics.Rect
import android.os.Bundle
import android.support.annotation.IdRes
import android.content.Context
import android.support.design.widget.TabLayout
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentActivity
import android.support.v4.view.ViewPager
import android.support.v7.app.AppCompatActivity
import android.text.Editable
import android.text.TextWatcher
import android.view.*
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.ImageView
import chat.rocket.android.R
class EmojiFragment : Fragment() {
class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow(context, view) {
private lateinit var viewPager: ViewPager
private lateinit var tabLayout: TabLayout
private lateinit var searchView: View
private lateinit var backspaceView: View
private lateinit var parentContainer: ViewGroup
private var editor: View? = null
private var decorLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
var softKeyboardVisible = false
var listener: Listener? = null
companion object {
const val PREF_EMOJI_RECENTS = "PREF_EMOJI_RECENTS"
const val PREF_KEYBOARD_HEIGHT = "PREF_KEYBOARD_HEIGHT"
const val MIN_KEYBOARD_HEIGHT_PX = 150
val TAG: String = EmojiFragment::class.java.simpleName
fun newInstance(editor: View) = EmojiFragment().apply { this.editor = editor }
fun getOrAttach(activity: FragmentActivity, @IdRes containerId: Int, editor: View): EmojiFragment {
val fragmentManager = activity.supportFragmentManager
var fragment: Fragment? = fragmentManager.findFragmentByTag(TAG)
return if (fragment == null) {
fragment = newInstance(editor)
fragment.parentContainer = activity.findViewById(containerId)
fragmentManager.beginTransaction()
.replace(containerId, fragment, TAG)
.commit()
fragment
} else {
fragment as EmojiFragment
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = inflater.inflate(R.layout.emoji_popup_layout, container, false)
override fun onCreateView(inflater: LayoutInflater): View {
val view = inflater.inflate(R.layout.emoji_popup_layout, null, false)
parentContainer = view.findViewById(R.id.emoji_keyboard_container)
viewPager = view.findViewById(R.id.pager_categories)
searchView = view.findViewById(R.id.emoji_search)
......@@ -60,67 +38,13 @@ class EmojiFragment : Fragment() {
return view
}
override fun onDetach() {
super.onDetach()
activity?.getWindow()?.decorView?.viewTreeObserver?.removeOnGlobalLayoutListener(decorLayoutListener)
listener = null
editor = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setupLayout()
override fun onViewCreated(view: View) {
setupViewPager()
setupBottomBar()
}
private fun setupLayout() {
activity?.let {
val decorView = it.getWindow().decorView
decorLayoutListener = object : ViewTreeObserver.OnGlobalLayoutListener {
private val windowVisibleDisplayFrame = Rect()
private var lastVisibleDecorViewHeight: Int = 0
override fun onGlobalLayout() {
if (editor == null) {
return
}
// Retrieve visible rectangle inside window.
decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame)
val visibleDecorViewHeight = windowVisibleDisplayFrame.height()
// Decide whether keyboard is visible from changing decor view height.
if (lastVisibleDecorViewHeight != 0) {
if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
// Calculate current keyboard height (this includes also navigation bar height when in fullscreen mode).
val currentKeyboardHeight = decorView.height - windowVisibleDisplayFrame.bottom - editor!!.measuredHeight
// Notify listener about keyboard being shown.
EmojiRepository.saveKeyboardHeight(currentKeyboardHeight)
setKeyboardHeight(currentKeyboardHeight)
softKeyboardVisible = true
parentContainer.postDelayed({
expandHidden()
}, 100)
} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
// Notify listener about keyboard being hidden.
softKeyboardVisible = false
}
}
// Save current decor view height for the next call.
lastVisibleDecorViewHeight = visibleDecorViewHeight
}
}
decorView.viewTreeObserver.addOnGlobalLayoutListener(decorLayoutListener)
}
val storedHeight = EmojiRepository.getKeyboardHeight()
if (storedHeight > 0) {
setKeyboardHeight(storedHeight)
}
}
private fun setupBottomBar() {
searchView.setOnClickListener {
}
backspaceView.setOnClickListener {
......@@ -129,11 +53,11 @@ class EmojiFragment : Fragment() {
}
private fun setupViewPager() {
activity?.let {
context.let {
val callback = when (it) {
is Listener -> it as Listener
is Listener -> it
else -> {
val fragments = it.supportFragmentManager.fragments
val fragments = (it as AppCompatActivity).supportFragmentManager.fragments
if (fragments == null || fragments.size == 0 || !(fragments[0] is Listener)) {
throw IllegalStateException("activity/fragment should implement Listener interface")
}
......@@ -141,14 +65,6 @@ class EmojiFragment : Fragment() {
}
}
viewPager.adapter = CategoryPagerAdapter(object : Listener {
override fun onEmojiPanelExpanded() {
// do nothing
}
override fun onEmojiPanelCollapsed() {
// do nothing
}
override fun onNonEmojiKeyPressed(keyCode: Int) {
// do nothing
}
......@@ -161,7 +77,7 @@ class EmojiFragment : Fragment() {
for (category in EmojiCategory.values()) {
val tab = tabLayout.getTabAt(category.ordinal)
val tabView = layoutInflater.inflate(R.layout.emoji_picker_tab, null)
val tabView = LayoutInflater.from(context).inflate(R.layout.emoji_picker_tab, null)
tab?.setCustomView(tabView)
val textView = tabView.findViewById(R.id.image_category) as ImageView
textView.setImageResource(category.resourceIcon())
......@@ -173,14 +89,6 @@ class EmojiFragment : Fragment() {
}
}
private fun setKeyboardHeight(height: Int) {
val oldHeight = parentContainer.layoutParams.height
if (oldHeight != height) {
parentContainer.layoutParams.height = height
parentContainer.requestLayout()
}
}
class EmojiTextWatcher(val editor: EditText) : TextWatcher {
@Volatile private var emojiToRemove = mutableListOf<EmojiTypefaceSpan>()
......@@ -225,51 +133,6 @@ class EmojiFragment : Fragment() {
}
}
private fun setKeyboardVisibility(visibility: Int) {
if (visibility != parentContainer.visibility) {
parentContainer.visibility = visibility
}
}
/**
* Show the emoji keyboard.
*/
fun show() {
setKeyboardVisibility(View.VISIBLE)
}
/**
* Expand the emoji keyboard with invisible contents.
*/
fun expandHidden() {
setKeyboardVisibility(View.INVISIBLE)
}
/**
* Hide the emoji keyboard.
*/
fun collapse() {
// Since the emoji keyboard is always behind the soft keyboard assume it's also dismissed
// when the emoji one is about to get close. Hence we should invoke our listener to update
// the UI as if the soft keyboard is hidden.
listener?.onEmojiPanelCollapsed()
setKeyboardVisibility(View.GONE)
}
/**
* Whether the emoji keyboard is visible.
*
* @return <code>true</code> if opened.
*/
fun isExpanded() = parentContainer.visibility == View.VISIBLE
/**
* Whether the emoji keyboard is collapsed.
*
* @return false if the emoji keyboard is visible and not obscured
*/
fun isCollapsed() = parentContainer.visibility == View.GONE
interface Listener {
/**
* When an emoji is selected on the picker.
......@@ -286,9 +149,5 @@ class EmojiFragment : Fragment() {
* @see android.view.KeyEvent
*/
fun onNonEmojiKeyPressed(keyCode: Int)
fun onEmojiPanelCollapsed()
fun onEmojiPanelExpanded()
}
}
\ No newline at end of file
......@@ -79,14 +79,14 @@ object EmojiRepository {
*/
fun addToRecents(emoji: Emoji) {
val emojiShortname = emoji.shortname
val recentsJson = JSONObject(preferences.getString(EmojiFragment.PREF_EMOJI_RECENTS, "{}"))
val recentsJson = JSONObject(preferences.getString(EmojiKeyboardPopup.PREF_EMOJI_RECENTS, "{}"))
if (recentsJson.has(emojiShortname)) {
val useCount = recentsJson.getInt(emojiShortname)
recentsJson.put(emojiShortname, useCount + 1)
} else {
recentsJson.put(emojiShortname, 1)
}
preferences.edit().putString(EmojiFragment.PREF_EMOJI_RECENTS, recentsJson.toString()).apply()
preferences.edit().putString(EmojiKeyboardPopup.PREF_EMOJI_RECENTS, recentsJson.toString()).apply()
}
/**
......@@ -96,7 +96,7 @@ object EmojiRepository {
*/
fun getRecents(): List<Emoji> {
val list = mutableListOf<Emoji>()
val recentsJson = JSONObject(preferences.getString(EmojiFragment.PREF_EMOJI_RECENTS, "{}"))
val recentsJson = JSONObject(preferences.getString(EmojiKeyboardPopup.PREF_EMOJI_RECENTS, "{}"))
for (shortname in recentsJson.keys()) {
val emoji = getEmojiByShortname(shortname)
emoji?.let {
......@@ -110,25 +110,6 @@ object EmojiRepository {
return list
}
/**
* Store current soft keyboard height for later reference.
*/
fun saveKeyboardHeight(height: Int) {
if (height <= 0) {
return
}
preferences.edit()
.putInt(EmojiFragment.PREF_KEYBOARD_HEIGHT, height)
.apply()
}
/**
* Get stored keyboard height.
*
* @return Height of the current soft keyboard.
*/
fun getKeyboardHeight() = preferences.getInt(EmojiFragment.PREF_KEYBOARD_HEIGHT, 0)
/**
* Replace shortnames to unicode characters.
*/
......
/**
* Copyright 2015 YA LLC
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package chat.rocket.android.widget.emoji
import android.content.Context
import android.graphics.Point
import android.graphics.Rect
import android.os.Build
import android.view.*
import android.widget.PopupWindow
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
/**
* Base class to create popup window that appears over software keyboard.
*/
abstract class OverKeyboardPopupWindow(val context: Context, private val rootView: View) : PopupWindow(context), ViewTreeObserver.OnGlobalLayoutListener {
/**
* @return keyboard height in pixels
*/
var keyboardHeight = 0
private set
private var pendingOpen = false
/**
* @return Returns true if the soft keyboard is open, false otherwise.
*/
var isKeyboardOpen = false
private set
private var keyboardHideListener: OnKeyboardHideListener? = null
interface OnKeyboardHideListener {
fun onKeyboardHide()
}
init {
setBackgroundDrawable(null)
if (BuildConfig.VERSION_CODE >= Build.VERSION_CODES.LOLLIPOP) {
elevation = 0f
}
val view = onCreateView(LayoutInflater.from(context))
onViewCreated(view)
contentView = view
softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
// Default size
setSize(this.context.resources.getDimensionPixelSize(R.dimen.supposed_keyboard_height),
WindowManager.LayoutParams.MATCH_PARENT)
setSizeForSoftKeyboard()
}
fun setKeyboardHideListener(keyboardHideListener: OnKeyboardHideListener) {
this.keyboardHideListener = keyboardHideListener
}
/**
* Manually set the popup window size
*
* @param width Width of the popup
* @param height Height of the popup
*/
fun setSize(width: Int, height: Int) {
setWidth(width)
setHeight(height)
}
/**
* Call this function to resize the emoji popup according to your soft keyboard size
*/
fun setSizeForSoftKeyboard() {
val viewTreeObserver = rootView.viewTreeObserver
viewTreeObserver.addOnGlobalLayoutListener(this)
}
override fun onGlobalLayout() {
val r = Rect()
rootView.getWindowVisibleDisplayFrame(r)
val screenHeight = calculateScreenHeight()
var heightDifference = screenHeight - (r.bottom - r.top)
val resources = context.resources
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
heightDifference -= resources.getDimensionPixelSize(resourceId)
}
if (heightDifference > 100) {
keyboardHeight = heightDifference
setSize(WindowManager.LayoutParams.MATCH_PARENT, keyboardHeight)
isKeyboardOpen = true
if (pendingOpen) {
showAtBottom()
pendingOpen = false
}
} else {
if (isKeyboardOpen && keyboardHideListener != null) {
keyboardHideListener!!.onKeyboardHide()
}
isKeyboardOpen = false
}
}
private fun calculateScreenHeight(): Int {
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val display = wm.getDefaultDisplay()
val size = Point()
display.getSize(size)
return size.y
}
/**
* Use this function to show the popup.
* NOTE: Since, the soft keyboard sizes are variable on different android devices, the
* library needs you to open the soft keyboard at least once before calling this function.
* If that is not possible see showAtBottomPending() function.
*/
fun showAtBottom() {
showAtLocation(rootView, Gravity.BOTTOM, 0, 0)
}
/**
* Use this function when the soft keyboard has not been opened yet. This
* will show the popup after the keyboard is up next time.
* Generally, you will be calling InputMethodManager.showSoftInput function after
* calling this function.
*/
fun showAtBottomPending() {
if (isKeyboardOpen) {
showAtBottom()
} else {
pendingOpen = true
}
}
abstract fun onCreateView(inflater: LayoutInflater): View
abstract fun onViewCreated(view: View)
}
\ No newline at end of file
......@@ -3,9 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/emoji_keyboard_container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@color/white"
android:visibility="gone">
android:layout_height="0dp"
android:background="@color/white">
<View
android:id="@+id/divider"
......
......@@ -17,4 +17,6 @@
<!-- Emoji -->
<dimen name="picker_padding_bottom">16dp</dimen>
<dimen name="supposed_keyboard_height">252dp</dimen>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment