SoftKeyboard otwierać i zamykać słuchacza w aktywności w Androidzie?

Mam Activity gdzie jest 5 EditText. Gdy użytkownik kliknie najpierw EditText, wtedy miękka klawiatura otworzy się, aby wprowadzić w niej jakąś wartość. Chcę ustawić inną Widoczność View na Gone gdy miękka klawiatura jest otwarta, gdy użytkownik kliknie pierwszy EditText i gdy miękka klawiatura jest zamknięta z tego samego EditText Na back press, następnie chcę ustawić inną Widoczność View na visible.

Czy jest jakiś listener, callback lub hack, gdy miękka klawiatura otwiera się po kliknięciu na pierwszy EditText W Androidzie?

Author: N Sharma, 2014-08-09

20 answers

To działa tylko wtedy, gdy android:windowSoftInputMode Twojej aktywności jest ustawiona na adjustResize w manifeście. Możesz użyć detektora układu, aby sprawdzić, czy główny układ Twojej aktywności jest zmieniany przez klawiaturę.

Używam czegoś w rodzaju następującej klasy bazowej do moich działań:

public class BaseActivity extends Activity {
    private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
            int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

            LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this);

            if(heightDiff <= contentViewTop){
                onHideKeyboard();

                Intent intent = new Intent("KeyboardWillHide");
                broadcastManager.sendBroadcast(intent);
            } else {
                int keyboardHeight = heightDiff - contentViewTop;
                onShowKeyboard(keyboardHeight);

                Intent intent = new Intent("KeyboardWillShow");
                intent.putExtra("KeyboardHeight", keyboardHeight);
                broadcastManager.sendBroadcast(intent);
            }
        }
    };

    private boolean keyboardListenersAttached = false;
    private ViewGroup rootLayout;

    protected void onShowKeyboard(int keyboardHeight) {}
    protected void onHideKeyboard() {}

    protected void attachKeyboardListeners() {
        if (keyboardListenersAttached) {
            return;
        }

        rootLayout = (ViewGroup) findViewById(R.id.rootLayout);
        rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);

        keyboardListenersAttached = true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (keyboardListenersAttached) {
            rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
        }
    }
}

Poniższy przykład działania używa tego do ukrycia widoku, gdy klawiatura jest pokazana, i pokazuje go ponownie, gdy klawiatura jest ukryta.

Układ xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/rootLayout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">              

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >

        <!-- omitted for brevity -->

    </ScrollView>

    <LinearLayout android:id="@+id/bottomContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <!-- omitted for brevity -->

    </LinearLayout>

</LinearLayout>

I aktywność:

public class TestActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_activity);

        attachKeyboardListeners();
    }

    @Override
    protected void onShowKeyboard(int keyboardHeight) {
        // do things when keyboard is shown
        bottomContainer.setVisibility(View.GONE);
    }

    @Override
    protected void onHideKeyboard() {
        // do things when keyboard is hidden
        bottomContainer.setVisibility(View.VISIBLE);
    }        
}
 68
Author: Jaap van Hengstum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 08:02:00

Jak zauważył Vikram w komentarzach, wykrywanie, czy softkeyboard jest pokazany lub zniknął, jest możliwe tylko przy niektórych brzydkich hakach.

Może wystarczy ustawić fokus na edittext :

yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            //got focus
        } else {
            //lost focus
        }
   }
});
 63
Author: CommonGuy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 07:08:49

Bułka z masłem z niesamowitą biblioteką KeyboardVisibilityEvent: https://android-arsenal.com/details/1/2519

KeyboardVisibilityEvent.setEventListener(
    getActivity(),
    new KeyboardVisibilityEventListener() {
        @Override
        public void onVisibilityChanged(boolean isOpen) {
            // some code depending on keyboard visiblity status
        }
    });

Obsługa wersji min SDK to 14 dla 2.0.0

 50
Author: Gal Rom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-19 06:28:36

Dla Aktywności:

    final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();

                activityRootView.getWindowVisibleDisplayFrame(r);

                int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) { 
                 //enter your code here
                }else{
                 //enter code for hid
                }
            }
        });

Dla Fragmentu:

    view = inflater.inflate(R.layout.live_chat_fragment, null);
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                //r will be populated with the coordinates of your view that area still visible.
                view.getWindowVisibleDisplayFrame(r);

                int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 500) { // if more than 100 pixels, its probably a keyboard...

                }
            }
        });
 36
