[app] Add search
This commit is contained in:
parent
fcae2633c0
commit
081a0c664d
|
|
@ -23,17 +23,27 @@ package io.github.lsposed.manager.ui.activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Filter;
|
||||||
|
import android.widget.Filterable;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import io.github.lsposed.manager.R;
|
import io.github.lsposed.manager.R;
|
||||||
import io.github.lsposed.manager.databinding.ActivityAppListBinding;
|
import io.github.lsposed.manager.databinding.ActivityAppListBinding;
|
||||||
import io.github.lsposed.manager.repo.RepoLoader;
|
import io.github.lsposed.manager.repo.RepoLoader;
|
||||||
|
|
@ -43,6 +53,8 @@ import me.zhanghai.android.fastscroll.FastScrollerBuilder;
|
||||||
|
|
||||||
public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
private final RepoLoader repoLoader = RepoLoader.getInstance();
|
private final RepoLoader repoLoader = RepoLoader.getInstance();
|
||||||
|
private SearchView searchView;
|
||||||
|
private SearchView.OnQueryTextListener searchListener;
|
||||||
private ActivityAppListBinding binding;
|
private ActivityAppListBinding binding;
|
||||||
private RepoAdapter adapter;
|
private RepoAdapter adapter;
|
||||||
|
|
||||||
|
|
@ -72,13 +84,25 @@ public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
repoLoader.addListener(this);
|
repoLoader.addListener(this);
|
||||||
fastScrollerBuilder.build();
|
fastScrollerBuilder.build();
|
||||||
binding.swipeRefreshLayout.setOnRefreshListener(repoLoader::loadRemoteData);
|
binding.swipeRefreshLayout.setOnRefreshListener(repoLoader::loadRemoteData);
|
||||||
|
searchListener = new SearchView.OnQueryTextListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextSubmit(String query) {
|
||||||
|
adapter.getFilter().filter(query);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextChange(String newText) {
|
||||||
|
adapter.getFilter().filter(newText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
adapter.setData(repoLoader.getOnlineModules());
|
adapter.initData();
|
||||||
binding.swipeRefreshLayout.setRefreshing(adapter.getItemCount() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -89,8 +113,20 @@ public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RepoAdapter extends RecyclerView.Adapter<RepoAdapter.ViewHolder> {
|
@Override
|
||||||
private OnlineModule[] modules = new OnlineModule[0];
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.menu_modules, menu);
|
||||||
|
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
|
||||||
|
searchView.setOnQueryTextListener(searchListener);
|
||||||
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RepoAdapter extends RecyclerView.Adapter<RepoAdapter.ViewHolder> implements Filterable {
|
||||||
|
private List<OnlineModule> fullList, showList;
|
||||||
|
|
||||||
|
RepoAdapter() {
|
||||||
|
fullList = showList = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -101,29 +137,46 @@ public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
holder.appName.setText(modules[position].getDescription());
|
OnlineModule module = showList.get(position);
|
||||||
String summary = modules[position].getSummary();
|
holder.appName.setText(module.getDescription());
|
||||||
|
String summary = module.getSummary();
|
||||||
if (summary != null) {
|
if (summary != null) {
|
||||||
holder.appDescription.setText(modules[position].getSummary());
|
holder.appDescription.setText(module.getSummary());
|
||||||
} else {
|
} else {
|
||||||
holder.appDescription.setVisibility(View.GONE);
|
holder.appDescription.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setClass(RepoActivity.this, RepoItemActivity.class);
|
intent.setClass(RepoActivity.this, RepoItemActivity.class);
|
||||||
intent.putExtra("module", (Parcelable) modules[position]);
|
intent.putExtra("module", (Parcelable) module);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return modules.length;
|
return showList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(OnlineModule[] modules) {
|
public void setData(OnlineModule[] modules) {
|
||||||
this.modules = modules;
|
fullList = Arrays.asList(modules);
|
||||||
notifyDataSetChanged();
|
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
|
||||||
|
runOnUiThread(() -> getFilter().filter(queryStr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initData() {
|
||||||
|
OnlineModule[] modules = repoLoader.getOnlineModules();
|
||||||
|
if (modules.length == 0) {
|
||||||
|
binding.swipeRefreshLayout.setRefreshing(true);
|
||||||
|
repoLoader.loadRemoteData();
|
||||||
|
} else {
|
||||||
|
adapter.setData(modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Filter getFilter() {
|
||||||
|
return new ModuleFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
@ -138,5 +191,36 @@ public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
appDescription = itemView.findViewById(R.id.description);
|
appDescription = itemView.findViewById(R.id.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ModuleFilter extends Filter {
|
||||||
|
|
||||||
|
private boolean lowercaseContains(String s, String filter) {
|
||||||
|
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FilterResults performFiltering(CharSequence constraint) {
|
||||||
|
if (constraint.toString().isEmpty()) {
|
||||||
|
showList = fullList;
|
||||||
|
} else {
|
||||||
|
ArrayList<OnlineModule> filtered = new ArrayList<>();
|
||||||
|
String filter = constraint.toString().toLowerCase();
|
||||||
|
for (OnlineModule info : fullList) {
|
||||||
|
if (lowercaseContains(info.getDescription(), filter) ||
|
||||||
|
lowercaseContains(info.getName(), filter) ||
|
||||||
|
lowercaseContains(info.getSummary(), filter)) {
|
||||||
|
filtered.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showList = filtered;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue