You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现跨多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 12:12:52