web-dev-qa-db-ja.com

Android:ソフトキーボードのオープンを検出する

ソフトキーボードが開いたら、スクロールビューで一番下までスクロールします。

このために使用できます:fullScroll(View.FOCUS_DOWN);

しかし、ソフトキーボードのオープンイベントがトリガーされた後、どうすればそのコマンドを実行できますか?

29
Noah Seidman

この投稿この投稿 のように、Android開発者では、あなたが望むことを行うことができないようです。自分のしていることについてユースケースを再調査する必要があるかもしれません。多分 softInputMode フラグの1つがあなたのために働くでしょう。

22
Rich Schuler

これが私の解決策です:

1 /シンプルなインターフェース

public interface KeyboardVisibilityListener {
    void onKeyboardVisibilityChanged(boolean keyboardVisible);
}

2 /ユーティリティメソッド(たとえば、KeyboardUtilという名前のクラスなど、必要な場所に配置します)

public static void setKeyboardVisibilityListener(Activity activity, KeyboardVisibilityListener keyboardVisibilityListener) {
    View contentView = activity.findViewById(Android.R.id.content);
    contentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        private int mPreviousHeight;

        @Override
        public void onGlobalLayout() {
            int newHeight = contentView.getHeight();
            if (mPreviousHeight != 0) {
                if (mPreviousHeight > newHeight) {
                    // Height decreased: keyboard was shown
                    keyboardVisibilityListener.onKeyboardVisibilityChanged(true);
                } else if (mPreviousHeight < newHeight) {
                    // Height increased: keyboard was hidden
                    keyboardVisibilityListener.onKeyboardVisibilityChanged(false);
                } else {
                    // No change
                }
            }
            mPreviousHeight = newHeight;
        }
    });
}

3 /この方法でアクティビティから使用する(良い場所はonCreateにあります):

KeyboardUtil.setKeyboardVisibilityListener(this, mKeyboardVisibilityListener);
43
BoD

日付を見て、おそらくあなたはあなたの質問に対する解決策を持っています、そうでなければ:

これは、関連する別の質問に対して私が行った同じ応答です: ソフトキーボードが表示されているかどうかを確認する方法はありますか?

デッドリンクを回避するためにここに完全な応答をコピーします:

アクティビティの構成変更を確認してください

これはあなたのAndroidManifest.xml

そして、これはあなたのActivityクラス http://developer.Android.com/reference/Android/app/Activity.html#onConfigurationChanged(Android.content.res。設定)

たとえば、これを処理できるようにするには、アクティビティのパブリックメソッドonConfigurationChanged(Android.content.res.Configuration)を@Overrideする必要があります値:
hardKeyboardHidden
キーボード
keyboardHidden

可能なすべての値を確認してください http://developer.Android.com/reference/Android/content/res/Configuration.html

次のようなものが表示されます。

HARDKEYBOARDHIDDEN_NO   
HARDKEYBOARDHIDDEN_UNDEFINED    
HARDKEYBOARDHIDDEN_YES  
KEYBOARDHIDDEN_NO   
KEYBOARDHIDDEN_UNDEFINED    
KEYBOARDHIDDEN_YES  
KEYBOARD_12KEY  
KEYBOARD_NOKEYS 
KEYBOARD_QWERTY 
KEYBOARD_UNDEFINED

また、次のようなものを読むことができます:

public int  hardKeyboardHidden  A flag indicating whether the hard keyboard has been      hidden.
public int  keyboard    The kind of keyboard attached to the device.
public int  keyboardHidden  A flag indicating whether any keyboard is available.

UPDATE:

ここに私が話していることの特定のサンプルがあります:

http://developer.Android.com/guide/topics/resources/runtime-changes.html

    
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
    // Checks whether a hardware keyboard is available
    if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
        Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
    } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
        Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
    }
}

これがお役に立てば幸いです

7
yeradis

これを回避できる唯一の方法は、アクティビティのAndroid:windowSoftInputMode = "adjustResize"を設定してから、レイアウトにカスタムの「検出器ビュー」を埋め込み、コンテナサイズの変更を処理して、それをカスタムイベントとして(リスナー)ソフトキーボードのオン/オフ。

次の投稿は、それを実装する方法について説明しています: EditTextは、戻るが押されたときに変更をトリガーしません

2
Roberto Andrade

これは私のために働く

parent.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {

            boolean someHasFocus = false;

            if(Host.hasFocus())
                someHasFocus = true;
            if(folder.hasFocus())
                someHasFocus = true;
            if(user.hasFocus())
                someHasFocus = true;
            if(pass.hasFocus())
                someHasFocus = true;

            if(someHasFocus){
                if(bottom>oldBottom){
                    // Keyboard Close
                    viewToHide.setVisibility(View.VISIBLE);

                }else if(bottom<oldBottom){
                   // Keyboard Open
                    viewToHide.setVisibility(View.GONE);
                }

            }else{
                // show
                viewToHide.setVisibility(View.VISIBLE);
            }
        }
    });

Parentがメインレイアウトである場合、viewToHideはキーボードが表示されたときに表示または非表示になるビューであり、Host、folder、userおよびpassは私のフォームのEditTextです。

そしてこれはマニフェスト

Android:windowSoftInputMode="stateHidden|adjustResize"

この助けを願っています

1

これが私の解決策です。 Android:windowSoftInputMode = "adjustResize"は必要ありません

public abstract class KeyboardActivity extends Activity {
    public static final int MIN_KEYBOARD_SIZE = 100;
    private Window mRootWindow;
    private View mRootView;
    private int mKeyboardHeight = -1;
    private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {

    public int height;
    public void onGlobalLayout() {
            Rect r = new Rect();
        View view = mRootWindow.getDecorView();
        view.getWindowVisibleDisplayFrame(r);
        if (height != r.height()) {
            int diff = height - r.height();
            height = r.height();
            if (Math.abs(diff) > MIN_KEYBOARD_SIZE) {
                int diff = height - r.height();
                if (height != 0 && Math.abs(diff) > MIN_KEYBOARD_SIZE) {
                    mKeyboardHeight = Math.abs(diff);
                    if (diff > 0) {
                        onKeyboardOpen();
                    } else {
                        onKeyboardClosed();
                    }
                }
                height = r.height();
            }
        }
    };

    protected abstract void onKeyboardClosed();

    protected abstract void onKeyboardOpen();

    /**
     * Should return keyboard height, if keyboard was shown at least once;
     * @return keyboard height or -1
     */
    protected int getKeyboardHeight() {
        return mKeyboardHeight;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mRootWindow = getWindow();
        mRootView = mRootWindow.getDecorView().findViewById(Android.R.id.content);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
    }

    @Override
    protected void onStop() {
        super.onStop();
        mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
    }
}

次に、このアクティビティから自分のアクティビティを拡張し、onKeyboardClosed/onKeyboardOpenメソッドをオーバーライドします。

1
Grimmy

@ BoDの答え 次の行を削除すると問題なく動作します。

if (mPreviousHeight != 0) {
     /* other code is same, because
        mPreviousHeight is 0 when it comes first */
}
0
venkat

これのために私が同じことをしていたもの:

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

    }
}
_

Activityまたはfragmentでは、このメソッドをonCreate()で呼び出します

_  private void hideAndShowKeyBOrd() {
        InputMethodManager im = (InputMethodManager) getActivity().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() {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                    }
                });
            }

            @Override
            public void onSoftKeyboardShow() {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (viewV.getVisibility() == View.VISIBLE) {
                            viewV.setVisibility(View.GONE);
                        }
                    }
                });

            }
        });
    }
_

コードをお楽しみください:)

0
John smith