I have an activity with 20 EditTexts
on it. I want to display a message if anything has been entered. Instead of attaching 20 listeners to each field, is there a way to know if input has been supplied(data changed)?
问题:
回答1:
Here is an example of a base class that takes care of notifying subclasses if any of their EditText
widgets is being used(if any exist). Depending on what you want to do when the user inputs something you may need to change my example to suit your particular case.
Base activity from which you'll inherit:
public abstract class BaseTextWatcherActivity extends Activity {
private TextWatcher mInputObserver = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
onInputChange(s.toString());
}
};
private boolean mOptimize = false;
@Override
public void setContentView(int layoutResID) {
View content = getLayoutInflater().inflate(layoutResID, null);
initInputsObservers((ViewGroup) content);
mOptimize = true;
super.setContentView(content);
}
@Override
public void setContentView(View view) {
if (view instanceof EditText) {
((EditText) view).addTextChangedListener(mInputObserver);
} else if (view instanceof ViewGroup && !mOptimize) {
initInputsObservers((ViewGroup) view);
mOptimize = false;
}
super.setContentView(view);
}
/**
* Implement this method to allow your activities to get notified when one
* of their {@link EditText} widgets receives input from the user.
*
* @param s the string that was entered by the user in one of the EditTexts.
*/
public abstract void onInputChange(String s);
/**
* This will recursively go through the entire content view and add a
* {@link TextWatcher} to every EditText widget found.
*
* @param root
* the content view
*/
private void initInputsObservers(ViewGroup root) {
final int count = root.getChildCount();
for (int i = 0; i < count; i++) {
final View child = root.getChildAt(i);
if (child instanceof EditText) {
((EditText) child).addTextChangedListener(mInputObserver);
} else if (child instanceof ViewGroup) {
initInputsObservers((ViewGroup) child);
}
}
}
}
Then all you have to do in your activities is implement the onInputchange
callback to let you know that the user entered something in one of the EditTexts
from the current layout. You may want to look at the key event callbacks from the activity class for something simpler, but if I'm not mistaken those events are consumed by the TextView
/EditText
widgets.
回答2:
Have your TextViews all call the addTextChangedListener() giving them your Activity as an argument (this). Have your Activity implement TextWatcher and override afterTextChanged(). Whenever one of the TextView changes, afterTextChanged() will be called. Here is an idea of what your code should look like
public class YouActivity extends Activity implements TextWatcher{
@Override
public void onCreate(Bundle savedInstanceState)
{
[...]
textView1.addTextChangedListener(this);
textView2.addTextChangedListener(this);
[...]
}
@Override
public void afterTextChanged (Editable s)
{
//do something
}
}