Как реализовать фильтр в блокноте?
Я хочу модернизировать блокнот и добавить в него поиск по заметкам через EditText . Вот исходный код . У меня не получается нужна помощь !
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main"
android:orientation="vertical">
<EditText
android:id="@+id/editText"
android:ems="10"
android:inputType="textPersonName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="18sp"
android:gravity="center"
android:layout_weight="10"
android:hint="Фильтр" />
<androidx.recyclerview.widget.RecyclerView
android:visibility="gone"
android:layout_weight="1"
android:id="@+id/notes_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/empty_notes_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/no_notes"
android:textSize="18sp" />
</LinearLayout>
//
public class MainActivity extends AppCompatActivity implements NoteEventListener, Drawer.OnDrawerItemClickListener {
private static final String TAG = "MainActivity";
private RecyclerView recyclerView;
private ArrayList<Note> notes;
private NotesAdapter adapter;
private NotesDao dao;
private MainActionModeCallback actionModeCallback;
private int chackedCount = 0;
private FloatingActionButton fab;
private SharedPreferences settings;
public static final String THEME_Key = "app_theme";
public static final String APP_PREFERENCES="notepad_settings";
private int theme;
@Override
public void onBackPressed() {
new AlertDialog.Builder(this)
.setTitle(R.string.exit)
.setNegativeButton(R.string.no, null)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface arg0, int arg1)
{
finishAndRemoveTask();
}
}).create().show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
settings = getSharedPreferences(APP_PREFERENCES, Context.MODE_PRIVATE);
theme = settings.getInt(THEME_Key, R.style.AppTheme);
setTheme(theme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setupNavigation(savedInstanceState, toolbar);
// init recyclerView
recyclerView = findViewById(R.id.notes_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// init fab Button
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// TODO: 13/05/2018 add new note
onAddNewNote();
}
});
dao = NotesDB.getInstance(this).notesDao();
}
private void setupNavigation(Bundle savedInstanceState, Toolbar toolbar) {
// Navigation menu items
// List<IDrawerItem> iDrawerItems = new ArrayList<>(); fix error : removed on materialdrawer 7.0.0
List<IDrawerItem<?>> iDrawerItems = new ArrayList<>();
iDrawerItems.add(new PrimaryDrawerItem().withName("Заметки").withIcon(R.drawable.ic_note_black_24dp));
// sticky DrawItems ; footer menu items
// List<IDrawerItem> stockyItems = new ArrayList<>(); removed on materialdrawer 7.0.0
List<IDrawerItem<?>> stockyItems = new ArrayList<>();
SwitchDrawerItem switchDrawerItem = new SwitchDrawerItem()
.withName("Темная тема")
.withChecked(theme == R.style.AppTheme_Dark)
.withIcon(R.drawable.ic_dark_theme)
.withOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(IDrawerItem drawerItem, CompoundButton buttonView, boolean isChecked) {
// TODO: 02/10/2018 change to darck theme and save it to settings
if (isChecked) {
settings.edit().putInt(THEME_Key, R.style.AppTheme_Dark).apply();
} else {
settings.edit().putInt(THEME_Key, R.style.AppTheme).apply();
}
// recreate app or the activity // if it's not working follow this steps
// MainActivity.this.recreate();
// this lines means wi want to close the app and open it again to change theme
TaskStackBuilder.create(MainActivity.this)
.addNextIntent(new Intent(MainActivity.this, MainActivity.class))
.addNextIntent(getIntent()).startActivities();
}
});
stockyItems.add(switchDrawerItem);
// navigation menu header
AccountHeader header = new AccountHeaderBuilder().withActivity(this)
.addProfiles(new ProfileDrawerItem()
.withName("APK")
.withIcon(R.mipmap.ic_launcher_round))
.withSavedInstance(savedInstanceState)
.withHeaderBackground(R.drawable.ic_launcher_background)
.withSelectionListEnabledForSingleProfile(false) // we need just one profile
.build();
// Navigation drawer
new DrawerBuilder()
.withActivity(this) // activity main
.withToolbar(toolbar) // toolbar
.withSavedInstance(savedInstanceState) // saveInstance of activity
.withDrawerItems(iDrawerItems) // menu items
.withTranslucentNavigationBar(true)
.withStickyDrawerItems(stockyItems) // footer items
.withAccountHeader(header) // header of navigation
//.withOnDrawerItemClickListener(this) // listener for menu items click
.build();
}
private void loadNotes() {
this.notes = new ArrayList<>();
List<Note> list = dao.getNotes();// get All notes from DataBase
this.notes.addAll(list);
this.adapter = new NotesAdapter(this, this.notes);
// set listener to adapter
this.adapter.setListener(this);
this.recyclerView.setAdapter(adapter);
showEmptyView();
// add swipe helper to recyclerView
swipeToDeleteHelper.attachToRecyclerView(recyclerView);
}
/**
* when no notes show msg in main_layout
*/
private void showEmptyView() {
if (notes.size() == 0) {
this.recyclerView.setVisibility(View.GONE);
findViewById(R.id.empty_notes_view).setVisibility(View.VISIBLE);
} else {
this.recyclerView.setVisibility(View.VISIBLE);
findViewById(R.id.empty_notes_view).setVisibility(View.GONE);
}
}
/**
* Start EditNoteActivity.class for Create New Note
*/
private void onAddNewNote() {
startActivity(new Intent(this, EditNoteActivity.class));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
return true;
}
@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
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() {
super.onResume();
loadNotes();
}
@Override
public void onNoteClick(Note note) {
// TODO: 22/07/2018 note clicked : edit note
Intent edit = new Intent(this, EditNoteActivity.class);
edit.putExtra(NOTE_EXTRA_Key, note.getId());
startActivity(edit);
}
@Override
public void onNoteLongClick(Note note) {
// TODO: 22/07/2018 note long clicked : delete , share ..
note.setChecked(true);
chackedCount = 1;
adapter.setMultiCheckMode(true);
// set new listener to adapter intend off MainActivity listener that we have implement
adapter.setListener(new NoteEventListener() {
@Override
public void onNoteClick(Note note) {
note.setChecked(!note.isChecked()); // inverse selected
if (note.isChecked())
chackedCount++;
else chackedCount--;
if (chackedCount > 1) {
actionModeCallback.changeShareItemVisible(false);
} else actionModeCallback.changeShareItemVisible(true);
if (chackedCount == 0) {
// finish multi select mode wen checked count =0
actionModeCallback.getAction().finish();
}
actionModeCallback.setCount(chackedCount + "/" + notes.size());
adapter.notifyDataSetChanged();
}
@Override
public void onNoteLongClick(Note note) {
}
});
actionModeCallback = new MainActionModeCallback() {
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
if (menuItem.getItemId() == R.id.action_delete_notes)
onDeleteMultiNotes();
else if (menuItem.getItemId() == R.id.action_share_note)
onShareNote();
actionMode.finish();
return false;
}
};
// start action mode
startActionMode(actionModeCallback);
// hide fab button
fab.setVisibility(View.GONE);
actionModeCallback.setCount(chackedCount + "/" + notes.size());
}
private void onShareNote() {
// TODO: 22/07/2018 we need share just one Note not multi
Note note = adapter.getCheckedNotes().get(0);
// TODO: 22/07/2018 do your logic here to share note ; on social or something else
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
String notetext = note.getNoteText() + "\n\n Create on : " +
NoteUtils.dateFromLong(note.getNoteDate()) + "\n By :" +
getString(R.string.app_name);
share.putExtra(Intent.EXTRA_TEXT, notetext);
startActivity(share);
}
private void onDeleteMultiNotes() {
// TODO: 22/07/2018 delete multi notes
List<Note> chackedNotes = adapter.getCheckedNotes();
if (chackedNotes.size() != 0) {
for (Note note : chackedNotes) {
dao.deleteNote(note);
}
// refresh Notes
loadNotes();
Toast.makeText(this, "Заметки успешно удалены!", Toast.LENGTH_SHORT).show();
} else Toast.makeText(this, "\n" + "Заметки не выбраны", Toast.LENGTH_SHORT).show();
//adapter.setMultiCheckMode(false);
}
@Override
public void onActionModeFinished(ActionMode mode) {
super.onActionModeFinished(mode);
adapter.setMultiCheckMode(false); // uncheck the notes
adapter.setListener(this); // set back the old listener
fab.setVisibility(View.VISIBLE);
}
// swipe to right or to left te delete
private ItemTouchHelper swipeToDeleteHelper = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// TODO: 28/09/2018 delete note when swipe
if (notes != null) {
// get swiped note
Note swipedNote = notes.get(viewHolder.getAdapterPosition());
if (swipedNote != null) {
swipeToDelete(swipedNote, viewHolder);
}
}
}
});
private void swipeToDelete(final Note swipedNote, final RecyclerView.ViewHolder viewHolder) {
new AlertDialog.Builder(MainActivity.this)
.setMessage("Удалить заметку?")
.setPositiveButton("Удалить", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// TODO: 28/09/2018 delete note
dao.deleteNote(swipedNote);
notes.remove(swipedNote);
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
showEmptyView();
}
})
.setNegativeButton("Отмена", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// TODO: 28/09/2018 Undo swipe and restore swipedNote
recyclerView.getAdapter().notifyItemChanged(viewHolder.getAdapterPosition());
}
})
.setCancelable(false)
.create().show();
}
@Override
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
Toast.makeText(this, "" + position, Toast.LENGTH_SHORT).show();
return false;
}
}
//
public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NoteHolder> {
private Context context;
private ArrayList<Note> notes;
private NoteEventListener listener;
private boolean multiCheckMode = false;
public NotesAdapter(Context context, ArrayList<Note> notes) {
this.context = context;
this.notes = notes;
}
@NonNull
@Override
public NoteHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.note_layout, parent, false);
return new NoteHolder(v);
}
@Override
public void onBindViewHolder(NoteHolder holder, int position) {
final Note note = getNote(position);
if (note != null) {
holder.noteText.setText(note.getNoteText());
holder.noteDate.setText(NoteUtils.dateFromLong(note.getNoteDate()));
// init note click event
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onNoteClick(note);
}
});
// init note long click
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
listener.onNoteLongClick(note);
return false;
}
});
// check checkBox if note selected
if (multiCheckMode) {
holder.checkBox.setVisibility(View.VISIBLE); // show checkBox if multiMode on
holder.checkBox.setChecked(note.isChecked());
} else holder.checkBox.setVisibility(View.GONE); // hide checkBox if multiMode off
}
}
@Override
public int getItemCount() {
return notes.size();
}
private Note getNote(int position) {
return notes.get(position);
}
/**
* get All checked notes
*
* @return Array
*/
public List<Note> getCheckedNotes() {
List<Note> checkedNotes = new ArrayList<>();
for (Note n : this.notes) {
if (n.isChecked())
checkedNotes.add(n);
}
return checkedNotes;
}
class NoteHolder extends RecyclerView.ViewHolder {
TextView noteText, noteDate;
CheckBox checkBox;
public NoteHolder(View itemView) {
super(itemView);
noteDate = itemView.findViewById(R.id.note_date);
noteText = itemView.findViewById(R.id.note_text);
checkBox = itemView.findViewById(R.id.checkBox);
}
}
public void setListener(NoteEventListener listener) {
this.listener = listener;
}
public void setMultiCheckMode(boolean multiCheckMode) {
this.multiCheckMode = multiCheckMode;
if (!multiCheckMode)
for (Note note : this.notes) {
note.setChecked(false);
}
notifyDataSetChanged();
}
}
//
Вот так не получается
EditText theFilter = (EditText) findViewById(R.id.editText);
theFilter.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
(MainActivity.this).adapter.getFilter().filter(charSequence);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
Ответы (1 шт):
Я все-равно не очень понял что вы подразумеваете под фразой - я не знаю как реализовать фильтр. Можно понимать это под тремя вещами:
- Вы не знаете как реализовать фильтрацию массива по вашему параметру
- Вы не знаете как выгрузить отфильтрованное в виджет списка
- 1 и 2 пункты вместе
С учетом того что вы не привели ваш класс-модель который вы грузите в адаптер, то я покажу на примере как можно отфильтровать массив. Имеется модель:
public class Student {
private String name;
private String age;
private String parent;
public Student(String name, String age, String parent){
this.name = name;
this.age = age;
this.parent = parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
}
мы формируем массив состоящий из объектов данного класса:
ArrayList<Student> arrayList = new ArrayList<Student>();
arrayList.add(new Student("Bob", "10", "Marta"));
arrayList.add(new Student("Steve", "10", "Bob"));
arrayList.add(new Student("Bob", "11", "Marta"));
arrayList.add(new Student("Peter", "10", "Tom"));
arrayList.add(new Student("Greg", "16", "Phillip"));
arrayList.add(new Student("Bob", "10", "Marta"));
и фильтруем данный массив:
List<Student> filteredList = arrayList.stream().filter(student -> student.getAge().equals("10")).collect(Collectors.toList());
ну и дальше грузим в список то что отфильтровали:
// set listener to adapter
this.adapter.setListener(this);
this.recyclerView.setAdapter(new NotesAdapter(this, filteredList));
если у вас это поле для ввода:
EditText theFilter = (EditText) findViewById(R.id.editText);
находится в пределах главной активности, то нет нужды вызывать метод из адаптера. Можно просто создать метод в главной активности который будет получать параметры для фильтрации и перезагружать список:
void filter(String parameter, ArrayList<Student> arrayList){
List<Student> filteredList = arrayList.stream().filter(student -> student.getAge().equals("10")).collect(Collectors.toList());
// set listener to adapter
this.adapter.setListener(this);
this.recyclerView.setAdapter(new NotesAdapter(this, filteredList));
this.adapter.notifyDatasetChanged()
}
вроде как-то так :)