Author: M Singh Karnawat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-10 12:06:20

Odpowiedź Jaap nie będzie działać dla AppCompatActivity. Zamiast tego uzyskaj wysokość paska stanu i paska nawigacji itp. i porównaj z rozmiarem okna aplikacji.

Like so:

    private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // navigation bar height
        int navigationBarHeight = 0;
        int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            navigationBarHeight = getResources().getDimensionPixelSize(resourceId);
        }

        // status bar height
        int statusBarHeight = 0;
        resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }

        // display window size for the app layout
        Rect rect = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

        // screen height - (user app height + status + nav) ..... if non-zero, then there is a soft keyboard
        int keyboardHeight = rootLayout.getRootView().getHeight() - (statusBarHeight + navigationBarHeight + rect.height());

        if (keyboardHeight <= 0) {
            onHideKeyboard();
        } else {
            onShowKeyboard(keyboardHeight);
        }
    }
};
 25
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41

Możesz spróbować:

private void initKeyBoardListener() {
    // Минимальное значение клавиатуры. Threshold for minimal keyboard height.
    final int MIN_KEYBOARD_HEIGHT_PX = 150;
    // Окно верхнего уровня view. Top-level window decor view.
    final View decorView = getWindow().getDecorView();
    // Регистрируем глобальный слушатель. Register global layout listener.
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        // Видимый прямоугольник внутри окна. Retrieve visible rectangle inside window.
        private final Rect windowVisibleDisplayFrame = new Rect();
        private int lastVisibleDecorViewHeight;

        @Override
        public void onGlobalLayout() {
            decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
            final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();

            if (lastVisibleDecorViewHeight != 0) {
                if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
                    Log.d("Pasha", "SHOW");
                } else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
                    Log.d("Pasha", "HIDE");
                }
            }
            // Сохраняем текущую высоту view до следующего вызова.
            // Save current decor view height for the next call.
            lastVisibleDecorViewHeight = visibleDecorViewHeight;
        }
    });
}
 6
Author: Pavel Dolbik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-05 08:35:30

Użyj tej klasy,

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

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;

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.softKeyboardThread.start();
}

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<EditText>();

    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 Handler mHandler = new Handler()
{
    @Override
    public void handleMessage(Message m)
    {
        switch(m.what)
        {
        case CLEAR_FOCUS:
            if(tempView != null)
            {
                tempView.clearFocus();
                tempView = null;
            }
            break;
        }
    }
};

private class SoftKeyboardChangesThread extends Thread
{
    private AtomicBoolean started;
    private SoftKeyboardChanged mCallback;

    public SoftKeyboardChangesThread()
    {
        started = new AtomicBoolean(true);
    }

    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();
                }
            }

            int currentBottomLocation = getLayoutCoordinates();

            // There is some lag between open soft-keyboard function and when it really appears.
            while(currentBottomLocation == layoutBottom && started.get())
            {
                currentBottomLocation = 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 >= layoutBottom && started.get())
            {
                currentBottomLocation = getLayoutCoordinates();
            }

            // Now Keyboard is shown, keep checking layout dimensions until keyboard is gone
            while(currentBottomLocation != layoutBottom && started.get())
            {
                                    synchronized(this)
                {
                    try 
                    {
                        wait(500);
                    } catch (InterruptedException e) 
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                currentBottomLocation = getLayoutCoordinates();
            }

            if(started.get())
                mCallback.onSoftKeyboardHide();

            // if keyboard has been opened clicking and EditText.
            if(isKeyboardShow && started.get())
                isKeyboardShow = false;

            // if an EditText is focused, remove its focus (on UI thread)
            if(started.get())
                mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget();
        }   
    }

    public void keyboardOpened()
    {
        synchronized(this)
        {
            notify();
        }
    }

    public void stopThread()
    {
        synchronized(this)
        {
            started.set(false);
            notify();
        }
    }

}
}

In Android Manifest, android:windowSoftInputMode="adjustResize" to konieczne.

