Filtrujemy ep.2 – FilterListener.onFilterComplete() – #1A

Po co przerywać użytkownikowi dodawanie składników do posiłku i wysyłać go na ekran dodawania składników? Zrobię to mądrzej 🙂

Jedną z rzeczy, które lubię w programowaniu jest to, że jeżeli sobie coś wymyślę, to z reguły okazuje się, że da się to zrobić. Problemem jest tylko ilość czasu, który trzeba na to poświęcić.

Mam filtrowaną listę składników, które mogę dodać do posiłku, ale w momencie kiedy wyszukiwanego składnika nie ma jeszcze w bazie użytkownik będzie zmuszony przerywać proces, przechodzić do ekranu dodawania składnika i wracać żeby go przypisać do posiłku. Męczące i nieefektowne.

Wymyśliłam sobie, że jeżeli przefiltrowana lista przestaje zwracać cokolwiek, to przy szukajce pojawia się klikalny przycisk dodawania. Po kliknięciu na plus składnik dodaje się do bazy i od razu przypisuje do posiłku + użytkownik dostaje wiadomość o poprawnym dorzuceniu składnika do bazy.

Tak to wygląda w praktyce:

a tak w kodzie:


final EditText filterEditText = (EditText) addIngredientView.findViewById(R.id.name_filter);
filterEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Filter filter = ingredientListAdapter.getFilter();
filter.filter(s, new Filter.FilterListener() {
@Override
public void onFilterComplete(int count) {
int icon = count == 0 ? android.R.drawable.ic_menu_add : 0;
filterEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, icon, 0);
}
});
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});

Do wywołania metody filter.filter(s) dorzucamy listener, który zostanie odpalony po zakończeniu filtrowania. Dzięki temu możemy sprawdzić ile rezultatów zostało zwróconych i w zależności od tego pokazać przycisk dodawania. Zależało mi na tym żeby przycisk dodawania był wyświetlany kiedy zostaną spełnione takie a nie inne warunki, stąd ta dziwna komenda setCompoundDrawablesWithIntrinsicBounds. Gdyby przycisk miał być widoczny zawsze wsadziłabym go w xml-a.

Trochę więcej trudności sprawia obsługa kliknięcia w taki „przycisk”. Niestety trzeba wyliczać czy obszar, na który kliknął użytkownik zawiera się w obszarze wyświetlania ikonki… no cóż, skoro tak trzeba, to trzeba. Nikt nie wymyślił nic mądrzejszego.


filterEditText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Drawable drawable = filterEditText.getCompoundDrawables()[DRAWABLE_RIGHT];
if (drawable != null) {
Rect bounds = drawable.getBounds();
if (event.getRawX() >= (filterEditText.getRight() – bounds.width())) {
String text = filterEditText.getText().toString().trim();
if (text.length() != 0) {
long ingredientId = ingredientContract.insert(dbHelper, text);
mealIngredientContract.insert(dbHelper, meal.getId(), ingredientId);
ingredientListAdapter.updateResults(mealIngredientContract.getIngredientsWithMeal(meal, dbHelper));
filterEditText.setText("");
Toast.makeText(v.getContext(), R.string.ingredient_added_message, Toast.LENGTH_SHORT).show();
return true;
}
}
}
}
return false;
}
});

Po tym jak stwierdzimy, że użytkownik kliknął w ikonkę i ma coś wpisane dodajemy to do bazy – dokładnie do dwóch tabelek, tej ze składnikami i tej asocjacyjnej dla posiłków i składników. Przeładowujemy listę, czyścimy filtr i wyświetlamy użytkownikowi wiadomość, żeby się nie zdziwił, że coś się nagle dzieje.

To tyle na dziś, czas chyba opracować funkcję tworzącą listę zakupów 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

This site uses Akismet to reduce spam. Learn how your comment data is processed.