监听键盘弹出与隐藏事件的三种方式 总结

我们在开发中经常会遇到软键盘遮挡住了输入框,而直接把输入框往上顶adjustResize这种方法过于暴力影响美观,我们希望键盘弹出时动态的去改变布局。这时候,便用到了监听键盘弹起事件的功能。

可能 大家都会潜意识觉得:Android中没有可以复写的方法么?或者说,没有什么listener可以让我们使用么?

抱歉,真的没有,我们潜意识都是以为系统会提供,其实系统提供的是InputMethodManager,让我们控制键盘的弹出和隐藏,而不是键盘弹出和隐藏触发事件。

Android系统并没有给我们提供监听键盘弹出的方法,我们只能自己监听view的高度变化来间接判断键盘是不是弹出了。

目前通用的方法是,由于键盘弹起与隐藏,会使得layout的布局发生变化,通过布局的大小变化触发的事件实现键盘事件的触发。

重写onSizeChanged方法

不要忘了设置键盘
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
x
 
1
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
自定义一个ViewGroup
public class AdjustSizeRelativeLayout extends RelativeLayout {
	public AdjustSizeRelativeLayout(Context context) {
		super(context);
	}
	
	public AdjustSizeRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	public AdjustSizeRelativeLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	private static final int CHANGE_SIZE = 200;
	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		Log.i("bqt", "【onSizeChanged】" + w + " " + h + " " + oldw + " " + oldh);
        if (oldw == 0 || oldh == 0) return;

		if (boardListener != null) {
			if (h - oldh < -CHANGE_SIZE) {
				Log.i("bqt", "键盘弹出" + "change" + w + " " + h + " " + oldw + " " + oldh);
				boardListener.keyBoardVisable(Math.abs(h - oldh));
			}
			if (h - oldh > CHANGE_SIZE) {
				Log.i("bqt", "键盘结束" + "change" + w + " " + h + " " + oldw + " " + oldh);
				boardListener.keyBoardInvisable(Math.abs(h - oldh));
			}
		}
	}
	
	public interface SoftkeyBoardListener {
		public void keyBoardVisable(int move);
		
		public void keyBoardInvisable(int move);
	}
	
	private SoftkeyBoardListener boardListener;
	
	public void setSoftKeyBoardListener(SoftkeyBoardListener boardListener) {
		this.boardListener = boardListener;
	}
}
x
1
public class AdjustSizeRelativeLayout extends RelativeLayout {
2
    public AdjustSizeRelativeLayout(Context context) {
3
        super(context);
4
    }
5
    
6
    public AdjustSizeRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
7
        super(context, attrs, defStyle);
8
    }
9
    
10
    public AdjustSizeRelativeLayout(Context context, AttributeSet attrs) {
11
        super(context, attrs);
12
    }
13
    
14
    private static final int CHANGE_SIZE = 200;
15
    
16
    @Override
17
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
18
        super.onSizeChanged(w, h, oldw, oldh);
19
        Log.i("bqt", "【onSizeChanged】" + w + " " + h + " " + oldw + " " + oldh);
20
        if (oldw == 0 || oldh == 0) return;
21
22
        if (boardListener != null) {
23
            if (h - oldh < -CHANGE_SIZE) {
24
                Log.i("bqt", "键盘弹出" + "change" + w + " " + h + " " + oldw + " " + oldh);
25
                boardListener.keyBoardVisable(Math.abs(h - oldh));
26
            }
27
            if (h - oldh > CHANGE_SIZE) {
28
                Log.i("bqt", "键盘结束" + "change" + w + " " + h + " " + oldw + " " + oldh);
29
                boardListener.keyBoardInvisable(Math.abs(h - oldh));
30
            }
31
        }
32
    }
33
    
34
    public interface SoftkeyBoardListener {
35
        public void keyBoardVisable(int move);
36
        
37
        public void keyBoardInvisable(int move);
38
    }
39
    
40
    private SoftkeyBoardListener boardListener;
41
    
42
    public void setSoftKeyBoardListener(SoftkeyBoardListener boardListener) {
43
        this.boardListener = boardListener;
44
    }
45
}
布局
<?xml version="1.0" encoding="utf-8"?>
<com.bqt.test.AdjustSizeRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                       android:id="@+id/rl_root"
                                       android:layout_width="match_parent"
                                       android:layout_height="match_parent">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:layout_alignParentBottom="true"
        android:hint="输入交易密码"
        android:inputType="text"
        android:paddingLeft="5dp"/>

</com.bqt.test.AdjustSizeRelativeLayout>
15
1
<?xml version="1.0" encoding="utf-8"?>
2
<com.bqt.test.AdjustSizeRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
                                       android:id="@+id/rl_root"
4
                                       android:layout_width="match_parent"
5
                                       android:layout_height="match_parent">
6
7
    <EditText
8
        android:layout_width="match_parent"
9
        android:layout_height="44dp"
