AutoCompleteTextView connecting to database - android

I am doing a dictionary app based on this project. This is my AutoCompleteTextView:
searchAutoCompleteTextView.setThreshold(1);
searchAutoCompleteTextView.setAdapter(new WordAutoComplite(ZhuangDictActivity.this, null));
searchAutoCompleteTextView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
char key = GB2Alpha.Char2Alpha(s.charAt(0));
if (currentChar != key) {
currentChar = key;
tableName = DatabaseHelper.transTableName(key);
}
}
}
});
My CursorAdapter:
#Override
public Cursor runQueryOnBackgroundThread(CharSequence word) {
return databaseHelper.queryAutoComplete(tableName, word.toString(), DEFAULT_AUTOCOMPLETE_LIMIT);
}
/* (non-Javadoc)
* #see android.widget.CursorAdapter#convertToString(android.database.Cursor)
*/
#Override
public CharSequence convertToString(Cursor cursor) {
return cursor.getString(0);
}
The DatabaseHelper.java is available here and here is the complete code of my activity.
I noticed a bug. Let say I search "apple" and I exit the app. Then I reenter the app and search "apple" again, this time the result cannot be found. In order to solve this problem, I have to type another alphabet randomly other than "a". If after I exit the app and return to it, I search "book" before searching "apple", I will be able to get the result. Seem like the app lost connection to the database. How should I solve this problem?

Related

Convert editText number input to percentage in real time not working in real device

I'm trying to convert the input of an editText to percentage while the user input it, the following code is not working, on the real device. It does format correctly on emulator.
public class PercentTextWatcher implements TextWatcher {
private final EditText percentage;
private final Locale locale;
public PercentTextWatcher(EditText percentage, Locale locale) {
this.percentage = percentage;
this.locale = locale;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
percentage.removeTextChangedListener(this);
if (percentage == null) return;
percentage.removeTextChangedListener(this);
NumberFormat format = NumberFormat.getPercentInstance(locale);
format.setMaximumFractionDigits(4);
String percentNumber = format.format(convertToDouble(percentage.getText().toString())/1000);
percentage.setText(percentNumber);
percentage.setSelection(percentNumber.length()-1);
percentage.addTextChangedListener(this);
}
private double convertToDouble(String value) {
double convertedNumber = 0;
NumberFormat nf = new DecimalFormat("##,##");
try {
convertedNumber = nf.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return convertedNumber;
}
The keyboard does not accept anymore input after the first char, and returns 0,001% for example.
The source of the problem is you try to access some index that is not present that's why IndexOutOfBoundsException. I believe there could be 2 places
1. You're using
percentage.setSelection(formatted.length());
and the indices start with 0. So please, try
percentage.setSelection(formatted.length()-1);
2. There could be that you're setting text into a textview that is longer than the allowed length of your input in the textview
Hope this helps you!

How to mock an EditText in android using Mockito

I am trying to write a Unit Test for a validator of my android Application. The validator accepts as parameter EditText, therefore I need to mock it. However the mocking does not work, forcing the Test to crash on calling the when() method with the exception:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
My code is:
#RunWith(MockitoJUnitRunner.class)
public class MyUnitTest
{
#Mock
Context mMockContext;
#Test
public void validateIsCorrect() {
final EditText input = Mockito.mock(EditText.class);
when(input.getText()).thenReturn(Editable.Factory.getInstance().newEditable("123"));
...
}
}
The dependencies in build.gradle file are:
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
The method getText() of the EditText is not private or final. What am I doing wrong? Is it possible to mock an EditText this way? How?
When you're running a unit test, you're using a standard JVM context, not Android's context and that's why it's crashing: The Editable.Factory class and it's methods (like getInstance()) are not in the classpath. And they have not been mocked either.
What I'd do is to create a class that implements Editable with a private member to hold a string reference and use it to mock the getText() method.
Something like this:
class MockEditable implements Editable {
private String str;
public MockEditable(String str) {
this.str = str;
}
#Override #NonNull
public String toString() {
return str;
}
#Override
public int length() {
return str.length();
}
#Override
public char charAt(int i) {
return str.charAt(i);
}
#Override
public CharSequence subSequence(int i, int i1) {
return str.subSequence(i, i1);
}
#Override
public Editable replace(int i, int i1, CharSequence charSequence, int i2, int i3) {
return this;
}
#Override
public Editable replace(int i, int i1, CharSequence charSequence) {
return this;
}
#Override
public Editable insert(int i, CharSequence charSequence, int i1, int i2) {
return this;
}
#Override
public Editable insert(int i, CharSequence charSequence) {
return this;
}
#Override
public Editable delete(int i, int i1) {
return this;
}
#Override
public Editable append(CharSequence charSequence) {
return this;
}
#Override
public Editable append(CharSequence charSequence, int i, int i1) {
return this;
}
#Override
public Editable append(char c) {
return this;
}
#Override
public void clear() {
}
#Override
public void clearSpans() {
}
#Override
public void setFilters(InputFilter[] inputFilters) {
}
#Override
public InputFilter[] getFilters() {
return new InputFilter[0];
}
#Override
public void getChars(int i, int i1, char[] chars, int i2) {
}
#Override
public void setSpan(Object o, int i, int i1, int i2) {
}
#Override
public void removeSpan(Object o) {
}
#Override
public <T> T[] getSpans(int i, int i1, Class<T> aClass) {
return null;
}
#Override
public int getSpanStart(Object o) {
return 0;
}
#Override
public int getSpanEnd(Object o) {
return 0;
}
#Override
public int getSpanFlags(Object o) {
return 0;
}
#Override
public int nextSpanTransition(int i, int i1, Class aClass) {
return 0;
}
}
You can then make use of this class
Mockito.when(input.getText()).thenReturn(new MockEditable("123"));
Looking at this from a bit further away; I am asking myself: why does your validator need to know anything about Android specific classes?
What I mean is: I assume that your validator (in the end) has to check the properties of maybe a String, or something alike?
I would thus suggest to focus on separating concerns here:
Create a component that fetches a String from your EditText
Create a validator that works with such strings
Then you don't need any specific mocking for your validator in the first place!
final EditText editText = Mockito.mock(EditText.class);
final ArgumentCaptor<Editable> captor = ArgumentCaptor.forClass(Editable.class);
Mockito.doNothing().when(editText).setText(captor.capture());
Mockito.when(editText.getText()).thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) {
return captor.getValue();
}
});
What about this guys, it works for me:
Please don't forget to add the MockitoAnnotations.init(this); and also use
#Mock private EditTextView passwordField;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
when(rootView.findViewById(R.id.button_logout)).thenReturn(buttonLogout);
when(rootView.findViewById(R.id.button_unlock)).thenReturn(buttonUnlock);
when(rootView.findViewById(R.id.ScreenLock_PasswordTextField)).thenReturn(passwordField);
when(passwordField.getText()).thenReturn(Editable.Factory.getInstance().newEditable("asd"));
when(application.getPassword()).thenReturn("asd");
sut = new ScreenLockPresenterImpl(application, rootView, screenLockListener,
logoutButtonClickListener);
}
#Test
public void testOnClickWhenOk() {
sut.onClick(null);
verify(passwordField).getText();
verify(screenLockListener).unLock();
}
I think this is what you are looking for:
when(passwordField.getText()).thenReturn(Editable.Factory.getInstance().newEditable("asd"));

