Android Development | Custom αναζήτηση σε λίστα

Ας υποθέσουμε ότι θέλουμε να δημιουργήσουμε ένα android app το οποία θα περιέχει μία λίστα (για παράδειγμα ονομάτων) και ένα πεδίο αναζήτησης στο οποίο ο χρήστης θα πληκτρολογεί το όνομα που ψάχνει και  στη λίστα θα μένουν δυναμικά τα ονόματα που ταιριάζουν.

Αυτό το tutorial βασίζεται στον κώδικα του LookingForTable.

Θέλουμε επιπλέον η αναζήτηση να μην είναι ευαίσθητη σε μικρά και κεφαλαία γράμματα ή στους τόνους. Θέλουμε δηλαδή να μας εμφανίζεται αποτέλεσμα ακόμα και να δεν έχουμε βάλει τον σωστό τόνο ή ακόμα και αν έχουμε βάλει μικρό αντί για κεφαλαίο και το αντίστροφο.

Ένα παράδειγμα του παραπάνω σεναρίου μπορείτε να δείτε στο βίντεο που ακολουθεί.

 

Στο παράδειγμά μας θα δουλέψουμε με το Android Studio. Αρχικά δημιουργούμε ένα νέο project.

screenshot-from-2016-10-17-17-10-00

Επιλέγουμε το Minimum SDK, πράγμα που δεν έχει ιδιαίτερη σημασία για το συγκεκριμένο παράδειγμα, αλλά γενικά καλό θα είναι να επιλέγεται να είναι το Android 4 μιας και η μεγάλη πλειοψηφία των συσκευών φορούν Android 4+. Αν επιλέξουμε μικρότερο Minimum SDK, τότε θα χάσουμε διάφορα νέα χαρακτηριστικά που έχει το Android από την έκδοση 4 και μετά.

screenshot-from-2016-10-17-17-10-12

Έπειτα επιλέγουμε να δημιουργήσουμε ένα κενό Activity.

screenshot-from-2016-10-17-17-10-22

Πρώτα απ’ όλα θα πρέπει να δημιουργήσουμε το γραφικό περιβάλλον της λίστας. Αυτό το κάνουμε από το xml αρχείο με το όνομα activity_main (ή όποιο άλλο όνομα έχει δοθεί), που βρίσκεται στον φάκελλο res>layouts. Εκεί με τη βοήθεια του γραφικού περιβάλλοντος ή με κώδικα δημιουργούμε ένα EditText, το οποίο είναι το πεδίο αναζήτησης και ένα ListView που είναι η λίστα.

screenshot-from-2016-10-17-17-13-03

 

Πατώντας το παρακάτω link μπορείτε να δείτε τον κώδικα του αρχείου αυτού.

 

Μεταφερόμαστε τώρα στη java. Εκεί, πρέπει αρχικά να ορίσουμε κάποια ArrayList και προφανώς τα στοιχεία που έχουμε δημιουργήσει στο layout αρχείο προηγουμένως. Χρησιμοποιούμε ένα ArrayList με το όνομα ListLabels, το οποίο θα περιέχει τα αρχικά δεδομένα της λίστας. Δημιουργούμε επίσης μία λίστα με το όνομα equivalentList η οποία θα ακολουθεί την εμφανιζόμενη λίστα ανάλογα με το τι πληκτρολογεί ο χρήστης. Τέλος μαζί με την αρχικοποίηση του ListView και του EditText δημιουργούμε έναν πίνακα items και άλλη μία λίστα listItems οι οποίες θα χρειαστούν αργότερα.

public class MainActivity extends AppCompatActivity {
 
    ArrayList<String> listLabels;
    ArrayList<String> equivalentList; //this arraylist follows the changes in the listView
    ListView listView;
    EditText editText;
 
    ArrayAdapter adapter;
 
    String selectedName;
 
 
    String[] items;
    ArrayList<String> listItems;
 
    int length = 0;
 
....

Στη συνέχεια μεταφερόμαστε στον onCreate. Εκεί αφού δημιουργήσουμε τα στιγμιότυπα όλων του listLabels και του equivalentList καθώς και των στοιχείων του layout, προσθέτουμε τα δεδομένα που θέλουμε στη listLabels με τη χρήση του add.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 
        listLabels = new ArrayList<String>();
 
        equivalentList = new ArrayList<String>();
 
        listView = (ListView) findViewById(R.id.listview);
 
