-
-
Save Piasy/2b79a25aa5ef360066f2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.younglive.livestreaming.utils.view; | |
/* | |
* Author: Felipe Herranz ([email protected]) | |
* Contributors:Francesco Verheye ([email protected]) | |
* Israel Dominguez ([email protected]) | |
*/ | |
import android.os.Handler; | |
import android.os.Message; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.inputmethod.InputMethodManager; | |
import android.widget.EditText; | |
import java.lang.ref.WeakReference; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
public class SoftKeyboard implements View.OnFocusChangeListener | |
{ | |
private static final int CLEAR_FOCUS = 0; | |
private ViewGroup layout; | |
private int layoutBottom; | |
private InputMethodManager im; | |
private int[] coords; | |
private boolean isKeyboardShow; | |
private SoftKeyboardChangesThread softKeyboardThread; | |
private List<EditText> editTextList; | |
private View tempView; // reference to a focused EditText | |
public SoftKeyboard(ViewGroup layout, InputMethodManager im) { | |
this.layout = layout; | |
keyboardHideByDefault(); | |
initEditTexts(layout); | |
this.im = im; | |
this.coords = new int[2]; | |
this.isKeyboardShow = false; | |
this.softKeyboardThread = new SoftKeyboardChangesThread(this); | |
this.softKeyboardThread.start(); | |
mHandler = new InnerHandler(this); | |
} | |
public void openSoftKeyboard() | |
{ | |
if(!isKeyboardShow) | |
{ | |
layoutBottom = getLayoutCoordinates(); | |
im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT); | |
softKeyboardThread.keyboardOpened(); | |
isKeyboardShow = true; | |
} | |
} | |
public void closeSoftKeyboard() | |
{ | |
if(isKeyboardShow) | |
{ | |
im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); | |
isKeyboardShow = false; | |
} | |
} | |
public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback) | |
{ | |
softKeyboardThread.setCallback(mCallback); | |
} | |
public void unRegisterSoftKeyboardCallback() | |
{ | |
softKeyboardThread.stopThread(); | |
} | |
public interface SoftKeyboardChanged | |
{ | |
public void onSoftKeyboardHide(); | |
public void onSoftKeyboardShow(); | |
} | |
private int getLayoutCoordinates() | |
{ | |
layout.getLocationOnScreen(coords); | |
return coords[1] + layout.getHeight(); | |
} | |
private void keyboardHideByDefault() | |
{ | |
layout.setFocusable(true); | |
layout.setFocusableInTouchMode(true); | |
} | |
/* | |
* InitEditTexts now handles EditTexts in nested views | |
* Thanks to Francesco Verheye ([email protected]) | |
*/ | |
private void initEditTexts(ViewGroup viewgroup) | |
{ | |
if(editTextList == null) | |
editTextList = new ArrayList<>(); | |
int childCount = viewgroup.getChildCount(); | |
for(int i=0; i<= childCount-1;i++) | |
{ | |
View v = viewgroup.getChildAt(i); | |
if(v instanceof ViewGroup) | |
{ | |
initEditTexts((ViewGroup) v); | |
} | |
if(v instanceof EditText) | |
{ | |
EditText editText = (EditText) v; | |
editText.setOnFocusChangeListener(this); | |
editText.setCursorVisible(true); | |
editTextList.add(editText); | |
} | |
} | |
} | |
/* | |
* OnFocusChange does update tempView correctly now when keyboard is still shown | |
* Thanks to Israel Dominguez ([email protected]) | |
*/ | |
@Override | |
public void onFocusChange(View v, boolean hasFocus) | |
{ | |
if(hasFocus) | |
{ | |
tempView = v; | |
if(!isKeyboardShow) | |
{ | |
layoutBottom = getLayoutCoordinates(); | |
softKeyboardThread.keyboardOpened(); | |
isKeyboardShow = true; | |
} | |
} | |
} | |
// This handler will clear focus of selected EditText | |
private final InnerHandler mHandler; | |
private static class SoftKeyboardChangesThread extends Thread { | |
WeakReference<SoftKeyboard> mSoftKeyboardWeakReference; | |
private AtomicBoolean started; | |
private SoftKeyboardChanged mCallback; | |
public SoftKeyboardChangesThread(SoftKeyboard softKeyboard) { | |
started = new AtomicBoolean(true); | |
mSoftKeyboardWeakReference = new WeakReference<>(softKeyboard); | |
} | |
public void setCallback(SoftKeyboardChanged mCallback) { | |
this.mCallback = mCallback; | |
} | |
@Override | |
public void run() { | |
while(started.get()) { | |
// Wait until keyboard is requested to open | |
synchronized(this) { | |
try { | |
wait(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
if (mSoftKeyboardWeakReference.get() != null && | |
mSoftKeyboardWeakReference.get().mHandler != null) { | |
int currentBottomLocation = mSoftKeyboardWeakReference.get().getLayoutCoordinates(); | |
// There is some lag between open soft-keyboard function and when it really appears. | |
while(currentBottomLocation == mSoftKeyboardWeakReference.get().layoutBottom && started.get()) { | |
currentBottomLocation = mSoftKeyboardWeakReference.get().getLayoutCoordinates(); | |
} | |
if(started.get()) { | |
mCallback.onSoftKeyboardShow(); | |
} | |
// When keyboard is opened from EditText, initial bottom location is greater than layoutBottom | |
// and at some moment equals layoutBottom. | |
// That broke the previous logic, so I added this new loop to handle this. | |
while(currentBottomLocation >= mSoftKeyboardWeakReference.get().layoutBottom && started.get()) { | |
currentBottomLocation = mSoftKeyboardWeakReference.get().getLayoutCoordinates(); | |
} | |
// Now Keyboard is shown, keep checking layout dimensions until keyboard is gone | |
while(currentBottomLocation != mSoftKeyboardWeakReference.get().layoutBottom && started.get()) { | |
synchronized(this) { | |
try { | |
wait(500); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
currentBottomLocation = mSoftKeyboardWeakReference.get().getLayoutCoordinates(); | |
} | |
if(started.get()) { | |
mCallback.onSoftKeyboardHide(); | |
} | |
// if keyboard has been opened clicking and EditText. | |
if(mSoftKeyboardWeakReference.get().isKeyboardShow && started.get()) { | |
mSoftKeyboardWeakReference.get().isKeyboardShow = false; | |
} | |
// if an EditText is focused, remove its focus (on UI thread) | |
if(started.get()) { | |
mSoftKeyboardWeakReference.get().mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget(); | |
} | |
} | |
} | |
} | |
public void keyboardOpened() | |
{ | |
synchronized(this) | |
{ | |
notify(); | |
} | |
} | |
public void stopThread() | |
{ | |
synchronized(this) | |
{ | |
started.set(false); | |
notify(); | |
} | |
} | |
} | |
private static final class InnerHandler extends Handler { | |
private WeakReference<SoftKeyboard> mSoftKeyboardWeakReference; | |
private InnerHandler(SoftKeyboard softKeyboard) { | |
mSoftKeyboardWeakReference = new WeakReference<>(softKeyboard); | |
} | |
@Override | |
public void handleMessage(Message m) { | |
switch(m.what) { | |
case CLEAR_FOCUS: | |
if(mSoftKeyboardWeakReference.get() != null && | |
mSoftKeyboardWeakReference.get().tempView != null) { | |
mSoftKeyboardWeakReference.get().tempView.clearFocus(); | |
mSoftKeyboardWeakReference.get().tempView = null; | |
mSoftKeyboardWeakReference.clear(); | |
} | |
break; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Android Manifest: android:windowSoftInputMode="adjustResize" | |
*/ | |
/* | |
Somewhere else in your code | |
*/ | |
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use the layout root | |
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE); | |
/* | |
Instantiate and pass a callback | |
*/ | |
SoftKeyboard softKeyboard; | |
softKeyboard = new SoftKeyboard(mainLayout, im); | |
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged() | |
{ | |
@Override | |
public void onSoftKeyboardHide() | |
{ | |
// Code here | |
} | |
@Override | |
public void onSoftKeyboardShow() | |
{ | |
// Code here | |
} | |
}); | |
/* | |
Open or close the soft keyboard easily | |
*/ | |
softKeyboard.openSoftKeyboard(); | |
softKeyboard.closeSoftKeyboard(); | |
/* Prevent memory leaks: | |
*/ | |
@Override | |
public void onDestroy() | |
{ | |
super.onDestroy(); | |
softKeyboard.unRegisterSoftKeyboardCallback(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment