1

I have 8 fragments, each inflating a layout with among others, an EditText wrapped inside a TextInputLayout. In the onCreateView, am implementing

EditText inputTextFrag1 = (EditText)findViewById(R.id.et_frag1);
inputTextFrag1.addTextChangedListener(new MyTextWatcher(inputTextFrag1));

Am also having to implement MyTextWatcher class in each fragment body as below:

private class MyTextWatcher implements TextWatcher {

            private View view;

            public MyTextWatcher(View view) {
                this.view = view;
            }

            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                saveButton.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
                saveButton.setClickable(false);
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                saveButton.getBackground().setColorFilter(null);
                switch (view.getId()) {
                    case R.id.et_frag1:
                        validateName();
                        break;
                }
            }
        }

Where validateName();

private boolean validateName() {
            if (inputTextFrag1 .getText().toString().trim().isEmpty()) {
                mInputLayoutName.setError(getString(R.string.err_msg_name));
                requestFocus(inputTextFrag1 );
                return false;
            } else {
                mInputLayoutName.setErrorEnabled(false);
            }
            return true;
        }

Is there a way to have just one MyTextWatcher class somewhere and one validateName() method to be called by each fragment instead of duplicating the same class/method 8 times. Thanks

Is this the correct way to place the TextWatcher class inside a BaseDialogFragment?

public abstract class BaseDialogFragment extends DialogFragment{

    private class MyTextWatcher implements TextWatcher {

        private View view;

        public MyTextWatcher(View view) {
            this.view = view;
        }

        @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) {
        }
    }
}

What logic goes into the beforeTextChanged and afterTextChanged methods of the TextWatcher?

Geob
  • 586
  • 5
  • 15

2 Answers2

0

You can create a BaseFragment that will be extended by your fragments.

Therefore, you can manage your TextWatcher inside this BaseFragment and consequently the fragments which have this heritage, will receive your expected logic.

As in the following example:

BaseFragment.class

public abstract class BaseFragment extends Fragment implements TextWatcher {

    EditText editText;
    Button button;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //inflate your edit text
        ...

        //inflate your button
        ...

        editText.addTextChangedListener(this);

    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        //text watcher listener
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        //text watcher listener
    }

    @Override
    public void afterTextChanged(Editable s) {
        //text watcher listener
    }
}

YourFragment.class

public class YourFragment extends BaseFragment {
   ...
}
0

No need for duplication. In your current implementation, it seems your MyTextWatcher class is an inner class of another class (probably fragment class). In this way of implementation you can't share it among all fragment classes.

However if you define your MyTextWatcher class as a standalone class, you can then use it for all fragment classes. To do this, you should only be using the variables and class members that have been declared in scope of the class being defined. In your case saveButton variable doesn't belong to MyTextWatcher class (it's accessible from the outer scope), in such cases, you should import them via the constructor method.

private class MyTextWatcher implements TextWatcher {

        private View view;
        private Button saveButton;

        public MyTextWatcher(View view, Button saveButton) {
            this.view = view;
            this.saveButton = saveButton;
        }

        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            saveButton.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
            saveButton.setClickable(false);
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            saveButton.getBackground().setColorFilter(null);
            switch (view.getId()) {
                case R.id.et_frag1:
                    validateName();
                    break;
            }
        }
    }

You can now instantiate this class 8 times for your 8 fragments.

However, @Bruno Vieira's solution is better (i.e. using a base fragment class).

frogatto
  • 28,539
  • 11
  • 83
  • 129