...
 
Commits (14)
package net.dankito.utils.android
import android.app.Activity
class KeyboardState {
companion object {
var isKeyboardVisible: Boolean = false
private set
private val keyboardToggleListener = KeyboardUtils.SoftKeyboardToggleListener { isVisible ->
isKeyboardVisible = isVisible
}
fun init(activity: Activity) {
KeyboardUtils.addKeyboardToggleListener(activity, keyboardToggleListener)
}
/**
* It's very important to call cleanUp() when done to avoid memory leaks!
*/
fun cleanUp() {
KeyboardUtils.removeKeyboardToggleListener(keyboardToggleListener)
}
}
}
\ No newline at end of file
package net.dankito.utils.android;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
import java.util.HashMap;
/**
* Thanks to ravindu1024 for providing this class: https://github.com/ravindu1024/android-keyboardlistener/blob/master/keyboard-listener/src/main/java/com/rw/keyboardlistener/KeyboardUtils.java
*
* Based on the following Stackoverflow answer:
* http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
*/
@SuppressWarnings("WeakerAccess")
public class KeyboardUtils implements ViewTreeObserver.OnGlobalLayoutListener
{
private final static int MAGIC_NUMBER = 200;
private SoftKeyboardToggleListener mCallback;
private View mRootView;
private Boolean prevValue = null;
private float mScreenDensity = 1;
private static HashMap<SoftKeyboardToggleListener, KeyboardUtils> sListenerMap = new HashMap<>();
public interface SoftKeyboardToggleListener
{
void onToggleSoftKeyboard(boolean isVisible);
}
@Override
public void onGlobalLayout()
{
Rect r = new Rect();
mRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
float dp = heightDiff/ mScreenDensity;
boolean isVisible = dp > MAGIC_NUMBER;
if (mCallback != null && (prevValue == null || isVisible != prevValue)) {
prevValue = isVisible;
mCallback.onToggleSoftKeyboard(isVisible);
}
}
/**
* Add a new keyboard listener
* @param act calling activity
* @param listener callback
*/
public static void addKeyboardToggleListener(Activity act, SoftKeyboardToggleListener listener)
{
removeKeyboardToggleListener(listener);
sListenerMap.put(listener, new KeyboardUtils(act, listener));
}
/**
* Remove a registered listener
* @param listener {@link SoftKeyboardToggleListener}
*/
public static void removeKeyboardToggleListener(SoftKeyboardToggleListener listener)
{
if(sListenerMap.containsKey(listener))
{
KeyboardUtils k = sListenerMap.get(listener);
k.removeListener();
sListenerMap.remove(listener);
}
}
/**
* Remove all registered keyboard listeners
*/
public static void removeAllKeyboardToggleListeners()
{
for(SoftKeyboardToggleListener l : sListenerMap.keySet())
sListenerMap.get(l).removeListener();
sListenerMap.clear();
}
/**
* Manually toggle soft keyboard visibility
* @param context calling context
*/
public static void toggleKeyboardVisibility(Context context)
{
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
/**
* Force closes the soft keyboard
* @param activeView the view with the keyboard focus
*/
public static void forceCloseKeyboard(View activeView)
{
InputMethodManager inputMethodManager = (InputMethodManager) activeView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activeView.getWindowToken(), 0);
}
private void removeListener()
{
mCallback = null;
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
else {
mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
private KeyboardUtils(Activity act, SoftKeyboardToggleListener listener)
{
mCallback = listener;
mRootView = ((ViewGroup) act.findViewById(android.R.id.content)).getChildAt(0);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
mScreenDensity = act.getResources().getDisplayMetrics().density;
}
}
......@@ -8,6 +8,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewTreeObserver
import android.view.inputmethod.InputMethodManager
import org.slf4j.LoggerFactory
fun View.showKeyboard() {
......@@ -15,7 +16,11 @@ fun View.showKeyboard() {
this.requestFocus()
val keyboard = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
keyboard.showSoftInput(this, 0)
try {
keyboard.showSoftInput(this, 0)
} catch (e: Exception) { // couldn't believe it, inside keyboard.showSoftInput() may a NullPointerException occurs
LoggerFactory.getLogger("ViewExtensions").error("Call to InputMethodManager.showSoftInput() resulted in an error", e)
}
}
}
......
package net.dankito.utils.android.keyboard
import android.app.Activity
class KeyboardState {
var isKeyboardVisible: Boolean = false
private set
private val keyboardUtils = KeyboardUtils()
private val keyboardToggleListener = object : SoftKeyboardToggleListener {
override fun onToggleSoftKeyboard(isVisible: Boolean) {
isKeyboardVisible = isVisible
}
}
fun init(activity: Activity) {
keyboardUtils.addKeyboardToggleListener(activity, keyboardToggleListener)
}
/**
* It's very important to call cleanUp() when done to avoid memory leaks!
*/
fun cleanUp() {
keyboardUtils.removeKeyboardToggleListener(keyboardToggleListener)
}
}
\ No newline at end of file
package net.dankito.utils.android.keyboard
import android.app.Activity
import android.content.Context
import android.view.View
import android.view.inputmethod.InputMethodManager
import java.util.*
/**
* Thanks to ravindu1024 for providing the original version of this class:
* https://github.com/ravindu1024/android-keyboardlistener/blob/master/keyboard-listener/src/main/java/com/rw/keyboardlistener/KeyboardUtils.java
*
* Based on the following Stackoverflow answer:
* http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
*/
class KeyboardUtils {
companion object {
/**
* Manually toggle soft keyboard visibility
* @param context calling context
*/
fun toggleKeyboardVisibility(context: Context) {
val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
}
/**
* Force closes the soft keyboard
* @param activeView the view with the keyboard focus
*/
fun forceCloseKeyboard(activeView: View) {
val inputMethodManager = activeView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(activeView.windowToken, 0)
}
}
private val listeners = HashMap<SoftKeyboardToggleListener, SoftKeyboardStateListener>()
/**
* Add a new keyboard toggleListener
* @param activity calling activity
* @param toggleListener callback
*/
fun addKeyboardToggleListener(activity: Activity, toggleListener: SoftKeyboardToggleListener) {
removeKeyboardToggleListener(toggleListener)
listeners[toggleListener] = SoftKeyboardStateListener(activity, toggleListener)
}
/**
* Remove a registered toggleListener
* @param toggleListener [SoftKeyboardToggleListener]
*/
fun removeKeyboardToggleListener(toggleListener: SoftKeyboardToggleListener) {
val listener = listeners.remove(toggleListener)
listener?.cleanUp()
}
/**
* Remove all registered keyboard listeners
*/
fun removeAllKeyboardToggleListeners() {
listeners.values.forEach { it.cleanUp() }
listeners.clear()
}
}
package net.dankito.utils.android.keyboard
import android.app.Activity
import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import net.dankito.utils.android.extensions.removeOnGlobalLayoutListener
internal class SoftKeyboardStateListener(activity: Activity, private var callback: SoftKeyboardToggleListener?) : ViewTreeObserver.OnGlobalLayoutListener {
companion object {
private const val MagicNumber = 200
}
private var rootView: View? = null
private var screenDensity = 1f
private var previousValue: Boolean? = null
init {
rootView = (activity.findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0)
rootView?.viewTreeObserver?.addOnGlobalLayoutListener(this)
screenDensity = activity.resources.displayMetrics.density
}
override fun onGlobalLayout() {
rootView?.let { rootView ->
val rect = Rect()
rootView.getWindowVisibleDisplayFrame(rect)
val heightDiff = rootView.rootView.height - (rect.bottom - rect.top)
val dp = heightDiff / screenDensity
val isVisible = dp > MagicNumber
if (callback != null && (previousValue == null || isVisible != previousValue)) {
previousValue = isVisible
callback?.onToggleSoftKeyboard(isVisible)
}
}
}
fun cleanUp() {
removeGlobalLayoutListener()
}
private fun removeGlobalLayoutListener() {
callback = null
rootView?.removeOnGlobalLayoutListener(this)
rootView = null
}
}
\ No newline at end of file
package net.dankito.utils.android.keyboard
interface SoftKeyboardToggleListener {
fun onToggleSoftKeyboard(isVisible: Boolean)
}
\ No newline at end of file