RecyclerView + SearchView 从搜索中打开 Activity

RecyclerView + SearchView Open Activity From Search

我正在使用 RecyclerView 列出一些文本,并使用 SearchView 搜索列表,当用户单击列表中的文本时,它会打开一个新的 activity 具体内容文本。在我使用 SearchView 之前,我只有我的文本列表并使用了 switch 语句,如果用户单击它首先打开的第一行 activity 等...

现在使用 SearchView,当您在底部搜索内容时,结果会弹出到列表顶部,因此 switch 语句会打开第一个错误的活动。

所以是的,我一直在思考如何在用户搜索时为列表中的正确文本打开正确的 activity。谁能帮我举个例子

MainFragment.java

public class MainFragment extends Fragment implements SearchView.OnQueryTextListener {

private static final String[] DUMMYTEXT = new String[]{

        "Text One ",
        "Text Two",
        "Text Three",
        "Text Four"
};

private RecyclerView mRecyclerView;
private Adapter mAdapter;
private List<Model> mModels;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_main, container, false);

    mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);

    return view;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setHasOptionsMenu(true);

    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    mModels = new ArrayList<>();

    for (String dummyText : DUMMYTEXT) {
        mModels.add(new Model(dummyText));
    }

    mAdapter = new Adapter(getActivity(), mModels);
    mRecyclerView.setAdapter(mAdapter);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, menu);

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
    searchView.setOnQueryTextListener(this);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
public boolean onQueryTextChange(String query) {
    final List<Model> filteredModelList = filter(mModels, query);
    mAdapter.animateTo(filteredModelList);
    mRecyclerView.scrollToPosition(0);
    return true;
}

@Override
public boolean onQueryTextSubmit(String query) {
    return false;
}

private List<Model> filter(List<Model> models, String query) {
    query = query.toLowerCase();

    final List<Model> filteredModelList = new ArrayList<>();
    for (Model model : models) {
        final String text = model.getText().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    return filteredModelList;
}
}

ViewHolder.java

public class ViewHolder extends RecyclerView.ViewHolder {

private final TextView tvText;
private final Context context;

public ViewHolder(final View itemView) {
    super(itemView);
    context = itemView.getContext();

    tvText = (TextView) itemView.findViewById(R.id.tvText);

    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = null;
         switch (getAdapterPosition()) {

             case 0:

                 intent =  new Intent(context, FirstActivity.class);
                 break;

             case 1:

                 intent =  new Intent(context, SecondActivity.class);
                 break;

             case 2:

                 intent =  new Intent(context, ThirdActivity.class);
                 break;

             case 3:

                 intent =  new Intent(context, FourthActivity.class);



             default:

                 break;


         }
            context.startActivity(intent);
        }
    });
}

public void bind(Model model) {
    tvText.setText(model.getText());
}
}

Model.java

public class Model {

private final String mText;

public Model(String text) {
    mText = text;
}

public String getText() {
    return mText;
}
}

Adapter.java

public class Adapter extends RecyclerView.Adapter<ViewHolder> {

private final LayoutInflater mInflater;
private final List<Model> mModels;

public Adapter(Context context, List<Model> models) {
    mInflater = LayoutInflater.from(context);
    mModels = new ArrayList<>(models);
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    final View itemView = mInflater.inflate(R.layout.text_items, parent, false);
    return new ViewHolder(itemView);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    final Model model = mModels.get(position);
    holder.bind(model);
}

@Override
public int getItemCount() {
    return mModels.size();
}

public void animateTo(List<Model> models) {
    applyAndAnimateRemovals(models);
    applyAndAnimateAdditions(models);
    applyAndAnimateMovedItems(models);
}

private void applyAndAnimateRemovals(List<Model> newModels) {
    for (int i = mModels.size() - 1; i >= 0; i--) {
        final Model model = mModels.get(i);
        if (!newModels.contains(model)) {
            removeItem(i);
        }
    }
}

private void applyAndAnimateAdditions(List<Model> newModels) {
    for (int i = 0, count = newModels.size(); i < count; i++) {
        final Model model = newModels.get(i);
        if (!mModels.contains(model)) {
            addItem(i, model);
        }
    }
}

private void applyAndAnimateMovedItems(List<Model> newModels) {
    for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
        final Model model = newModels.get(toPosition);
        final int fromPosition = mModels.indexOf(model);
        if (fromPosition >= 0 && fromPosition != toPosition) {
            moveItem(fromPosition, toPosition);
        }
    }
}

public Model removeItem(int position) {
    final Model model = mModels.remove(position);
    notifyItemRemoved(position);
    return model;
}

public void addItem(int position, Model model) {
    mModels.add(position, model);
    notifyItemInserted(position);
}

public void moveItem(int fromPosition, int toPosition) {
    final Model model = mModels.remove(fromPosition);
    mModels.add(toPosition, model);
    notifyItemMoved(fromPosition, toPosition);
}
}

行为正确。因为当 ListView 重新计算适配器的更改时,它也会 changes/refreshes 新列表项的位置。

但是按照你的逻辑位置1会得到一个特定的Activity。

我认为您必须将位置强制执行到模型中,而不是使用 getAdapterPosition()

获取位置

你可以这样做,

mModels.get(getAdapterPosition()).getPosition();

假设您的 Model class

int positiongetters and setters

这里的问题与数据绑定有关。您的 model 不知道在选择(单击)事件时对它的期望是什么。下面的例子可能看起来很复杂,但它是为了突出这个问题。

让我们更改您的模型 class:

public class Model {

    private final String mText;
    private Class mLaunchClass;

    public Model(String text, Class launchClass) {
        mText = text;
        mLaunchClass = launchClass;
    }

    public String getText() {
        return mText;
    }

    public Class getLaunchClass() {
        return mLaunchClass;
    }
}

接下来,我们编辑您的片段代码以合并此更改:

private static final String[] DUMMYTEXT = new String[]{

    "Text One ",
    "Text Two",
    "Text Three",
    "Text Four"
};

private static final Class[] LAUNCH_CLASSES = new Class[] {
    FirstActivity.class,
    SecondActivity.class,
    ThirdActivity.class,
    FourthActvity.class
    ....
};

为您的适配器创建项目时:

mModels = new ArrayList<>();

for (int i = 0; i < DUMMYTEXT.length; i++) {
    mModels.add(new Model(DUMMYTEXT[i], LAUNCH_CLASSES[i]));
}

最后,您对 click 事件的 ViewHolder's 反应将会改变:

public ViewHolder(final View itemView) {
    super(itemView);
    context = itemView.getContext();

    tvText = (TextView) itemView.findViewById(R.id.tvText);
}

public void bind(final Model model) {
    tvText.setText(model.getText());

    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Context context = itemView.getContext();
            Intent intent = new Intent(context, 
                                          model.getLaunchClass());
            context.startActivity(intent);
        }
    });
}

您的模型现在可以提供相关信息了。