Jor*_*rdy 8 android android-softkeyboard android-listview android-edittext android-recyclerview
我正在创建一个可编辑项的列表(从后端接收)。我正在为此使用“新” recyclerview。我的recyclerview中有几种可能的viewTypes:
我遇到的问题是EditText获得关注。AdjustResize正常运行,并显示我的键盘。但是已经获得焦点的EditText在列表中不再可见。(现在调整大小的部分在列表中的位置在可见位置下方)。在这种情况下,我不想使用AdjustPan,因为在最上面有一个寻呼机和我想固定在那里的东西。
之所以发生这种情况,是因为在显示键盘时,您EditText不再存在。我已经做了几次尝试来找到解决此问题的干净方法,以保持adjustResize输入模式和良好的用户体验。我最终得到的是:
为了确保EditText在显示键盘之前可以看到它,您必须RecyclerView手动滚动,然后聚焦EditText。您可以通过覆盖代码中的焦点和单击处理来实现。
首先,EditText通过将android:focusableInTouchMode属性设置为来禁用对的关注false:
<EditText
android:id="@+id/et_review"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusableInTouchMode="false"/>
Run Code Online (Sandbox Code Playgroud)
然后,您必须EditText在要手动滚动RecyclerView并显示键盘的位置设置一个Click侦听器。您将必须知道ViewHolder包含以下内容的位置EditText:
editText.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
// you may want to play with the offset parameter
layoutManager.scrollToPositionWithOffset(position, 0);
editText.setFocusableInTouchMode(true);
editText.post(() -> {
editText.requestFocus();
UiUtils.showKeyboard(editText);
});
}
});
Run Code Online (Sandbox Code Playgroud)
最后,您必须确保EditText当其自然失去焦点时,无法再次将其聚焦:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
editText.setFocusableInTouchMode(false);
UiUtils.hideKeyboard();
}
}
});
Run Code Online (Sandbox Code Playgroud)
这远不是一个简单而干净的解决方案,但希望它能对我有所帮助。
在布局中使用它有效: android:descendantFocusability="beforeDescendants"
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:descendantFocusability="beforeDescendants"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/extrasLayout"
android:layout_below="@+id/anchorView"
android:layout_marginTop="@dimen/margin5"
android:fastScrollEnabled="false"
/>
Run Code Online (Sandbox Code Playgroud)
清单文件:将其添加到活动部分android:windowSoftInputMode="stateHidden|adjustPan"
<activity
android:name=".activites.CartActivity"
android:label="@string/title_activity_cart"
android:exported="true"
android:windowSoftInputMode="stateHidden|adjustPan"
android:parentActivityName=".activites.HomeActivity"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activites.HomeActivity"/>
</activity>
Run Code Online (Sandbox Code Playgroud)
我有同样的问题。长话短说 - 没有正确而优雅的解决方案。焦点处理在 Android 中一直是一个很大的痛点。
注意力不集中的原因有很多:
EditText视图EditText没有被渲染,因为RecycleView甚至还没有ViewHolder为它创建一个。示例:您有 10 个视图,其中 5 个在屏幕上,其他不可见,因为它们在下面。CheckBox或某些DatePickerRecyclerView 由于滚动事件消耗焦点在我的解决方案中,关于架构和结构方法的几句话:
EditText, Spinner, DatePicker,CheckBox或RadioButtongroup 都是一个单独的 ViewModel,它是一个单独的单元,它自己处理很多东西。我使用了很多技巧并将它们混合在一起。正如有人已经提到的,第一步是将这些参数添加到您的RecyclerView:
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
Run Code Online (Sandbox Code Playgroud)
所有可能输入的基本视图模型都定义了 interface,我们称之为SingleInputViewModel接口,在该接口中,您可以定义下一个函数/方法:
void onFocusGained();
void onFocusLost();
boolean isFocusable();
Run Code Online (Sandbox Code Playgroud)
在每个特定的输入项实现中,您都可以控制焦点,例如,您可以实现CheckBox为不可聚焦,并且焦点将跳转到下一个isFocusable() == true项目。此外,您将能够根据对特定视图的消耗/获得关注来控制状态和动作。
修复一些焦点传递问题的下一步是在IME_ACTION_NEXT发生时滚动 RecyclerView。在这种情况下,您需要将滚动逻辑委托给LayoutManager.scrollHorizontallyBy()或LayoutManager.scrollToPosition()计算适当的偏移或位置。
硬而优雅的方法是覆盖内部的逻辑LayoutManager,它也负责焦点处理。LinearLayoutManager有很多隐藏的逻辑,您将无法覆盖这些逻辑,因此您可能需要从头开始编写大量代码。
最后也是最复杂的修复方法是扩展RecyclerView和覆盖与焦点搜索相关的乐趣/方法:
RecyclerView.focusSearch()RecyclerView.isPreferredNextFocus()RecyclerView.onRequestFocusInDescendants()RecyclerView.onFocusSearchFailed()RecyclerView.onInterceptFocusSearch()RecyclerView.onRequestChildFocus()PS看看FocusFinder它的用法,只是为了一般知识。现在你几乎没有选择。我希望你会发现一些有用的东西。祝你好运!