如何实现跨多RecyclerView的搜索并切换容器可见性?
实现全局RecyclerView搜索及视图切换功能
我来一步步帮你搞定这个搜索功能,结合你给出的代码结构,咱们分几个核心步骤来实现:
1. 搭建全局数据源与搜索基础配置
首先得搞定两个核心前提:一个能收集所有Fragment中数据的全局列表,以及Toolbar上的搜索输入框。
1.1 在MainActivity中维护全局数据池
在MainActivity里添加一个全局列表,用来统一收集所有Fragment中的Station数据,方便后续搜索:
public class MainActivity extends AppCompatActivity { public List<Station> allStations = new ArrayList<>(); // ... 你的其他已有代码 // 提供方法让Fragment把数据添加到全局列表 public void addStationsToGlobalList(List<Station> stations) { // 简单去重,避免重复数据 if (!allStations.containsAll(stations)) { allStations.addAll(stations); } } // 可选:Fragment销毁时移除对应数据,防止内存泄漏 public void removeStationsFromGlobalList(List<Station> stations) { allStations.removeAll(stations); } }
然后在你对应fragment_stations.xml的Fragment类(假设叫StationsFragment)里,把当前Fragment的数据源同步到全局列表:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 假设当前Fragment的数据源是mStations MainActivity mainActivity = (MainActivity) getActivity(); if (mainActivity != null) { mainActivity.addStationsToGlobalList(mStations); } // ... 你原本初始化RecyclerView的代码 } // 记得在Fragment销毁时清理全局列表里的对应数据 @Override public void onDestroyView() { super.onDestroyView(); MainActivity mainActivity = (MainActivity) getActivity(); if (mainActivity != null) { mainActivity.removeStationsFromGlobalList(mStations); } }
1.2 给Toolbar添加搜索功能
先在res/menu/menu_search.xml创建搜索菜单:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:icon="@android:drawable/ic_menu_search" android:title="搜索电台" app:showAsAction="ifRoom|collapseActionView" app:actionViewClass="androidx.appcompat.widget.SearchView" /> </menu>
然后在对应fragment_search.xml的SearchFragment中,设置Toolbar并监听搜索输入:
public class SearchFragment extends Fragment { private RecyclerView searchRecyclerView; private RecyclerStationAdapter searchAdapter; private List<Station> filteredStations = new ArrayList<>(); @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_search, container, false); // 配置Toolbar Toolbar toolbar = view.findViewById(R.id.toolbar_main); // 对应你toolbar_main.xml里的Toolbar id ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); setHasOptionsMenu(true); // 初始化搜索用的RecyclerView searchRecyclerView = view.findViewById(R.id.recyclerViewSearch); searchRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); searchAdapter = new RecyclerStationAdapter(getContext(), filteredStations); searchRecyclerView.setAdapter(searchAdapter); // 初始状态隐藏搜索列表 searchRecyclerView.setVisibility(View.GONE); return view; } @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.menu_search, menu); MenuItem searchItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) searchItem.getActionView(); // 设置搜索提示文字 searchView.setQueryHint("搜索电台名称..."); // 监听搜索输入变化 searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { filterStations(query); return true; } @Override public boolean onQueryTextChange(String newText) { filterStations(newText); return true; } }); super.onCreateOptionsMenu(menu, inflater); } // 核心过滤逻辑 private void filterStations(String query) { filteredStations.clear(); MainActivity mainActivity = (MainActivity) getActivity(); if (mainActivity == null) return; if (TextUtils.isEmpty(query)) { // 输入为空时,恢复主体容器显示,隐藏搜索列表 LinearLayout mainContainer = getActivity().findViewById(R.id.main_container); mainContainer.setVisibility(View.VISIBLE); searchRecyclerView.setVisibility(View.GONE); return; } // 从全局列表中过滤匹配的电台(这里匹配名称,可扩展匹配其他字段) String lowerQuery = query.toLowerCase(); for (Station station : mainActivity.allStations) { if (station.getName().toLowerCase().contains(lowerQuery)) { filteredStations.add(station); } } // 更新搜索列表数据 searchAdapter.updateStations(filteredStations); // 切换视图:隐藏主体容器,显示搜索列表 LinearLayout mainContainer = getActivity().findViewById(R.id.main_container); mainContainer.setVisibility(View.GONE); searchRecyclerView.setVisibility(View.VISIBLE); } }
2. 优化适配器支持动态数据更新
你的RecyclerStationAdapter目前只能通过构造方法传数据,我们加一个方法来动态更新数据源:
public class RecyclerStationAdapter extends RecyclerView.Adapter<RecyclerStationAdapter.ViewHolder> { // ... 你的已有代码 // 添加动态更新数据源的方法 public void updateStations(List<Station> newStations) { this.mStations.clear(); this.mStations.addAll(newStations); notifyDataSetChanged(); } // ... 你的已有代码 }
3. 初始化视图状态
在MainActivity的onCreate方法里,确保初始状态下主体容器可见、搜索列表隐藏:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 加载头部的SearchFragment getSupportFragmentManager().beginTransaction() .replace(R.id.container_from_toolbar, new SearchFragment()) .commit(); // 设置初始视图状态 LinearLayout mainContainer = findViewById(R.id.main_container); mainContainer.setVisibility(View.VISIBLE); }
几个关键注意点
- 数据去重:如果多个Fragment有重复的电台数据,
addStationsToGlobalList里的判断可以避免全局列表出现重复项。 - 内存泄漏:记得在Fragment销毁时从全局列表移除对应数据,也可以用
WeakReference持有Activity,避免强引用泄漏。 - 性能优化:如果数据量很大,建议用协程或者异步任务做过滤,避免阻塞主线程导致界面卡顿。
- 搜索扩展:目前只匹配电台名称,你可以扩展匹配电台的分类、描述等其他字段,提升搜索体验。
内容的提问来源于stack exchange,提问作者student158
相关产品推荐
相关产品推荐

