lpf*_*pfx 4 android soft-keyboard
当编辑文本获得焦点后出现软键盘时,我试图调整布局。现在,如果我有很多编辑文本并且键盘出现,则最后一个编辑文本被隐藏并且我无法向上滚动。
这是我的布局是如何构建的:
模板:
<LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical">
// where I inflate view_1
</LinearLayout>
<LinearLayout>
// footer
</LinearLayout>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
视图 (view_1):
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
</LinearLayout>
</LinearLayout>
</ScrollView>
Run Code Online (Sandbox Code Playgroud)
我已经尝试了android:windowSoftInputMode(在 manifest.xml 上和以编程方式)的各种组合。我试图设置android:isScrollContainer="false"滚动视图,但没有。
我也试过这个答案,在我的滚动视图中放置了一个 GlobalLayoutListener ,但是当键盘出现时没有调用 onGlobalLayout 。而且isKeyboardShown总是假的。
我找到的最佳解决方案是adjustpan在manifest.xml文件的 activity<> 标记中添加属性。
<activity
android:name="MyActivity"
android:windowSoftInputMode="adjustPan"/>
Run Code Online (Sandbox Code Playgroud)
我最终按照自己的方式做了。
我创建了一个实现 OnFocusChangeListener 的类来处理我的所有 EditText:
public class EditTextFocusChangeListener implements OnFocusChangeListener {
private ScrollView scrollView;
public EditTextFocusChangeListener(ScrollView scrollView) {
this.scrollView = scrollView;
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
if(hasFocus) {
int left = view.getLeft();
int top = view.getTop();
int bottom = view.getBottom();
int keyboardHeight = scrollView.getHeight() / 3;
// if the bottom of edit text is greater than scroll view height divide by 3,
// it means that the keyboard is visible
if (bottom > keyboardHeight) {
// increase scroll view with padding
scrollView.setPadding(0, 0, 0, keyboardHeight);
// scroll to the edit text position
scrollView.scrollTo(left, top);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在活动中,我为每个编辑文本设置了侦听器:
EditTextFocusChangeListener listener = new EditTextFocusChangeListener(mainScrollView);
editText1 = (EditText) findViewById(R.id.editText1);
editText1.setOnFocusChangeListener(listener);
editText2 = (EditText) findViewById(R.id.editText2);
editText2.setOnFocusChangeListener(listener);
...
editTextN = (EditText) findViewById(R.id.editTextN);
editTextN.setOnFocusChangeListener(listener);
Run Code Online (Sandbox Code Playgroud)
对于最后的编辑文本,我设置了一个 EditorAction 侦听器来处理软键盘上的“完成”按钮 - 隐藏键盘并将滚动视图放回其原始位置:
editTextN.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
int result = actionId & EditorInfo.IME_MASK_ACTION;
switch(result) {
// user taped on keyboard DONE button
case EditorInfo.IME_ACTION_DONE:
// put the scroll view back to its original position
mainScrollView.setPadding(0, 0, 0, 0);
// hide keyboard
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
// remove focus from any edit text
LinearLayout scrollViewLL = (LinearLayout) mainScrollView.getChildAt(0);
scrollViewLL.requestFocus();
break;
}
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
最后,一种处理用户触摸编辑文本外部以隐藏键盘并将滚动视图放回其原始位置的方法(在网络上找到此方法并进行了一些更改以满足我的需要):
public void setupUI(View view) {
// Set up touch listener for non-text box views to hide keyboard.
if (!(view instanceof EditText)) {
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// put the scroll view back to its original position
if (v instanceof ScrollView) {
v.setPadding(0, 0, 0, 0);
LinearLayout scrollViewLL = (LinearLayout) ((ScrollView) v).getChildAt(0);
scrollViewLL.requestFocus();
}
hideKeyboard();
return false;
}
});
}
// If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView);
}
}
}
Run Code Online (Sandbox Code Playgroud)