Reputation: 99
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
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
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
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
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