Custom Android AutoCompleteTextView Validator - android

I'm struggling implementing a custom validator in my Android app.
I want to show in a list view some suggestions retrieved from a server (which works correctly) even if the don't start with the same letters of the text in my AutoCompleteTextView.
So, i.e. if I write "n" i'd like to get the server response, wich is "r".
So, i tried to implement a validatore setting up the isValid sample which controls if the server response is not empty.
I show my code here:
autoCompleteTextView.setAdapter(adapter);
autoCompleteTextView.setValidator(new Validator());
autoCompleteTextView.performValidation();
and here Validator class:
class Validator implements AutoCompleteTextView.Validator {
public boolean isValid(CharSequence text) {
Log.v("Test", "Checking if valid: ");
int i = 0;
if (!MainActivity.interventos.isEmpty()) {
return true;
}
return false;
}
public CharSequence fixText(CharSequence arg0) {
// TODO Auto-generated method stub
return null;
}
isValid() returns me always False, but it should return me True because MainActivity.interventos is not empty.
Ps: The entire method works good if the server responses with a word which starts with the same letters as in AutocompleteTextView.
Suggestion?
Thanks in advance

I had a similar problem which I worked out using a CustomArrayAdapter with A viewHolder implements a filter to get data from server. So, you can show in AutoComplete list data you need.
And so validator is not useful and you don't need it.
Enjoy and keep me up!!

Related

Filtering a recyclerview with a firebaserecycleradapter

I have a RecyclerView with a FirebaseRecyclerAdapter. I want to populate the RecyclerView with a list of names when the user starts typing into the SearchView.
public class SchoolsAdapter extends FirebaseRecyclerAdapter<School, SchoolsAdapter.SchoolViewHolder> {
public SchoolsAdapter(Query ref) {
super(School.class, R.layout.item_school, SchoolViewHolder.class, ref);
}
#Override
public void populateViewHolder(SchoolViewHolder schoolViewHolder, School school, int position) {
schoolViewHolder.name.setText(school.getName());
schoolViewHolder.address.setText(school.getAddress());
}
static class SchoolViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public TextView address;
public SchoolViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.school_item_tview_name);
address = (TextView) itemView.findViewById(R.id.school_item_tview_address);
}
}
}
I'm guessing I need to add a QueryTextListener to the searchview that would update the Query in the adapter. Would this break the FirebaseRecyclerAdapter?
Or should I
#Override
public boolean onQueryTextChange(String newText) {
mRecyclerView.setAdapter(new SchoolAdapter(ref.orderByChild("name").startAt(userQuery).endAt(userQuery+"~"))
return false;
}
whenever the user types something?
Also the docs talk about ordering and sorting firebase queries but don't explicitly say the best way to do string pattern matching. What's the best way to do string matching so that the recycler view shows all results which have the search query as a substring of the database record, and possibly those that are 1 edit distance away as well.
Also a way to ignorecase on queries?
I just finished doing something near to what you're looking for, I'm not sure it's the most elegant solution, but I'll throw out some ideas and if you think my idea will help I can definitely provide some examples.
Firstly, when I extended the base FirebaseAdapter I added a new filter named mFullList, since mItems of the FirebaseAdapter will be used for the display list, I don't want to keep going back to the network when I didn't have to. I then override all the methods in my child class to update mFullList with the values from the Firebase callbacks, sort them, filter them then call super.X() with the new list.
Quickly:
public reset(List)
mFullList = List
Collections.sort(mFullList, Comparator)
getFilter().filter(filterString)
The filterString is a field within the Adapter and is updated during the call to getFilter().filter(). During the perform filter I then loop through the mFullList and do a compare of:
mFullList.get(pos).getName().toLowerCase().contains(filterString.toLowerCase);
Once fitlering is done you have a new list that is passed to Filter.publishResults in the FilterResults object. publishResults calls a method in the class that performs the update and notify.
filterCompleted(List)
getItems().clear
getItems().addAll
notify
Essentially, I didn't want the FirebaseAdapater to stop getting the full list of items, I just wanted the users request to filter that full list and handle their request appropriately. Also, I didn't see a point to the added network requests based the user typing an extra character.
Using this method you can just use:
adapter.getFilter().filter("something")
to filter the list based on your updated field, and
adapter.getFilter().filter("")
to reset the full list (as long as your performFilter() handled it correctly. This way new updates from FireBase will be filtered based on the users selection, as well as when a user types in new values, won't require making new Firebase network requests.

Android: How to validate a set of fields without using TextWatcher and TextChangeListener

I have a number of EditText in an Activity. On clicking the submit button, I want to validate them, and prevent submission if there are errors in those EditText objects. I don't want to use TextWatcher because I don't want the methods to get fired at every single change. It does not make sense for an overall validation before submission. Is there a method that lets us loop through an array of the controls of the form? Thanks.
You have two options:
1) Create a Utils class with static methods for ensuring that the fields are valid.
i.e. toy example for checking email
public class Utils{
public static boolean isValidEmail(String str){
return str.contains("#");
}
}
and do so for checking the various fields (phone #, email, name, etc...). In your Activity that has the EditText(s), when you try to submit them, have something like:
public boolean validateFields(){
boolean result = true;
if(!Utils.isValidEmail(mEmailEdit.getText().toString()){
mEmailEdit.setError("Invalid email!");
result = false;
}
if(!Utils.isValidName(mEmailEdit.getText().toString()){
mNameEdit.setError("Invalid name!");
result = false;
}
return result;
}
This is a very simple idea of what you would do. Call validateFields() when clicking the submit button, and if the validateFields() method returns false, then do not proceed with the fields. If it returns true, well then all fields are valid and call another method to submit the data to w/e you are using it for.
2) (Best option for larger projects) Create an interface, call it Validator with a boolean-return function called validate(). This validator interface is extended for each various validation you wish to do, and you create a new interface like so:
public interface Validator{
public boolean validate(String s);
}
public interface EmailValidator extends Validator{
#Override
public boolean validate(String s){
return s.contains("#");
}
}
And extend a new EditText class view that has a Validator interface field, with a getter/setter. Then, in the validateFields() method, we do the same thing except call each EditText's validation interface's validate() method. There are a few more subtleties for this and I can type this all out if interested on how to do exactly. Let me know if that helps
The most straight forward way to do this is to get references to each of your sub views after you create the main view via setContentView(..). Use findViewById() to get references to each of them.
Then in your submit button click handler grab the inputs from each of them via something like nameField.getText() and do whatever validation you want. And if it fails show the error to the user in some fashion.
So, taking ideas from Lucas, creating custom components such as a DateEditText extending EditText and implementing a Validator interface, in my activity button for update onclick, I call this method that I wrote "isValidViewGroup(ViewGroup viewGroup), it will recursively go through all views, starting with the given viewGroup, and check children views, until it meets one implementing Validator and then call its isValid() method. It stops as soon as it finds an invalid one, or go through the end of views. Here's the method:
...
private boolean isValidViewGroup(ViewGroup viewGroup) {
int viewGroupChildCount = viewGroup.getChildCount();
View view = null;
for (int i = 0; i < viewGroupChildCount;i++) {
view = viewGroup.getChildAt(i);
if (view instanceof ViewGroup){
if (!isValidViewGroup((ViewGroup) view)){
return false;
}
} else {
if (view instanceof Validator){
if (!((Validator)view).isValid()){
return false;
}
}
}
}
return true;
}
...
I'm sure there could be a better, more efficient way, but for the moment that works really fine.

UI responesive in Android

I create an app that like dictionary app. When the user types in an Edittext, I call an AsyncTask to compute and update the result to the screen (I put the UI update code in onPostExecute() method ). However, when you type little fast, the eddittext become not responesive (a little latency). I think this promblem occurs because many AsyncTasks are running (each AsynTask for an input letter). So, I think I need to stop the first task before calling new task. Am I right? What should I do in this situation?
You don't need to implement the filter method in an async task. I call filter method on data when first letter has been written in editbox and save the result in an temporary array, then when another letter has been written, I call filter method on the temporary data which technically has less information than the original data. By doing this, the dimmension of data set decreases as you type in editbox. Also, you can use this method to store previous data set so when you press backspace, you don't have to call filter method again, you just go to previous saved temporary data set. For me, it works fine and I don't have to use async task because it is efficient
I suggest you another approach: use only one thread. The searching thread should wait for searching data > do search > and sleep until new data. E.g.:
private static class SearchThread extends Thread{
private Object monitor = new Object();
private String value;
public void search(String value){
this.value = value;
synchronized (monitor){monitor.notify();}
}
#Override
public void run() {
while(true){
try {System.out.println("Wait for search data."); synchronized (monitor){monitor.wait(); }
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println("Searching for " + value);
}
}
}

Android validation is not a number from EditText

mail_xml is this:
EditText android:inputType="numberDecimal|numberSigned`
onTextChanged implemented on this and other edittexts and calls relative methods.
//and one method example:
if (editTextNumber.getText().toString().equals("") ||
editTextNumber.getText().toString().equals("-") ||
editTextNumber.getText().toString().equals(".")) {
//say its bad or reset interface so the user knows;
else {
//do stuff;
}
Should I create a class to do the validation and instantiate it, then use an if/else statement returning a boolean?
It's difficult because a - is valid as the user types, so is a .. But a . and - crashes. I'm thinking a class would be best?
I don't remember a function in java to do this, unless the api has been updated and I haven't seen it yet. I've created the classes i need and can instantiate them call their getter methods no problem. just stuck on the basic validation.
You can simply put the cast in a block try/catch...
This way if the text inserted is not a number, an exception is fired...
For exemple:
if(editTextNumber.getText()!=null && !editTextNumber.getText().toString().equals("")){
try{
// int value
Integer.parseInt(editTextNumber.getText().toString());
// double value
Double.parseDouble(editTextNumber.getText().toString());
}catch(Exception e){
//prints the exception that you got
//if number format exception then your input is not a number
e.printStackTrace();
}
}
Hope it helped...

How to use List<Status in android?

I am retrieving the information I need here.
getStatus
public java.util.List<Status> getStatus(int limit)
throws EasyFacebookError
Throws:
EasyFacebookError
how do I set the List<Status> I retrieve to a list in android?
EDIT Here is what i am using to reteive the the status...
List<Status> status;
try {
status = rest.getStatus(10);
} catch (EasyFacebookError e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
How do i set this to a arrayAdapter?
What do you mean a "list in android"? It's giving you a list that you can use already.
To understand what the <Status> part means, you need to understand generics.
Generics allow you to have methods that take and return the type you need, rather than dealing with possible exceptions or accidentally putting the wrong type into a list.
Without generics, List's methods (it's an interface that things such as ArrayList or LinkedList happen to implement) would look like this (only some methods shown):
boolean add(Object object);
boolean add(int location, Object object);
Object get(int location);
boolean contains(Object object);
Everything is an Object and you could for example, put in anything or get out anything.
If you use a generic List, everything is of type Status instead:
boolean add(Status object);
boolean add(int location, Status object);
Status get(int location);
boolean contains(Status object);
You can then just use your retrieved list and do the following to check if size > 0 and get the first status, as an example (I have no experience with the Facebook API itself so you may have to do something entirely different than this for what you actually need):
if (list.size() > 0) {
Status myStatus = list.get(0);
}
You don't have to worry in this case that list.get(index) doesn't return a Status.
You can definitely pass this list to anything that says it accepts a List, for example an ArrayAdapter.
Check out generics, interfaces, and Android's java.util.List interface for more info on each of those things!
UPDATE
To set this list to an ArrayAdapter, ArrayAdapter has a constructor just for this:
List<Status> status;
try {
status = rest.getStatus(10);
ArrayAdapter<Status> arrayAdapter = new ArrayAdapter<Status>(context, R.layout.list_layout_name, R.id.list_item_textbox, status);
listView.setAdapter(arrayAdapter);
} catch (EasyFacebookError e1) {
// TODO Handle possible errors, of course!
e1.printStackTrace();
}
Notice ArrayAdapter is also generic. You are going to need to make an XML layout file with a TextView element that has the ID you set in the second resource argument. If you just want what the default layout, you use the two parameters android.R.layout.simple_list_item_1, android.R.id.text1. context is most likely this if you are inside an extended Activity class, or if not, you would pass a reference of the instance of your activity instead.
See you just pass the list right into the ArrayAdapter!
Note you might want a more complex adapter for more complex views, in which case you would have to subclass an Adapter and override the getView to do whatever with the Status elements. An ArrayAdapter will just put Status.toString() into the specified item text view, which may or may not be what you want.

Categories

Resources