Xamarin android format string onkey pressed

I have this EditText in which I want the user to type a credit card number, so I want to format the string while the user is typing it, I specifically want the string to have a space every 4 numbers, like this:
xxxx xxxx xxxx xxxx
I found that I could use TextWatcher and onKeyUp but I couldn't understand how use it in a EditText, if some one could explain me I would really appreciate it, thanks.
Create a class that implements the ITextWatcher interface. Then add an instance of that class as a text changed listener...
public class CreditCardFormatter : Java.Lang.Object, ITextWatcher
{
private EditText _editText;
public CreditCardFormatter(EditText editText)
{
_editText = editText;
}
public void AfterTextChanged(IEditable s)
{
}
public void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
}
public void OnTextChanged(ICharSequence s, int start, int before, int count)
{
}
}
In your activity.. (or OnCreateView in a fragment)
public override void OnCreate()
{
// other code..
myEditText.AddTextChangedListener(new CreditCardFormatter(myEditText));
}
Then use the override methods to reformat the text to show what you need.

Can i have customized Edittext properties for my customized edittext?

I need to work with validations.For that I would like to give my type of validation as an attribute/property while am creating my EditText field.
android:inputType="email"
my customized is
validation:requiredType="phone"
in my edit text field how can I achieve this in Eclipse.
maybe this can help you
public abstract class TextValidator
implements TextWatcher {
private final TextView textView;
public TextValidator(TextView textView) {
this.textView = textView;
}
public abstract void validate(TextView textView, String text);
#Override
final public void afterTextChanged(Editable s) {
String text = textView.getText().toString();
validate(textView, text);
}
#Override
final public void beforeTextChanged(CharSequence s, int start, int count, int after) {
/* Don't care */
}
#Override
final public void onTextChanged(CharSequence s, int start, int before, int count) {
/* Don't care */
}
}
Just use it like this:
editText.addTextChangedListener(new TextValidator(editText) {
#Override
public void validate (TextView textView, String text){
/* Validation code here */
}
});
To create a library:
File > New Module
select Android Library
To use the library add it as a dependancy:
File > Project Structure > Modules > Dependencies
Then add the module (android library) as a module dependency.
Run your project. It will work.
hope it helps

How to remove recursion in EditText TextChangedListener?

I want to expurgate some bad words from edit text suppose. Father Uncle Cousin King will be F**K... But the problem is if I change the text it come to change handler again. Anyone know the solution. Please help. Code is there.
search_name.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
search_name.setText(s.toString().replace("something", "s**ething"));
// here comes it repeatedly
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){}
});
I agree with #njzk2 comments re:InputFilter, if the recursion is the trouble you want to solve, you can try something like this to prevent it:
// make your TextWatcher a class variable
protected TextWatcher mTextWatcher = new TextWatcher()
{
public void afterTextChanged(Editable s) {
textFixerUpper(search_name, s.toString());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){}
};
protected textFixerUpper(EditText t, String s)
{
t.removeTextChangedListener(mTextWatcher); // remove the listener
t.setText(s.replace("something", "s**ething")); // update the text
t.addTextChangedListener(mTextWatcher); // add the listener back
}
or by setting a Boolean flag instead of removing and re-adding the listener....though either seems a bit messy.
You can manipulate text via Editable instance provided by afterTextChanged(e: Editable) method:
val textWatcher = object : TextWatcher {
override fun afterTextChanged(e: Editable) {
e.insert(0, "Hello World")
// e.delete(st, en) ...
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
}
Listener methods are not called in this scenario.
I have solved it with a variable. Got idea from #njzk2
int checker = 0;
search_name.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
checker = 0;
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){
if(checker!=1)
{
checker = 1;
search_name.setText(s.toString().replace("something", "s**ething"));
}
}
});
Simplest way is control the count and before value
view.addTextChangedListener(
...
#Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if ( count - before != 0) {
onTextChange(charSequence);
}
}
);

Categories

Resources