Chiranjeev Jain
Chiranjeev Jain

Reputation: 99

How do I change value of one EditText based on the input in another

I currently have an EditText for temperature in Celsius and a TextView in Fahrenheit with it to display the answer. I have used TextChangedListener but this doesn't work with EditText. I can't change the values in EditText using TextChangedListener. Is there a way I can do this.? I want the user to enter a value in anyof the EditTexts and get result in the other one. Here's my code with the TextView. My MainActivity:

    public class MainActivity extends ActionBarActivity {

    EditText C, F;
    TextView Ct, Ft;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        C = (EditText) findViewById(R.id.celsius);
        F = (EditText) findViewById(R.id.fahrenheit);
        Ct = (TextView) findViewById(R.id.celsiusTextView);
        Ft = (TextView) findViewById(R.id.fahrenheitTextView);

        C.addTextChangedListener(new TextWatcher() {

            double f,
            c;

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (!s.toString().equals("")) {
                    c = Double.parseDouble(s.toString());
                    f = (((9 / 5) * c) + 32);
                    Ft.setText(String.valueOf(f));
                } else {
                    Ft.setText("");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        F.addTextChangedListener(new TextWatcher() {

            double f,
            c;

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (!s.toString().equals("")) {
                    f = Double.parseDouble(s.toString());
                    c = ((f - 32) * 5 / 9);
                    Ct.setText(String.valueOf(c));
                } else {
                    Ct.setText("");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

    }
}

And my XML:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:id="@+id/nameText"
    android:background="@drawable/fab_linear_layout">

        <TextView
            android:text="@string/converter"
            android:layout_gravity="bottom"
            android:textSize="30sp"
            android:textColor="#FFFFFF"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="20dp"/>

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_below="@+id/nameText"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:id="@+id/linearLayout1"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true">

    <EditText
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:inputType="numberSigned|numberDecimal"
        android:hint="@string/celsius"
        android:id="@+id/celsius"/>

    <TextView
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/fahrenheit"
        android:id="@+id/fahrenheitTextView"/>

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_below="@+id/linearLayout1"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:id="@+id/linearLayout2"
    android:layout_centerVertical="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true">

    <EditText
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:inputType="numberSigned|numberDecimal"
        android:hint="@string/fahrenheit"
        android:id="@+id/fahrenheit"/>

    <TextView
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="@string/celsius"
        android:id="@+id/celsiusTextView"/>

</LinearLayout>

As can be seen from the code, I want to remove the redundant TextViews and instead get the answer in the EditText.

Upvotes: 1

Views: 7657

Answers (4)

Emmanuel Guerra
Emmanuel Guerra

Reputation: 1624

Another way to achieve this is checking if the EditText has focus (Kotlin code):

inputOne.addTextChangedListener { editableString->
        //do nothing if this EditText is not being edited.
        if(!inputOne.hasFocus())
            return@addTextChangedListener
        //do stuff
}

Upvotes: 1

Shivam Verma
Shivam Verma

Reputation: 8023

//Untested Code.

If you just want to use two EditTexts. It might work if you remove the text watcher from the other EditText in onTextChanged.

Suppose the text watcher for the Fahrenheit EditText is called fWatcher and the text watcher for Celcius EditText is called cWatcher.

The idea will be that while you're modifying the text in the celsius edit text, you remove the text watcher on the fahrenheit edittext so that it doesn't fire that listener while you're editing the text.

Define cWatcher like this :

TextWatcher cWatcher = new TextWatcher() {

    double f,
    c;

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        fEditText.removeTextChangedListener(fWatcher);
        if (!s.toString().equals("")) {
            c = Double.parseDouble(s.toString());
            f = (((9 / 5) * c) + 32);
            Ft.setText(String.valueOf(f));
        } else {
            Ft.setText("");
        }
        fEditText.setTextChangedListener(fWatcher);
    }

    @Override
    public void afterTextChanged(Editable s) {

    }
}

Similarly define the other TextWatcher.

Upvotes: 3

Trebia Project.
Trebia Project.

Reputation: 940

Looking at your post you are entering in an infinite loop and the app crushes. As you have onTextChanged method in both EditText, when C changes the text, changes F that changes C because is changed.... and all again and again.

Do an easy test, you will see that the change is working if you remove one of the method from either C or F.

What you need to do is to differenciate between the text changed by the user and the text changed by the app automatically.

What I suggest is the following.

Define a boolean that will be the one that will make the differentiation:

EditText C, F;
TextView Ct, Ft;
private Boolean machine_changed_edittext = false;

Not at each onTextChanged add the following:

@Override
        public void onTextChanged(CharSequence s, int start, int before, int       count) {
            //We check that the change is human
            if (! machine_changed_edittext) {
                machine_changed_edittext = true;
                if (!s.toString().equals("")) {
                          c = Double.parseDouble(s.toString());
                          f = (((9 / 5) * c) + 32);
                          F.setText(String.valueOf(f));
                } else {
                          F.setText("");
                }
                //Now as it is finished we declare back the Boolean to the correct value
                machine_changed_edittext = false;
            }
        }

I think I should have done it right, but is just a game where you put the boolean values changes. If my idea does not work, just tell me and we initiate a chat, we can debug it.

Upvotes: 2

Nimrod Dayan
Nimrod Dayan

Reputation: 3100

You're setting the text on the wrong view:

Ft.setText(String.valueOf(f));
        } else {
            Ft.setText("");

instead of Ft which is a TextView you should call setText on F which is EditText.

Upvotes: -2

Related Questions