10
        android:layout_alignParentBottom="true"
11
        android:hint="输入交易密码"
12
        android:inputType="text"
13
        android:paddingLeft="5dp"/>
14
15
</com.bqt.test.AdjustSizeRelativeLayout>
使用
public class MainActivity extends Activity {
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit);
		AdjustSizeRelativeLayout layout = findViewById(R.id.rl_root);
		layout.setSoftKeyBoardListener(new AdjustSizeRelativeLayout.SoftkeyBoardListener() {
			@Override
			public void keyBoardVisable(int move) {
				Log.i("bqt", "【keyBoardVisable】" + move);
			}
			
			@Override
			public void keyBoardInvisable(int move) {
				Log.i("bqt", "【keyBoardInvisable】" + move);
			}
		});
	}
}
x
1
public class MainActivity extends Activity {
2
    
3
    protected void onCreate(Bundle savedInstanceState) {
4
        super.onCreate(savedInstanceState);
5
        setContentView(R.layout.edit);
6
        AdjustSizeRelativeLayout layout = findViewById(R.id.rl_root);
7
        layout.setSoftKeyBoardListener(new AdjustSizeRelativeLayout.SoftkeyBoardListener() {
8
            @Override
9
            public void keyBoardVisable(int move) {
10
                Log.i("bqt", "【keyBoardVisable】" + move);
11
            }
12
            
13
            @Override
14
            public void keyBoardInvisable(int move) {
15
                Log.i("bqt", "【keyBoardInvisable】" + move);
16
            }
17
        });
18
    }
19
}

添加 OnLayoutChangeListener - 简单

不要忘了设置键盘
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
 
1
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
使用
public class MainActivity extends Activity {
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit);
		
		int screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();
		int keyHeight = screenHeight / 3;
		int scrollHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
		
		RelativeLayout layout = findViewById(R.id.rl_root);
		layout.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
			if (oldBottom != 0 && bottom != 0) {
				if (oldBottom - bottom > keyHeight) {
					Toast.makeText(MainActivity.this, "键盘弹起", Toast.LENGTH_SHORT).show();
					v.scrollBy(0, scrollHeight);
				} else if ((bottom - oldBottom > keyHeight)) {
					Toast.makeText(MainActivity.this, "键盘落下", Toast.LENGTH_SHORT).show();
					v.scrollBy(0, -scrollHeight);
				}
			}
		});
	}
}
x
1
public class MainActivity extends Activity {
2
    
3
    protected void onCreate(Bundle savedInstanceState) {
4
        super.onCreate(savedInstanceState);
5
        setContentView(R.layout.edit);
6
        
7
        int screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();
8
        int keyHeight = screenHeight / 3;
9
        int scrollHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
10
        
11
        RelativeLayout layout = findViewById(R.id.rl_root);
12
        layout.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
13
            if (oldBottom != 0 && bottom != 0) {
14
                if (oldBottom - bottom > keyHeight) {
15
                    Toast.makeText(MainActivity.this, "键盘弹起", Toast.LENGTH_SHORT).show();
16
                    v.scrollBy(0, scrollHeight);
17
                } else if ((bottom - oldBottom > keyHeight)) {
18
                    Toast.makeText(MainActivity.this, "键盘落下", Toast.LENGTH_SHORT).show();
19
                    v.scrollBy(0, -scrollHeight);
20
                }
21
            }
22
        });
23
    }
24
}

添加 ViewTreeObserver.OnGlobalLayoutListener

KeyboardChangeListener
public class KeyboardChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {
	private static final String TAG = "bqt";
	private View mContentView;
	private int mOriginHeight;
	private int mPreHeight;
	private KeyBoardListener mKeyBoardListen;
	
	public interface KeyBoardListener {
		/**
		 * call back
		 *
		 * @param isShow         true is show else hidden
		 * @param keyboardHeight keyboard height
		 */
		void onKeyboardChange(boolean isShow, int keyboardHeight);
	}
	
	public void setKeyBoardListener(KeyBoardListener keyBoardListen) {
		this.mKeyBoardListen = keyBoardListen;
	}
	
	public KeyboardChangeListener(Activity contextObj) {
		if (contextObj == null) {
			Log.i(TAG, "contextObj is null");
			return;
		}
		mContentView = findContentView(contextObj);
		if (mContentView != null) {
			addContentTreeObserver();
		}
	}
	
	private View findContentView(Activity contextObj) {
		return contextObj.findViewById(android.R.id.content);
	}
	
	private void addContentTreeObserver() {
		mContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
	}
	