/*
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();
}

P. S-całkowicie wzięte z tutaj .

 1
Author: Shubham A.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-26 10:40:23

Inna implementacja soft-keyboard-listener, która nie polega na zmianie rozmiaru okna i dlatego działa również dobrze w świecie wielu okien. ma oczywiście swoje własne dziwactwa, ale imo są niczym w porównaniu z kompletnym złamaniem, które jest wykrywaniem wielu okien i okien.

Https://github.com/sqrt1764/AndroidSoftKeyboardListener

Byłbym wdzięczny za pomysły na ulepszenia!

 1
Author: jānis graumanis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-08 06:42:43

Jeśli możesz, spróbuj rozszerzyć EditText i nadpisać metodę 'onKeyPreIme'.

@Override
public void setOnEditorActionListener(final OnEditorActionListener listener) {
    mEditorListener = listener; //keep it for later usage
    super.setOnEditorActionListener(listener);
}

@Override
public boolean onKeyPreIme(final int keyCode, final KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        if (mEditorListener != null) {
            //you can define and use custom listener,
            //OR define custom R.id.<imeId>
            //OR check event.keyCode in listener impl
            //* I used editor action because of ButterKnife @
            mEditorListener.onEditorAction(this, android.R.id.closeButton, event);
        }
    }
    return super.onKeyPreIme(keyCode, event);
}

Jak można go rozszerzyć:

  1. zaimplementuj nasłuchiwanie onFocus i zadeklaruj 'onKeyboardShown'
  2. declare 'onKeyboardHidden'

Myślę, że przeliczanie wysokości ekranu nie jest w 100% skuteczne, jak wspomniano wcześniej. Aby było jasne, nadpisywanie 'onKeyPreIme' nie jest wywoływane przy metodach 'Hide soft keyboard programowo' , ale jeśli robisz to gdziekolwiek, powinieneś to zrobić "onKeyboardHidden" logika tam i nie tworzyć kompleksowe rozwiązania.

 1
Author: zegee29,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-16 21:11:18

Innym podejściem byłoby sprawdzenie, kiedy użytkownik przestał pisać...

Gdy TextEdit jest w Focusie (użytkownik jest / był wpisując) można ukryć widoki (słuchacz focus)

I użyj funkcji obsługi + Runnable i słuchacza zmiany tekstu, aby zamknąć klawiaturę (niezależnie od jej widoczności) i pokazać widoki po pewnym opóźnieniu.

Najważniejszą rzeczą, na którą należy zwrócić uwagę, byłoby opóźnienie, którego używasz, które zależałoby od treści tych tekstów.

Handler timeoutHandler = new Handler();
Runnable typingRunnable = new Runnable() {
    public void run() {
        // current TextEdit
        View view = getCurrentFocus();

        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        // reset focus
        view.clearFocus();
        // close keyboard (whether its open or not)
        imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);

        // SET VIEWS VISIBLE
    }
};

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // SET VIEWS GONE

            // reset handler
            timeoutHandler.removeCallbacks(typingRunnable);
            timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT);
        }
    }
});

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // Reset Handler...
        timeoutHandler.removeCallbacks(typingRunnable);
    }

    @Override
    public void afterTextChanged(Editable s) {
        // Reset Handler Cont.
        if (editText.getText().toString().trim().length() > 0) {
            timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT);
        }
    }
});
 1
Author: Ullauri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-14 02:05:10
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainactivity);
    attachKeyboardListeners();
    ....
    yourEditText1.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                yourEditText2.setVisibility(View.GONE);
                yourEditText3.setVisibility(View.GONE);
                yourEditText4.setVisibility(View.GONE);
                yourEditText5.setVisibility(View.GONE);
            } else {
                yourEditText2.setVisibility(View.VISIBLE);
                yourEditText3.setVisibility(View.VISIBLE);
                yourEditText4.setVisibility(View.VISIBLE);
                yourEditText5.setVisibility(VISIBLE);
            }
       }
    });
    }
}
 0
Author: Sagar Pilkhwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-11 07:51:31

Niestety nie mam wystarczająco wysokiej reputacji, aby skomentować odpowiedź Jaapa van Hengstuma. Ale czytam kilka komentarzy ludzi, którzy mają problem, że {[0] } jest zawsze 0 i że onShowKeyboard(...) jest zawsze nazywany.

Miałem ten sam problem i zorientowałem się, jaki mam problem. Użyłem AppCompatActivity zamiast "normalnego" Activity. W tym przypadku Window.ID_ANDROID_CONTENT odnosi się do ContentFrameLayout, a nie do FrameLayout z prawą górną wartością. W moim przypadku dobrze było użyć "normalnego" Activity, jeśli trzeba użyć kolejny typ aktywności (właśnie testowałem AppCompatActivity, może to również problem z innymi typami aktywności, takimi jak FragmentActivity), musisz uzyskać dostęp do FrameLayout, który jest przodkiem ContentFrameLayout.

 0
Author: agi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-06 13:23:33

W przypadku adjustResize i FragmentActivity przyjęte rozwiązanie z @Jaap nie działa dla mnie.

Oto moje rozwiązanie:

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    private int contentDiff;
    private int rootHeight;
    @Override
    public void onGlobalLayout() {
        View contentView = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
        if (rootHeight != mDrawerLayout.getRootView().getHeight()) {
            rootHeight = mDrawerLayout.getRootView().getHeight();
            contentDiff = rootHeight - contentView.getHeight();
            return;
        }
        int newContentDiff = rootHeight - contentView.getHeight();
        if (contentDiff != newContentDiff) {
            if (contentDiff < newContentDiff) {
                onShowKeyboard(newContentDiff - contentDiff);
            } else {
                onHideKeyboard();
            }
            contentDiff = newContentDiff;
        }
    }
};
 0
Author: AnoDest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-23 11:01:43

Gdy klawiatura Pokaż

rootLayout.getHeight() < rootLayout.getRootView().getHeight() - getStatusBarHeight() 

Is true, else hide

 0
Author: 余艳辉,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-09 10:36:24
private boolean isKeyboardShown = false;
private int prevContentHeight = 0;
private ViewGroup contentLayout;

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener =
        new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        int contentHeight = contentLayout.getHeight();
        int rootViewHeight = contentLayout.getRootView().getHeight();

        if (contentHeight > 0) {

            if (!isKeyboardShown) {
                if (contentHeight < prevContentHeight) {
                    isKeyboardShown = true;
                    onShowKeyboard(rootViewHeight - contentHeight);
                }
            } else {
                if (contentHeight > prevContentHeight) {
                    isKeyboardShown = false;
                    onHideKeyboard();
                }
            }

            prevContentHeight = contentHeight;
        }
    }
};

Trochę zmodyfikowałem akceptowaną odpowiedź Jaap. Ale w moim przypadku jest kilka założeń, takich jak android:windowSoftInputMode=adjustResize i klawiatura nie pojawia się na początku, gdy aplikacja się uruchamia. A także, zakładam, że ekran w odniesieniu pasuje do wysokości rodzica.

contentHeight > 0 to sprawdzenie pozwala mi wiedzieć, czy ekran dotyczący jest ukryty lub pokazany, aby zastosować nasłuchiwanie zdarzeń klawiatury dla tego konkretnego ekranu. Również przekazuję widok układu ekranu w attachKeyboardListeners(<your layout view here>) w mojej głównej aktywności onCreate() metoda. Za każdym razem, gdy zmienia się wysokość ekranu, zapisuję go do zmiennej prevContentHeight, aby później sprawdzić, czy klawiatura jest pokazana czy ukryta.

Jak dla mnie, do tej pory udało się to całkiem nieźle. Mam nadzieję, że to działa również na innych.
 0
Author: psychoplasma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-03 08:21:33

Odpowiedź"Jaap van Hengstum" działa dla mnie, ale nie ma potrzeby, aby ustawić "android: windowSoftInputMode", jak właśnie powiedział!

Zmniejszyłem go (teraz wykrywa to, co chcę, właściwie zdarzenie dotyczące pokazywania i ukrywania klawiatury):

private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
        int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
        if(heightDiff <= contentViewTop){
            onHideKeyboard();
        } else {
            onShowKeyboard();
        }
    }
};

private boolean keyboardListenersAttached = false;
private ViewGroup rootLayout;

protected void onShowKeyboard() {}
protected void onHideKeyboard() {}

protected void attachKeyboardListeners() {
    if (keyboardListenersAttached) {
        return;
    }

    rootLayout = (ViewGroup) findViewById(R.id.CommentsActivity);
    rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);

    keyboardListenersAttached = true;
}

@Override
protected void onDestroy() {
    super.onDestroy();

    if (keyboardListenersAttached) {
        rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener);
    }
}

I nie zapomnij dodać tego

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_comments);
    attachKeyboardListeners();}
 0
Author: Khalil Yossefi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-20 14:38:13

Ten kod działa bardzo ładnie

Użyj tej klasy dla widoku głównego:

public class KeyboardConstraintLayout extends ConstraintLayout {

private KeyboardListener keyboardListener;
private EditText targetEditText;
private int minKeyboardHeight;
private boolean isShow;

public KeyboardConstraintLayout(Context context) {
    super(context);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); //128dp
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!isInEditMode()) {
        Activity activity = (Activity) getContext();
        @SuppressLint("DrawAllocation")
        Rect rect = new Rect();
        getWindowVisibleDisplayFrame(rect);

        int statusBarHeight = rect.top;
        int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight;

        if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) {
            if (keyboardHeight > minKeyboardHeight) {
                if (!isShow) {
                    isShow = true;
                    keyboardListener.onKeyboardVisibility(true);
                }
            }else {
                if (isShow) {
                    isShow = false;
                    keyboardListener.onKeyboardVisibility(false);
                }
            }
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public boolean isShowKeyboard() {
    return isShow;
}

public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) {
    this.targetEditText = targetEditText;
    this.keyboardListener = keyboardListener;
}

public interface KeyboardListener {
    void onKeyboardVisibility (boolean isVisible);
}

}

I ustaw słuchacz klawiatury w aktywności lub fragmencie:

        rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() {
        @Override
        public void onKeyboardVisibility(boolean isVisible) {

        }
    });
 0
Author: saleh gholamian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 16:02:54

To zadziała bez potrzeby zmiany aktywności android:windowSoftInputMode

Krok 1: rozszerzenie klasy EditText i nadpisanie tych dwóch:

@Override
public void setOnEditorActionListener(final OnEditorActionListener listener) {
    mEditorListener = listener;
    super.setOnEditorActionListener(listener);
}

@Override
public boolean onKeyPreIme(final int keyCode, final KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
        if (mEditorListener != null) {
            mEditorListener.onEditorAction(this, android.R.id.closeButton, event);
        }
    }
    return super.onKeyPreIme(keyCode, event);
}

Krok 2: Utwórz te dwa w swojej aktywności:

private void initKeyboard() {
    final AppEditText editText = findViewById(R.id.some_id);
    editText.setOnFocusChangeListener(new OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            setKeyboard(hasFocus);
        }
    });
    editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (event == null || event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                editText.clearFocus();
            }
            return false;
        }
    });
}

public void setKeyboard(boolean isShowing) {
    // do something
}

*** pamiętaj, aby clearFocus zadziałało, musisz skupić się na rodzicu lub pierwszym dziecku w hierarchii rodzicielskiej.

    setFocusableInTouchMode(true);
    setFocusable(true);
 0
Author: kasra fallen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-02 17:38:54

Możesz użyć mojej funkcji rozszerzenia RX (Kotlin).

/**
 * @return [Observable] to subscribe on keyboard visibility changes.
 */
