क्या एंड्रॉइड में यह पता लगाने का कोई तरीका है कि सॉफ्टवेयर (उर्फ "सॉफ्ट") कीबोर्ड स्क्रीन पर दिखाई देता है या नहीं?
क्या एंड्रॉइड में यह पता लगाने का कोई तरीका है कि सॉफ्टवेयर (उर्फ "सॉफ्ट") कीबोर्ड स्क्रीन पर दिखाई देता है या नहीं?
जवाबों:
इसका कोई सीधा तरीका नहीं है - http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a देखें, जहां एंड्रॉइड टीम के डायन हैकर ने जवाब दिया है। हालाँकि, आप यह अप्रत्यक्ष रूप से जाँच कर सकते हैं कि क्या विंडो का आकार #onMeasure में बदला गया है। देखें एंड्रॉयड में सॉफ्टवेयर कुंजीपटल की दृश्यता की जांच कैसे करें? ।
यह मेरे लिए काम करता है। शायद यह हमेशा सभी संस्करणों के लिए सबसे अच्छा तरीका है ।
कीबोर्ड दृश्यता की संपत्ति बनाना और देरी से किए गए इस बदलाव का निरीक्षण करना प्रभावी होगा क्योंकि ऑनग्लोबलआउट विधि कई बार कॉल करती है। इसके अलावा डिवाइस के रोटेशन की जांच करना अच्छा है और windowSoftInputMode
ऐसा नहीं है adjustNothing
।
boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
print("keyboard " + opened);
}
// ContentView is the root view of the layout of this activity/fragment
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
contentView.getWindowVisibleDisplayFrame(r);
int screenHeight = contentView.getRootView().getHeight();
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
int keypadHeight = screenHeight - r.bottom;
Log.d(TAG, "keypadHeight = " + keypadHeight);
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
// keyboard is opened
if (!isKeyboardShowing) {
isKeyboardShowing = true
onKeyboardVisibilityChanged(true)
}
}
else {
// keyboard is closed
if (isKeyboardShowing) {
isKeyboardShowing = false
onKeyboardVisibilityChanged(false)
}
}
}
});
contentView
घोषित किया गया है?
इसे इस्तेमाल करे:
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
writeToLog("Software Keyboard was shown");
} else {
writeToLog("Software Keyboard was not shown");
}
मैंने एक साधारण वर्ग बनाया, जिसका उपयोग इसके लिए किया जा सकता है: https://github.com/ravindu1024/android-keyboardlistener । बस इसे अपनी परियोजना में कॉपी करें और निम्नानुसार उपयोग करें:
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
@Override
public void onToggleSoftKeyboard(boolean isVisible)
{
Log.d("keyboard", "keyboard visible: "+isVisible);
}
});
rootView
इस मामले में मेरे मूल दृष्टिकोण की ओर इशारा करने वाला एक दृश्य है relative layout
:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/addresses_confirm_root_view"
android:background="@color/WHITE_CLR">
RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);
getViewTreeObserver()
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
if (heightDiff > 100) {
Log.e("MyActivity", "keyboard opened");
} else {
Log.e("MyActivity", "keyboard closed");
}
}
});
1
। कोई बात नहीं। केवल यह कीबोर्ड की वास्तविक लंबाई से कम होना चाहिए
मैंने इसे एक आधार के रूप में इस्तेमाल किया: http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
public int result = -1;
public IMMResult() {
super(null);
}
@Override
public void onReceiveResult(int r, Bundle data) {
result = r;
}
// poll result value for up to 500 milliseconds
public int getResult() {
try {
int sleep = 0;
while (result == -1 && sleep < 500) {
Thread.sleep(100);
sleep += 100;
}
} catch (InterruptedException e) {
Log.e("IMMResult", e.getMessage());
}
return result;
}
}
फिर इस विधि को लिखा:
public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {
IMMResult result = new IMMResult();
int res;
imm.showSoftInput(v, 0, result);
// if keyboard doesn't change, handle the keypress
res = result.getResult();
if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {
return true;
}
else
return false;
}
फिर आप सभी फ़ील्ड (EditText, AutoCompleteTextView, आदि) का परीक्षण करने के लिए इसका उपयोग कर सकते हैं, जिसने एक सॉफ्टफ़ोन फ़ोल्डर खोला हो सकता है:
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
//close the softkeyboard
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
Addmittely एक आदर्श समाधान नहीं है, लेकिन यह काम हो जाता है।
आप कीबोर्ड की स्थिति की जांच करने के लिए showSoftInput () और HideSoftInput () के कॉलबैक परिणाम का उपयोग कर सकते हैं। पूर्ण विवरण और उदाहरण कोड
http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
आप इस उत्तर का उल्लेख कर सकते हैं - https://stackoverflow.com/a/24105062/3629912
इसने मेरे लिए हर समय काम किया।
adb shell dumpsys window InputMethod | grep "mHasSurface"
यह सच है, अगर सॉफ्टवेयर कीबोर्ड दिखाई देता है।
इसलिए AccessibilityServices, विंडो इनसेट, स्क्रीन की ऊंचाई का पता लगाने आदि के साथ खेलने के लंबे समय के बाद, मुझे लगता है कि मुझे ऐसा करने का एक तरीका मिला।
अस्वीकरण: यह एंड्रॉइड में एक छिपी हुई विधि का उपयोग करता है, जिसका अर्थ है कि यह सुसंगत नहीं हो सकता है। हालांकि, मेरे परीक्षण में, यह काम करने लगता है।
यह विधि InputMethodManager # getInputMethodWindowVanishHeight () है , और यह लॉलीपॉप (5.0) के बाद से मौजूद है।
वह कॉलिंग जो वर्तमान कीबोर्ड के पिक्सेल में, ऊँचाई को लौटाती है। सिद्धांत रूप में, एक कीबोर्ड 0 पिक्सेल लंबा नहीं होना चाहिए, इसलिए मैंने एक साधारण ऊंचाई जांच की (कोटलिन में):
val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
//keyboard is shown
else {
//keyboard is hidden
}
जब मैं छिपी हुई विधियों को कॉल करता हूं, तो मैं एंड्रॉइड छिपे हुए एपीआई का उपयोग करता हूं (मैं उन ऐप के लिए बहुत कुछ करता हूं जो मैं विकसित करता हूं, जो ज्यादातर हैक / ट्यूनर ऐप हैं), लेकिन यह प्रतिबिंब के साथ भी संभव होना चाहिए:
val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic
यह मेरी ज़रूरतों के लिए बहुत कम जटिल था। आशा है कि यह मदद कर सकता है:
मुख्यता पर:
public void dismissKeyboard(){
InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
mKeyboardStatus = false;
}
public void showKeyboard(){
InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
mKeyboardStatus = true;
}
private boolean isKeyboardActive(){
return mKeyboardStatus;
}
MKeyboardStatus के लिए डिफ़ॉल्ट प्राइमरी बूलियन वैल्यू को झूठे के लिए इनिशियलाइज़ किया जाएगा ।
फिर निम्नानुसार मान की जांच करें, और यदि आवश्यक हो तो एक क्रिया करें:
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
यदि आपको कीबोर्ड की स्थिति की जांच करने की आवश्यकता है तो यह काम करना चाहिए:
fun Activity.isKeyboardOpened(): Boolean {
val r = Rect()
val activityRoot = getActivityRoot()
val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)
activityRoot.getWindowVisibleDisplayFrame(r)
val heightDiff = activityRoot.rootView.height - r.height()
return heightDiff > visibleThreshold;
}
fun Activity.getActivityRoot(): View {
return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}
जहाँ UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP
= 100 और डुबकी () एक aco func है जो dpToPx को परिवर्तित करता है:
fun dip(value: Int): Int {
return (value * Resources.getSystem().displayMetrics.density).toInt()
}
मैंने GlobalLayoutListener की स्थापना इस प्रकार की:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 3) {
//Make changes for Keyboard not visible
} else {
//Make changes for keyboard visible
}
}
});
इस कोड की कोशिश करो यह वास्तव में काम कर रहा है यदि KeyboardShown दिखाया गया है तो यह फ़ंक्शन सही मान लौटाता है ...।
private final String TAG = "TextEditor";
private TextView mTextEditor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
mTextEditor = (TextView) findViewById(R.id.text_editor);
mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
isKeyboardShown(mTextEditor.getRootView());
}
});
}
private boolean isKeyboardShown(View rootView) {
/* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
/* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
int heightDiff = rootView.getBottom() - r.bottom;
/* Threshold size: dp to pixels, multiply with display density */
boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;
Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
+ "root view height:" + rootView.getHeight() + ", rect:" + r);
return isKeyboardShown;
}
मेरे मामले EditText
में मेरे पास मेरे लेआउट में प्रबंधन करने के लिए केवल एक था इसलिए मैं इस समाधान को सफेद कर आया । यह अच्छी तरह से काम करता है, मूल रूप से यह एक रिवाज है EditText
जो फ़ोकस के लिए सुनता है और एक स्थानीय प्रसारण भेजता है अगर फ़ोकस बदलता है या यदि बैक / किया हुआ बटन दबाया जाता है। काम करने के लिए आपको View
अपने लेआउट में एक डमी रखने की आवश्यकता होती है android:focusable="true"
और android:focusableInTouchMode="true"
क्योंकि जब आप कॉल clearFocus()
करते हैं तो फ़ोकस को पहले फ़ोकस करने योग्य दृश्य पर फिर से असाइन किया जाएगा। डमी दृश्य का उदाहरण:
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>
अतिरिक्त infos
समाधान जो लेआउट परिवर्तनों में अंतर का पता लगाता है, बहुत अच्छी तरह से काम नहीं करता है क्योंकि यह दृढ़ता से स्क्रीन घनत्व पर निर्भर करता है, क्योंकि 100px एक निश्चित डिवाइस में बहुत कुछ हो सकता है और कुछ अन्य में कुछ भी नहीं जो आपको झूठी सकारात्मक मिल सकती है। इसके अलावा विभिन्न विक्रेताओं के पास अलग-अलग कीबोर्ड हैं।
Android में आप ADB शेल के माध्यम से पता लगा सकते हैं। मैंने इस विधि को लिखा और उपयोग किया है:
{
JSch jsch = new JSch();
try {
Session session = jsch.getSession("<userName>", "<IP>", 22);
session.setPassword("<Password>");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
BufferedReader in = new BufferedReader(new
InputStreamReader(channel.getInputStream()));
channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window
InputMethod | findstr \"mHasSurface\"");
channel.connect();
String msg = null;
String msg2 = " mHasSurface=true";
while ((msg = in.readLine()) != null) {
Boolean isContain = msg.contains(msg2);
log.info(isContain);
if (isContain){
log.info("Hiding keyboard...");
driver.hideKeyboard();
}
else {
log.info("No need to hide keyboard.");
}
}
channel.disconnect();
session.disconnect();
} catch (JSchException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int screenHeight = activityRootView.getRootView().getHeight();
Log.e("screenHeight", String.valueOf(screenHeight));
int heightDiff = screenHeight - (r.bottom - r.top);
Log.e("heightDiff", String.valueOf(heightDiff));
boolean visible = heightDiff > screenHeight / 3;
Log.e("visible", String.valueOf(visible));
if (visible) {
Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
}
}
});
@IWantScala का उत्तर बहुत अच्छा है लेकिन मेरे लिए काम नहीं करना
rootView.getRootView().getHeight()
हमेशा समान मूल्य रखता है
एक तरीका दो वेरिएंट को परिभाषित करना है
private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;
वैश्विक श्रोता जोड़ें
rootView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentRootViewHeight = rootView.getHeight();
if (currentRootViewHeight > maxRootViewHeight) {
maxRootViewHeight = currentRootViewHeight;
}
}
});
तो जाँच
if (currentRootViewHeight >= maxRootViewHeight) {
// Keyboard is hidden
} else {
// Keyboard is shown
}
ठीक काम करता है
अंत में अब कोटलिन पर आधारित Android R से शुरू होने वाला एक सीधा रास्ता है।
val imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
//Ime is visible
//Lets move our view by the height of the IME
view.translationX = imeInsets.bottom }
मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था। मुझे स्क्रीन पर एंटर बटन (जो कि कीबोर्ड छिपाया गया था) पर प्रतिक्रिया करने की आवश्यकता थी। इस मामले में आप पाठ दृश्य के OnEditorAction की सदस्यता ले सकते हैं, कीबोर्ड के साथ opend था - यदि आपके पास कई संपादन योग्य बॉक्स हैं, तो उन सभी की सदस्यता लें।
आपकी गतिविधि में आपके पास कीबोर्ड का पूर्ण नियंत्रण है, इसलिए किसी भी बिंदु पर आपको इस समस्या का सामना नहीं करना पड़ेगा कि क्या आप सभी उद्घाटन और समापन घटनाओं को सुनते हैं या नहीं।
इसका पता लगाने के लिए एक सीधा तरीका है। और, इसमें लेआउट परिवर्तन की आवश्यकता नहीं है।
तो यह इमर्सिव फुलस्क्रीन मोड में भी काम करता है।
लेकिन, दुर्भाग्य से, यह सभी उपकरणों पर काम नहीं करता है। तो आपको इसे अपने डिवाइस (ओं) के साथ परीक्षण करना होगा।
चाल यह है कि आप नरम कीबोर्ड को छिपाने या दिखाने की कोशिश करते हैं और उस कोशिश के परिणाम को कैप्चर करते हैं।
यदि यह सही काम करता है तो कीबोर्ड वास्तव में दिखाया या छिपाया नहीं गया है। हम सिर्फ राज्य के लिए कहते हैं।
अप-टू-डेट रहने के लिए, आप बस इस ऑपरेशन को दोहराते हैं, जैसे हर 200 मिलीसेकंड, एक हैंडलर का उपयोग करके।
नीचे दिए गए कार्यान्वयन में केवल एक ही चेक है।
यदि आप कई जांच करते हैं, तो आपको सभी (_keyboardV अदृश्य) परीक्षणों को सक्षम करना चाहिए।
public interface OnKeyboardShowHide
{
void onShowKeyboard( Object param );
void onHideKeyboard( Object param );
}
private static Handler _keyboardHandler = new Handler();
private boolean _keyboardVisible = false;
private OnKeyboardShowHide _keyboardCallback;
private Object _keyboardCallbackParam;
public void start( OnKeyboardShowHide callback, Object callbackParam )
{
_keyboardCallback = callback;
_keyboardCallbackParam = callbackParam;
//
View view = getCurrentFocus();
if (view != null)
{
InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
}
else // if (_keyboardVisible)
{
_keyboardVisible = false;
_keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
}
}
private ResultReceiver _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
@Override
protected void onReceiveResult( int resultCode, Bundle resultData )
{
switch (resultCode)
{
case InputMethodManager.RESULT_SHOWN :
case InputMethodManager.RESULT_UNCHANGED_SHOWN :
// if (!_keyboardVisible)
{
_keyboardVisible = true;
_keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
}
break;
case InputMethodManager.RESULT_HIDDEN :
case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
// if (_keyboardVisible)
{
_keyboardVisible = false;
_keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
}
break;
}
}
};
यहां यह जानने के लिए वर्कअराउंड किया गया है कि सॉफ्टबैंक दिखाई दे रहा है या नहीं।
कुछ लोकप्रिय कीबोर्ड में उनके वर्गनाम में कुछ कीवर्ड हैं:
ActivityManager.RunningServiceInfo से, ClassNames में उपरोक्त पैटर्न की जाँच करें। इसके अलावा, ActivManager.RunningServiceInfo के क्लाइंटपैक = एंड्रॉइड, जो यह दर्शाता है कि कीबोर्ड सिस्टम से जुड़ा है।
उपर्युक्त जानकारी को नरम कीबोर्ड दिखाई देने का पता लगाने के लिए एक सख्त तरीके से जोड़ा जा सकता है।
जैसा कि आप जानते हैं कि एंड्रॉइड सॉफ्टवेयर कीबोर्ड तभी दिखाई देगा जब टाइपिंग की एक संभावित घटना हो। दूसरे शब्दों में, कीबोर्ड केवल तभी दिखाई देता है जब EditText केंद्रित होता है। इसका मतलब है कि आप मौसम को देख सकते हैं कि कीबोर्ड दिखाई दे रहा है या नहीं OnFocusChangeListener का उपयोग करके ।
//Declare this Globally
public boolean isKeyBoardVisible = false;
//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*
text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
isKeyBoardVisible = true;
else
isKeyBoardVisible = false;
}
});
अब आप मौसम खुला है या नहीं, मौसम पाने के लिए वर्ग में कहीं भी KKBBardV अदृश्य चर का उपयोग कर सकते हैं । इसने मेरे लिए अच्छा काम किया।
नोट: यह प्रक्रिया तब काम नहीं करती जब कीबोर्ड InputMethodManager का उपयोग करके प्रोग्रामेटिक रूप से खोला जाता है क्योंकि यह OnFocusChangeListener को इनवोक नहीं करता है।
मैंने कोटलिन के उत्तर को बदल दिया, आशा है कि यह कोटलिन उपयोगकर्ताओं के लिए मदद करता है।
private fun checkKeyboardVisibility() {
var isKeyboardShowing = false
binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
binding.coordinator.getWindowVisibleDisplayFrame(r)
val screenHeight = binding.coordinator.rootView.height
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
val keypadHeight = screenHeight - r.bottom
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
// keyboard is opened
if (!isKeyboardShowing) {
isKeyboardShowing = true
}
} else {
// keyboard is closed
if (isKeyboardShowing) {
isKeyboardShowing = false
}
}
}
}
यह गतिविधि और जीवन चक्र की घटनाओं के समायोजन ध्वज के साथ काम करता है। कोटलिन के साथ भी:
/**
* This class uses a PopupWindow to calculate the window height when the floating keyboard is opened and closed
*
* @param activity The parent activity
* The root activity that uses this KeyboardManager
*/
class KeyboardManager(private val activity: AppCompatActivity) : PopupWindow(activity), LifecycleObserver {
private var observerList = mutableListOf<((keyboardTop: Int) -> Unit)>()
/** The last value of keyboardTop */
private var keyboardTop: Int = 0
/** The view that is used to calculate the keyboard top */
private val popupView: View?
/** The parent view */
private var parentView: View
var isKeyboardShown = false
private set
/**
* Create transparent view which will be stretched over to the full screen
*/
private fun createFullScreenView(): View {
val view = LinearLayout(activity)
view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
view.background = ColorDrawable(Color.TRANSPARENT)
return view
}
init {
this.popupView = createFullScreenView()
contentView = popupView
softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE or LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
inputMethodMode = INPUT_METHOD_NEEDED
parentView = activity.findViewById(android.R.id.content)
width = 0
height = LayoutParams.MATCH_PARENT
popupView.viewTreeObserver.addOnGlobalLayoutListener {
val rect = Rect()
popupView.getWindowVisibleDisplayFrame(rect)
val keyboardTop = rect.bottom
if (this.keyboardTop != keyboardTop) {
isKeyboardShown = keyboardTop < this.keyboardTop
this.keyboardTop = keyboardTop
observerList.forEach { it(keyboardTop) }
}
}
activity.lifecycle.addObserver(this)
}
/**
* This must be called after the onResume of the Activity or inside view.post { } .
* PopupWindows are not allowed to be registered before the onResume has finished
* of the Activity
*/
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun start() {
parentView.post {
if (!isShowing && parentView.windowToken != null) {
setBackgroundDrawable(ColorDrawable(0))
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
}
}
}
/**
* This manager will not be used anymore
*/
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun close() {
activity.lifecycle.removeObserver(this)
observerList.clear()
dismiss()
}
/**
* Set the keyboard top observer. The observer will be notified when the keyboard top has changed.
* For example when the keyboard is opened or closed
*
* @param observer The observer to be added to this provider
*/
fun registerKeyboardTopObserver(observer: (keyboardTop: Int) -> Unit) {
observerList.add(observer)
}
}
कीबोर्ड के ऊपर हमेशा दृश्य रखने की उपयोगी विधि
fun KeyboardManager.updateBottomMarginIfKeyboardShown(
view: View,
activity: AppCompatActivity,
// marginBottom of view when keyboard is hide
marginBottomHideKeyboard: Int,
// marginBottom of view when keybouard is shown
marginBottomShowKeyboard: Int
) {
registerKeyboardTopObserver { bottomKeyboard ->
val bottomView = ViewUtils.getFullViewBounds(view).bottom
val maxHeight = ScreenUtils.getFullScreenSize(activity.windowManager).y
// Check that view is within the window size
if (bottomView < maxHeight) {
if (bottomKeyboard < bottomView) {
ViewUtils.updateMargin(view, bottomMargin = bottomView - bottomKeyboard +
view.marginBottom + marginBottomShowKeyboard)
} else ViewUtils.updateMargin(view, bottomMargin = marginBottomHideKeyboard)
}
}
}
जहां getFullViewBounds
fun getLocationOnScreen(view: View): Point {
val location = IntArray(2)
view.getLocationOnScreen(location)
return Point(location[0], location[1])
}
fun getFullViewBounds(view: View): Rect {
val location = getLocationOnScreen(view)
return Rect(location.x, location.y, location.x + view.width,
location.y + view.height)
}
जहां getFullScreenSize है
fun getFullScreenSize(wm: WindowManager? = null) =
getScreenSize(wm) { getRealSize(it) }
private fun getScreenSize(wm: WindowManager? = null, block: Display.(Point) -> Unit): Point {
val windowManager = wm ?: App.INSTANCE.getSystemService(Context.WINDOW_SERVICE)
as WindowManager
val point = Point()
windowManager.defaultDisplay.block(point)
return point
}
जहां अपडेट करें
fun updateMargin(
view: View,
leftMargin: Int? = null,
topMargin: Int? = null,
rightMargin: Int? = null,
bottomMargin: Int? = null
) {
val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
if (leftMargin != null) layoutParams.leftMargin = leftMargin
if (topMargin != null) layoutParams.topMargin = topMargin
if (rightMargin != null) layoutParams.rightMargin = rightMargin
if (bottomMargin != null) layoutParams.bottomMargin = bottomMargin
view.layoutParams = layoutParams
}
मैंने इसे निम्नानुसार किया है, लेकिन इसका रीलेव केवल तभी होगा जब आपका लक्ष्य कीबोड को बंद / खोलना है।
घनिष्ठ उदाहरण: (यदि कीबोर्ड पहले से ही बंद है, यदि नहीं - बंद हो रहा है)
imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
});
एक का उपयोग कर सकते हैं:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(
getClass().getSimpleName(),
String.format("conf: %s", newConfig));
if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
onHardwareKeyboardChange(newConfig.hardKeyboardHidden);
hardKeyboardHidden = newConfig.hardKeyboardHidden;
}
if (newConfig.keyboardHidden != keyboardHidden) {
onKeyboardChange(newConfig.keyboardHidden);
keyboardHidden = newConfig.hardKeyboardHidden;
}
}
public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;
//todo
private void onKeyboardChange(int keyboardHidden) {
}
//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {
}
मैंने नमूना लिखा ।
यह भंडार इस धारणा के बिना कीबोर्ड की स्थिति का पता लगाने में मदद कर सकता है कि "कीबोर्ड स्क्रीन के एक्स भाग से अधिक होना चाहिए"
अगर आप अपने ऐप में AndroidR के लिए एप का समर्थन करते हैं तो आप नीचे दिए गए तरीके का उपयोग कर सकते हैं।
In kotlin :
var imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
view.translationX = imeInsets.bottom
}
नोट: यह केवल AndroidR के लिए उपलब्ध है और Android संस्करण के नीचे कुछ अन्य उत्तर का पालन करने की आवश्यकता है या मैं इसके लिए इसे अपडेट करूंगा।