How to capture the “virtual keyboard show/hide” event in Android?

前端 未结 16 1196
暗喜
暗喜 2020-11-22 07:23

I would like to alter the layout based on whether the virtual keyboard is shown or not. I\'ve searched the API and various blogs but can\'t seem to find anything useful.

相关标签:
16条回答
  • 2020-11-22 08:17

    If you want to handle show/hide of IMM (virtual) keyboard window from your Activity, you'll need to subclass your layout and override onMesure method(so that you can determine the measured width and the measured height of your layout). After that set subclassed layout as main view for your Activity by setContentView(). Now you'll be able to handle IMM show/hide window events. If this sounds complicated, it's not that really. Here's the code:

    main.xml

       <?xml version="1.0" encoding="utf-8"?>
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >
            <EditText
                 android:id="@+id/SearchText" 
                 android:text="" 
                 android:inputType="text"
                 android:layout_width="fill_parent"
                 android:layout_height="34dip"
                 android:singleLine="True"
                 />
            <Button
                 android:id="@+id/Search" 
                 android:layout_width="60dip"
                 android:layout_height="34dip"
                 android:gravity = "center"
                 />
        </LinearLayout>
    

    Now inside your Activity declare subclass for your layout (main.xml)

        public class MainSearchLayout extends LinearLayout {
    
        public MainSearchLayout(Context context, AttributeSet attributeSet) {
            super(context, attributeSet);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(R.layout.main, this);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            Log.d("Search Layout", "Handling Keyboard Window shown");
    
            final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
            final int actualHeight = getHeight();
    
            if (actualHeight > proposedheight){
                // Keyboard is shown
    
            } else {
                // Keyboard is hidden
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
    

    You can see from the code that we inflate layout for our Activity in subclass constructor

    inflater.inflate(R.layout.main, this);
    

    And now just set content view of subclassed layout for our Activity.

    public class MainActivity extends Activity {
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            MainSearchLayout searchLayout = new MainSearchLayout(this, null);
    
            setContentView(searchLayout);
        }
    
        // rest of the Activity code and subclassed layout...
    
    }
    
    0 讨论(0)
  • 2020-11-22 08:18

    using viewTreeObserver for easily get the keyboard event.

    layout_parent.viewTreeObserver.addOnGlobalLayoutListener {
                val r = Rect()
                layout_parent.getWindowVisibleDisplayFrame(r)
                if (layout_parent.rootView.height - (r.bottom - r.top) > 100) { // if more than 100 pixels, its probably a keyboard...
                    Log.e("TAG:", "keyboard open")
                } else {
                    Log.e("TAG:", "keyboard close")
                }
            }
    

    ** layout_parent is your view like edit_text.parent

    0 讨论(0)
  • 2020-11-22 08:20

    Nebojsa's solution almost worked for me. When I clicked inside a multi-line EditText it knew the keyboard was displayed, but when I started typing inside the EditText, the actualHeight and proposedHeight were still the same so it did not know they keyboard was still displayed. I made a slight modification to store the max height and it works fine. Here is the revised subclass:

    public class CheckinLayout extends RelativeLayout {
    
        private int largestHeight;
    
        public CheckinLayout(Context context, AttributeSet attributeSet) {
            super(context, attributeSet);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(R.layout.checkin, this);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
            largestHeight = Math.max(largestHeight, getHeight());
    
            if (largestHeight > proposedheight)
                // Keyboard is shown
            else
                // Keyboard is hidden
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:20

    Sander ,I believe you are trying to show the view blocked by the soft keyboard. Try this http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html.

    0 讨论(0)
提交回复
热议问题