fun Activity.keyboardVisibilityChanges(): Observable<Boolean> {

    // flag indicates whether keyboard is open
    var isKeyboardOpen = false

    val notifier: PublishSubject<Boolean> = PublishSubject.create()

    // approximate keyboard height
    val approximateKeyboardHeight = 100.fromDpToPx()

    // device screen height
    val screenHeight: Int = Resources.getSystem().displayMetrics.heightPixels

    val visibleDisplayFrame = Rect()
    with(window.decorView) {
        viewTreeObserver.addOnDrawListener {
            getWindowVisibleDisplayFrame(visibleDisplayFrame)

            val keyboardHeight =
                screenHeight - (visibleDisplayFrame.bottom - visibleDisplayFrame.top)

            val keyboardOpen = keyboardHeight >= approximateKeyboardHeight

            val hasChanged = isKeyboardOpen xor keyboardOpen

            if (hasChanged) {
                isKeyboardOpen = keyboardOpen
                notifier.onNext(keyboardOpen)
            }
        }
    }

    return notifier
}
 0
Author: Vlad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 07:36:30

To nie działa zgodnie z życzeniem...

... widziałem wiele użyć obliczenia wielkości, aby sprawdzić ...

Chciałem ustalić, czy jest otwarta, czy nie i znalazłem isAcceptingText()

Więc to naprawdę nie odpowiada na pytanie, ponieważ nie odnosi się do otwierania lub zamykania raczej jak jest otwarte lub zamknięte, więc jest to powiązany kod, który może pomóc innym w różnych scenariuszach...

W aktywności

    if (((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
    } else {
        Log.d(TAG,"Software Keyboard was not shown");
    }

We fragmencie

    if (((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
    } else {
        Log.d(TAG,"Software Keyboard was not shown");

    }
 0
Author: CrandellWS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-08 01:16:09