javaandroidfor-loopandroid-edittextaddtextchangedlistener

AddTextChangedListener to Loop-generated EditText views


I'm new to Android development. I'm facing a dead end developing an app for a project. Please take some time and help me out.

The problem: I am generating some EditText views nested in a LinearLayout using a for loop.

For example:

LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
for (int i=0,j=10;i<j;i++) {
    EditText et = new EditText(this);
    rootView.addView(et);
    et.setHint("EditText No. "+ i);
    et.setId(i);
} // This code is for example purposes only.

Now, I can't seem to understand how I can set an addTextChangedListener on the EditText that is focused at a particular time and set that text on other EditTexts. Please tell me what approach should I adopt to achieve this. I tried my best to explain the problem; however, if there is still any ambiguity, feel free to comment and ask. I'm waiting for a solution to this problem.

In terms of screenshots:

What I have:

enter image description here

What I want:

enter image description here

I hope this clears things up!

**

EDIT:

Thanks to TylerSebastian for the solution. I got it to work. Here is the final code: (Inside OnCreate() method)

final LinearLayout rootView = (LinearLayout) findViewById(R.id.rootview);
    for (int i=0,j=10;i<j;i++) {

        final EditText et = new EditText(this);
        rootView.addView(et);
        et.setHint("EditText No. "+ i);
        et.setId(i);
        final TextWatcher textwatcher = 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(final Editable s) {
                for (int i=0;i<10;i++){
                    EditText view = (EditText) findViewById(i);
                    if (view != et){
                        view.setText(s.toString());
                    }
                }
            }
        };
        et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    et.addTextChangedListener(textwatcher);
                } else {
                    et.removeTextChangedListener(textwatcher);
                }
            }
        });

    } 

**


Solution

  • I don't have access to a machine with AS on it atm so no guarantee that the following is bug-free, but this should point you in the right direction:

    final LinearLayout rootLayout = ...;
    
    // within your loop
    et.addTextChangedListener(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(final Editable s) {
            for (int i = 0; i < rootLayout.getChildCount(); i++) {
                View view = rootLayout.getChildAt(i);
    
                if (view instanceof EditText && view != et) {
                    ((EditText) view).setText(s.toString());
                }
            }
        }
    });
    

    edit: so the above will cause an infinite loop - see my comment below

    How about:

    final LinearLayout rootLayout = ...;
    
    // again, within your loop
    TextWatcher textWatcher = 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(final Editable s) {
            for (int i = 0; i < rootLayout.getChildCount(); i++) {
                View view = rootLayout.getChildAt(i);
    
                if (view instanceof EditText && view != et) {
                    ((EditText) view).setText(s.toString());
                }
            }
        }
    };
    
    et.setOnFocusChangeListener(new OnFocusChangeListener() {
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                 ((EditText) view).addTextChangedListener(textWatcher);
            } else {
                 ((EditText) view).removeTextChangedListener(textWatcher);
            }
        }
    });
    

    basically, only the focused element will have the textwatcher