	@Override
	public void onGlobalLayout() {
		int currHeight = mContentView.getHeight();
		if (currHeight == 0) {
			Log.i(TAG, "currHeight is 0");
			return;
		}
		boolean hasChange = false;
		if (mPreHeight == 0) {
			mPreHeight = currHeight;
			mOriginHeight = currHeight;
		} else {
			if (mPreHeight != currHeight) {
				hasChange = true;
				mPreHeight = currHeight;
			} else {
				hasChange = false;
			}
		}
		if (hasChange) {
			boolean isShow;
			int keyboardHeight = 0;
			if (mOriginHeight == currHeight) {
				//hidden
				isShow = false;
			} else {
				//show
				keyboardHeight = mOriginHeight - currHeight;
				isShow = true;
			}
			
			if (mKeyBoardListen != null) {
				mKeyBoardListen.onKeyboardChange(isShow, keyboardHeight);
			}
		}
	}
	
	@SuppressLint("ObsoleteSdkInt")
	public void destroy() {
		if (mContentView != null) {
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
				mContentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
			}
		}
	}
}
x
 
1
public class KeyboardChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {
2
    private static final String TAG = "bqt";
3
    private View mContentView;
4
    private int mOriginHeight;
5
    private int mPreHeight;
6
    private KeyBoardListener mKeyBoardListen;
7
    
8
    public interface KeyBoardListener {
9
        /**
10
         * call back
11
         *
12
         * @param isShow         true is show else hidden
13
         * @param keyboardHeight keyboard height
14
         */
15
        void onKeyboardChange(boolean isShow, int keyboardHeight);
16
    }
17
    
18
    public void setKeyBoardListener(KeyBoardListener keyBoardListen) {
19
        this.mKeyBoardListen = keyBoardListen;
20
    }
21
    
22
    public KeyboardChangeListener(Activity contextObj) {
23
        if (contextObj == null) {
24
            Log.i(TAG, "contextObj is null");
25
            return;
26
        }
27
        mContentView = findContentView(contextObj);
28
        if (mContentView != null) {
29
            addContentTreeObserver();
30
        }
31
    }
32
    
33
    private View findContentView(Activity contextObj) {
34
        return contextObj.findViewById(android.R.id.content);
35
    }
36
    
37
    private void addContentTreeObserver() {
38
        mContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
39
    }
40
    
41
    @Override
42
    public void onGlobalLayout() {
43
        int currHeight = mContentView.getHeight();
44
        if (currHeight == 0) {
45
            Log.i(TAG, "currHeight is 0");
46
            return;
47
        }
48
        boolean hasChange = false;
49
        if (mPreHeight == 0) {
50
            mPreHeight = currHeight;
51
            mOriginHeight = currHeight;
52
        } else {
53
            if (mPreHeight != currHeight) {
54
                hasChange = true;
55
                mPreHeight = currHeight;
56
            } else {
57
                hasChange = false;
58
            }
59
        }
60
        if (hasChange) {
61
            boolean isShow;
62
            int keyboardHeight = 0;
63
            if (mOriginHeight == currHeight) {
64
                //hidden
65
                isShow = false;
66
            } else {
67
                //show
68
                keyboardHeight = mOriginHeight - currHeight;
69
                isShow = true;
70
            }
71
            
72
            if (mKeyBoardListen != null) {
73
                mKeyBoardListen.onKeyboardChange(isShow, keyboardHeight);
74
            }
75
        }
76
    }
77
    
78
    @SuppressLint("ObsoleteSdkInt")
79
    public void destroy() {
80
        if (mContentView != null) {
81
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
82
                mContentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
83
            }
84
        }
85
    }
86
}
使用
public class MainActivity extends Activity {
	
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit);
		
		int scrollHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
		
		RelativeLayout layout = findViewById(R.id.rl_root);
		new KeyboardChangeListener(this).setKeyBoardListener((isShow, keyboardHeight) -> {
			if (isShow) {
				Toast.makeText(MainActivity.this, "键盘弹起", Toast.LENGTH_SHORT).show();
				layout.scrollBy(0, scrollHeight);
			} else {
				Toast.makeText(MainActivity.this, "键盘落下", Toast.LENGTH_SHORT).show();
				layout.scrollBy(0, -scrollHeight);
			}
		});
	}
}
20
1
public class MainActivity extends Activity {
2
    
3
    protected void onCreate(Bundle savedInstanceState) {
4
        super.onCreate(savedInstanceState);
5
        setContentView(R.layout.edit);
6
        
7
        int scrollHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
8
        
9
        RelativeLayout layout = findViewById(R.id.rl_root);
10
        new KeyboardChangeListener(this).setKeyBoardListener((isShow, keyboardHeight) -> {
11
            if (isShow) {
12
                Toast.makeText(MainActivity.this, "键盘弹起", Toast.LENGTH_SHORT).show();
13
                layout.scrollBy(0, scrollHeight);
14
            } else {
15
                Toast.makeText(MainActivity.this, "键盘落下", Toast.LENGTH_SHORT).show();
16
                layout.scrollBy(0, -scrollHeight);
17
            }
18
        });
19
    }
20
}
2018-5-21




猜你喜欢

转载自www.cnblogs.com/baiqiantao/p/813bd984967ff66ce1cf10d2eb0cc82d.html