        editText = (EditText) findViewById(R.id.txtsearch);
 
 
        listLabels.add("Σπύρος");
        listLabels.add("Γιάννης");
        listLabels.add("Γιώργος");
        listLabels.add("τάκης");
        listLabels.add("μάκης");
        listLabels.add("σάκης");
 
 
        items = new String[listLabels.size()];
        initList();
....

Εκεί υπάρχει η συνάρτηση initList. Σε αυτή τη συνάρτηση τα στοιχεία που βρίσκονται στη listLabels εμφανίζονται στη λίστα. Για να γίνει αυτό χρειαζόμαστε έναν adapter. Ο adapter παίρνει σαν όρισμα ένα xml αρχείο το οποίο περιγράφει το τι θα βρίσκεται σε κάθε γραμμή της λίστας. Μπορεί να θέλουμε ένα απλό textView ή ένα TextView και μία εικόνα (όπως γίνεται στο LookingForTable). Στο συγκεκριμένο παράδειγμα θα χρησιμοποιήσουμε μόνο κείμενο.

Το xml που θα χρησιμοποιηθεί στον adapter το ονομάζουμε listitem.xml και το δημιουργούμε στον φάκελλο res>layout. Το αρχείο είναι απλά ένα LinearLayout με ένα TextView.

 

 

 

Σε αυτό το σημείο έχουμε έτοιμη τη λίστα η οποία αντικατοπτρίζει να δεδομένα που της έχουμε προσθέσει. Για να βάλουμε και το EditText στο παιχνίδι θα ορίσουμε έναν addTextChangedListener. Ο Listener αυτός περιέχει τις Overrited συναρτήσεις: beforeTextChanged, onTextChanged και afterTextChanged. Επίσης χρειαζόμαστε μία συνάρτηση η οποία θα κάνει αναζήτηση. Ονομάζουμε αυτή τη συνάρτηση searchItem. Η συνάρτηση αυτή παίρνει σαν όρισμα ένα String και “ειδοποιεί” την λίστα να προβεί στις αλλαγές. Η συνάρτηση αναζητά ένα ένα τα στοιχεία του πίνακα items κοιτώντας εάν περιέχουν ( με τη χρήση του contains ) το String του ορίσματος. Για να πετύχουμε όμως την ανεξαρτησία από τόνους και από μικρά ή κεφαλαία μετατρέπουμε εσωτερικά τα πάντα σε μικρά, έπειτα τα πάντα χωρίς τόνους και τέλος τα πάντα μικρά και χωρίς τόνους. Με αυτό τον τρόπου καλύπτουμε και τις 3 αυτές περιπτώσεις. Η μετατροπή σε μικρά γίνεται με την συνάρτηση της java, toLoweCase, ενώ η αφαίρεση των τόνων με μία δικιά μας συνάρτηση της οποίας τον κώδικα μπορείτε να δείτε με κλικ στο παρακάτω link .

Στη ουσία η συνάρτηση αυτή ανταλλάσσει τα στοιχεία που έχουν τόνους με τα αντίστοιχα χωρίς τόνους χρησιμοποιώντας τον ascii code.

Τέλος η searchItems ειδοποιεί τον adapter για τις αλλαγές.

public void searchItem (String txtToSearch) {
        for (int i=0; i<items.length;i++) {
            if (!items[i].toLowerCase().contains(txtToSearch.toString().toLowerCase())  &&  !removeTones(items[i]).contains(removeTones(txtToSearch.toString()))  &&  !removeTones(items[i]).toLowerCase().contains(removeTones(txtToSearch.toString()).toLowerCase())  ) {
                listItems.remove(items[i]);
                equivalentList.remove(items[i]);
            }
        }
        adapter.notifyDataSetChanged();
    }

Όταν λοιπόν αλλάζει το κείμενο στο EditText, θέλουμε όταν είναι κενό να γίνεται αρχικοποίηση της λίστας με τη συνάρτηση initList, ενώ όταν δεν είναι κενή (δηλαδή ο χρήστης έχει δώσει κάποιους χαρακτήρες) , να καλείται η searchItems. Χρησιμοποιώντας τον ίδιο κώδικα με την searchItem χειριζόμαστε και την afterTextChanged.

 

editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                length = s.toString().length();
            }
 
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (s.toString().equals("")) {
                    initList();
                } else {
                    searchItem(s.toString());
                }
 
            }
 
            @Override
            public void afterTextChanged(Editable s) {
                if (s.toString().length() < length) {
                    initList();
 
                    for (int i=0; i<items.length; i++) {
                        if (!items[i].toLowerCase().contains(s.toString().toLowerCase())  &&  !removeTones(items[i]).contains(removeTones(s.toString()))  &&  !removeTones(items[i]).toLowerCase().contains(removeTones(s.toString()).toLowerCase())  ) {
                            listItems.remove(items[i]);
                            equivalentList.remove(items[i]);
                            //listPicture.remove(pictures[i]);
 
 
                        }
                    }
 
                }
 
            }
        });

Τέλος για να δημιουργήσουμε κάποια ενέργεια με το πάτημα ενός στοιχείου της λίστας, ορίζουμε ένα OnItemClickListener στην listView.  Επειδή στη λίστα τη στιγμή του “κλικ” μπορεί να υπάρχουν λίγα στοιχεία λόγω κάποιας αναζήτησης θα χρησιμοποιήσουμε την equivalentList για να τραβήξουμε το περιεχόμενο του στοιχείου. Στο δικό μας παράδειγμα αποθηκεύουμε το στοιχείο στο String selectedName και το εμφανίζουμε με ένα Toast.

 

Ολόκληρο τον κώδικα μπορείτε να τον δείτε πατώντας στο “Get Source Code”. Εάν θέλετε να βοηθήσετε την προσπάθειά μας, μπορείτε να πατήσετε στο “ShowYourLove” και να δείτε τις διαφημίσεις απενεργοποιώντας το adblock είτε κάνοντάς μας κάποιο donate.

Show Your Love  Get source code

Facebook Profile photo

Studying in Computer Engineering & Informatics Department. Member of the fedora community. Interested in mobile apps and machine learning.

1 Comment on “Android Development | Custom αναζήτηση σε λίστα

Leave a Reply

Your email address will not be published. Required fields are marked *