如何让RecyclerView适配器内的EditText在Fragment显示时自动聚焦
问题描述
我有一个包含RecyclerView控件的Fragment,该RecyclerView绑定了头部适配器HeaderAdapter,适配器布局内包含一个EditText控件。
当Fragment进入可视区域时,我希望这个EditText能够自动聚焦(即自动弹出软键盘)。
对应Fragment的初始实现代码如下:
public class My Fragment extends Fragment { private LinearLayoutManager layoutManager; private FeedRecyclerView recyclerView; private PostAdapter postAdapter; private ConcatAdapter concatAdapter; private HeaderAdapter headerAdapter; private List<Post> postData = new ArrayList<>(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { return inflater.inflate(R.layout.my_fragment, parent, false); } @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { recyclerView = view.findViewById(R.id.recycler_view); layoutManager = new FeedLinearLayoutManager(getContext()); recyclerView.setLayoutManager(layoutManager); recyclerView.setItemAnimator(new DefaultItemAnimator()); // This is the adapter that contains the EditText headerAdapter = new HeaderAdapter(getContext()); postAdapter = new PostAdapter(getContext(), postData, layoutManager); concatAdapter = new ConcatAdapter(); recyclerView.setAdapter(concatAdapter); concatAdapter.addAdapter(searchHeaderAdapter); } }
头部适配器类HeaderAdapter的实现代码如下:
public class HeaderAdapter extends RecyclerView.Adapter<HeaderAdapter.ViewHolder> { private Context context; public HeaderAdapter(Context context) { this.context = context; } @NonNull @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_header, parent, false)); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // } @Override public long getItemId(int position) { return 1; } @Override public int getItemCount() { return 1; } public class ViewHolder extends RecyclerView.ViewHolder { public EditText myEditText; public ViewHolder(View v) { super(v); myEditText = v.findViewById(R.id.my_edit_text); } } }
需要实现在Fragment展示时,HeaderAdapter内的EditText自动聚焦并弹出软键盘。
实现方案
首先修正初始代码的两处笔误,否则功能无法正常运行:
- 类名
My Fragment存在非法空格,改为MyFragment concatAdapter.addAdapter(searchHeaderAdapter)引用了不存在的变量,改为concatAdapter.addAdapter(headerAdapter),确保头部适配器被正确添加到适配器链中
之后按以下步骤实现自动聚焦:
- 配置宿主Activity软键盘模式
打开AndroidManifest.xml,找到承载该Fragment的Activity节点,不要配置android:windowSoftInputMode="stateHidden"或stateAlwaysHidden"(这两个属性会强制进入页面时隐藏软键盘),推荐添加adjustResize属性避免软键盘遮挡布局:
<activity android:name=".YourHostActivity" android:windowSoftInputMode="adjustResize" />
- 在Fragment可见时执行聚焦逻辑
不要在onViewCreated或适配器的onBindViewHolder中直接调用聚焦方法:前者执行时RecyclerView还未完成布局,拿不到头部ViewHolder的EditText实例;后者可能在页面预加载时触发,导致非可见状态下乱弹键盘。
正确做法是重写Fragment的onResume方法(该方法触发时Fragment已进入可视状态),通过post等待RecyclerView布局完成后再查找控件、执行聚焦和弹键盘操作:
// 导入需要的依赖类 import android.content.Context; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; @Override public void onResume() { super.onResume(); recyclerView.post(() -> { // HeaderAdapter是第一个添加到ConcatAdapter的适配器,对应item位置为0 HeaderAdapter.ViewHolder headerHolder = (HeaderAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(0); if (headerHolder != null) { EditText targetEt = headerHolder.myEditText; // 让EditText获取焦点 targetEt.requestFocus(); // 调起软键盘 InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null) { imm.showSoftInput(targetEt, InputMethodManager.SHOW_IMPLICIT); } } }); }
- (可选)离开页面时自动收起软键盘
如果需要Fragment切到后台时自动收起键盘,可以重写onPause方法添加对应逻辑:
@Override public void onPause() { super.onPause(); InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (imm != null && getView() != null) { imm.hideSoftInputFromWindow(getView().getWindowToken(), 0); } }
注意:如果后续调整了ConcatAdapter的add顺序,HeaderAdapter不在第一个位置,需要把代码里查找ViewHolder的位置参数
0改成HeaderAdapter对应的实际起始位置即可。
内容的提问来源于stack exchange,提问作者user1695123
相关产品推荐
相关产品推荐

