I've figured out that afterTextChanged() is called the everytime the EditText text changes (and thats why it crashes) but I don't know how to solve the problem. Can anyone please help me!
setting the edit text and adding addTextChangedListener
editText= (EditText) findViewById(R.id.editText);
editText.setInputType(InputType.TYPE_NULL);
editText.addTextChangedListener(textWatcher);
textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//editText.removeTextChangedListener(textWatcher); //this doesn't help
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
// Toast.makeText(mainAct, "OK",Toast.LENGTH_SHORT).show();
String user_answer =editText.getText().toString();
user_ans_int = Integer.parseInt(user_answer);
This should check if the text in the EditText is correct and this is also where the app crashes (without this part it runs perfectly)
if (user_ans_int == answer){
Toast.makeText(mainAct, "True", Toast.LENGTH_SHORT).show();
editText.setText("");
}
else {
Toast.makeText(mainAct, "Naaw - try again haha", Toast.LENGTH_SHORT).show();
editText.setText("");//delete text after checking
tru = false;
}
}
};
}
You will get a NumberFormatException here: user_ans_int = Integer.parseInt(user_answer); It's because you sign a None Number value to your editText and cause its afterTextChanged() being called.
I think you can change your code as following:
user_ans_int = Integer.parseInt(user_answer);
to:
try{
user_ans_int = Integer.parseInt(user_answer);
}catch(NumberFormatException e){
// A none number value is signed to your edittext, do something here.
return;
}
You need to disable the TextWatcher when you update the text in the if..else statement where you check for the correct answer. What you do right now is that you check if the answer is correct and then set the text back to "". That triggers again the text watcher because the text has changed. Then you try to parse to int an empty string. So change your if..else to this:
if (user_ans_int == answer){
editText.removeTextChangedListener(textWatcher);
Toast.makeText(mainAct, "True", Toast.LENGTH_SHORT).show();
editText.setText("");
editText.addTextChangedListener(textWatcher);
} else {
editText.removeTextChangedListener(textWatcher);
Toast.makeText(mainAct, "Naaw - try again haha", Toast.LENGTH_SHORT).show();
editText.setText("");//delete text after checking
tru = false;
editText.addTextChangedListener(textWatcher);
}
Practically, you could also place a try..catch statement where you parse the content of the editText to an int to catch the exception but in this case you will call the textWatcher without needing to do so. I believe that disabling and re-enabling the textWatcher is much more efficient.
// Write down few code inside a afterTextChanged method
if(!s.equal("")){
try {
String user_answer = s.getText().toString();
user_ans_int = Integer.parseInt(user_answer);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}else{
Toast.makeText(mainAct, "Please Enter Text",Toast.LENGTH_SHORT).show();
}
Related
I am attempting to convert an EditText, which is of type number in xml, to an Integer in order to calculate the value in seconds.
hoursIn = (EditText) findViewById(R.id.hoursET);
minIn = (EditText) findViewById(R.id.minET);
start = (Button) findViewById(R.id.startButton);
stop = (Button) findViewById(R.id.stopButton);
textViewTime = (TextView) findViewById(R.id.timeDisp);
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
hoursMs = hrsToMs(inHr);
minMs = minToMs(inMin);
totalTime = hoursMs + minMs;
When I comment the lines where inHr and inMin are initialized I get no error in runtime, however when I leave the code as it is above I get the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{dit.assignment3/dit.assignment3.Timer}: java.lang.NumberFormatException: Invalid int: ""
I have also attempted this while getting the same error starting at the same line of code:
final CounterClass timer = new CounterClass(totalTime, 1000);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (hoursIn != null)
{
inHr = Integer.parseInt(hoursIn.getText().toString());
hoursMs = hrsToMs(inHr);
}
if (minIn != null)
{
inMin = Integer.parseInt(minIn.getText().toString());
minMs = minToMs(inMin);
}
else
{
textViewTime.setText("PLEASE GIVE A TIME");
}
totalTime = hoursMs + minMs;
timer.start();
}
});
Thanks in advance :)
I'm certain that this codes blocks are exactly same as you've shown here. That means You are directly initializing EditText and immediately calling getText() method which causes Exception.
There wont be any value immediately after initialization so that you are getting NumberFormatException when calling Integer.parseInt to empty value.
So I suggest you to put these codes inside some event like buttonClicked like here, so that you can be sure that you've entered some texts. And It's better checking if empty as well,
public void buttonClicked(View v){
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
}
You will get an java.lang.NumberFormatException: Invalid int: "" whenever you try to parse an empty string to Integer. Thus you need to check whether the EditText is empty or not.
You could easily do that as below
if (hoursIn.getText().toString().matches("")) {
Toast.makeText(this, "You did not enter a text", Toast.LENGTH_SHORT).show();
return;
}
OR
you can simply do a check as below
if (hoursIn.getText().toString().equals("")) {
Toast.makeText(this, "You did not enter a text", Toast.LENGTH_SHORT).show();
return;
}
First you have to put the lines where you are reading from edittext inside some event like click of a button. Then check whether anything is entered in the edittext or not, then use try/catch clause to convert it into number.
Try this code.
Add a button to your activity xml file:
<Button
android:height="wrap_content"
android:width="wrap_content"
android:onClick="myClickHandler" />
hoursIn = (EditText) findViewById(R.id.hoursET);
minIn = (EditText) findViewById(R.id.minET);
start = (Button) findViewById(R.id.startButton);
stop = (Button) findViewById(R.id.stopButton);
textViewTime = (TextView) findViewById(R.id.timeDisp);
public void myClickHandler(View v){
if (hoursIn.getText().toString().matches("") || minIn.getText().toString().matches("")){
Toast.makeText(this, "You did not enter a text",Toast.LENGTH_SHORT).show();
return;
} else {
try {
inHr = Integer.parseInt(hoursIn.getText().toString());
inMin = Integer.parseInt(minIn.getText().toString());
hoursMs = hrsToMs(inHr);
minMs = minToMs(inMin);
totalTime = hoursMs + minMs;
Log.i("success");
} catch (NumberFormatException e) {
Toast.makeText(this, "Please enter number only",Toast.LENGTH_SHORT).show();
return;
}
}
}
I'm kinda new to java programming for android, so if i make stupid mistakes, i'm sorry.
So basically, what i wanna make is an app where if you type in the answer correctly, the next textview is gonna be displayed. And when the next textView is displayed, you're needing to give a answer to that textView, when the answer is given correctly. The textview changes again. And so on.
Does anybody have an idea how to do this?
If you don't undarstand what im saying, here is a example:
public class Game extends AppCompatActivity {
public static EditText editText_ans;
public static TextView textView_1;
String enteredText = editText.getText().toString();
If(enteredText = 3 && textView_1 = #string/1+2){
setText.textView_1(#string/3+4)
}
If(enteredText = 7 && textView_1 = #string/3+4){
setText.textView_1("100 - 23")
I'm really stuck and i hope that you guys wanna help me.
If you wanted to change the view without button you can use method addTextChangeListner() which will notify you when when the text hasbeen change for particular edittext.
edittext.addTextChangedListener(textWatcher);
private final TextWatcher textWatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
textView.setVisibility(View.VISIBLE);
}
public void afterTextChanged(Editable s) {
if (s.length() == 0) {
textView.setVisibility(View.GONE);
} else{
textView.setText("You have entered : " + editText.getText());
}
}
};
int x=0; //to keep track of qustions
private List<String> mQuestionList=new ArrayList<>(); //array of question
private List<String> mAnswerList=new ArrayList<>(); //array of question answer
displayquestion.settext(mQuestionList.get(x);//displayquestion is textview
//nextquestion is the button when user click it will first check answer and than move to next question if answer is correct
nextquestion.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String answer=editText.getText().toString();
if(answer.equal(mAnswerList.get(x)){
x=x+1;
displayquestion.settext(mQuestionList.get(x); //answer is correct display next quesion
}else{
//wrong answer
}
}
});
How do I require the user to input data into an EditText and not allow the application to proceed until the EditText is populated?
Right now, my application continues to progress even after the user acknowledges the error message stating the EditText is empty and is required.
private final static int EMPTY_TEXT_ALERT = 0;
protected Dialog onCreateDialog(int id) {
switch(id) {
case EMPTY_TEXT_ALERT: {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("oops!!")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
return builder.create();
}
}
return null;
}
public void sends(View v) {
DatePicker datePicker = (DatePicker) findViewById(R.id.datePicker1);
int year = datePicker.getYear();
int month = datePicker.getMonth();
int day = datePicker.getDayOfMonth();
final EditText phone = (EditText) findViewById(R.id.editText2);
final EditText nameplate = (EditText) findViewById(R.id.editText3);
final EditText issue = (EditText) findViewById(R.id.editText4);
String ph = phone.getText().toString();
if(ph.trim().equals("")) {
// text is empty
showDialog(EMPTY_TEXT_ALERT);
}
String np = nameplate.getText().toString();
if(np.trim().equals("")) {
// text is empty
showDialog(EMPTY_TEXT_ALERT);
}
String i = issue.getText().toString();
if(i.trim().equals("")) {
// text is empty
showDialog(EMPTY_TEXT_ALERT);
}
else
{StringBuilder s= new StringBuilder(100);
s.append(year);
s.append(". ");
s.append(month+1);// month starts from 0 in this
s.append(". ");
s.append(day);
s.append(". ");
s.append(". ");
s.append(ph);
s.append(". ");
s.append(np);
s.append(". ");
s.append(i);
String st=s.toString();
Intent emailIntentt = new Intent(android.content.Intent.ACTION_SEND);
emailIntentt.setType("plain/text");
String aEmailList[] = { "shreyas.t#gmail.com" };
emailIntentt.putExtra(android.content.Intent.EXTRA_EMAIL, aEmailList);
emailIntentt.putExtra(android.content.Intent.EXTRA_SUBJECT, "Feedback");
emailIntentt.putExtra(android.content.Intent.EXTRA_TEXT, st);
startActivity(emailIntentt);
}
}}
You can add return statement after showing the dialog as shown below.
if(i.trim().equals("")) {
// text is empty
showDialog(EMPTY_TEXT_ALERT);
return;
}
It would be better to use Toast messages than showDialog though.
I don't know how you are calling your sends() method, but after any empty error you can just add a return statement immediately after the showDialog(). It means that somehow the sends() method has to get re-invoked via the UI after the user has put in text.
If your sends() method is called from a button via onClick(), then it means the user will see dialog with error, input some text and then, hit the button to send again.
Shreyas Tallani
how to validate the phone number... enters more than 10 digits the
error message should be displayed
If you are just wanting to test the length of the String, just get the String and compare the length to the max length of 10.
In your validate(...) method do something similar to the following:
String ph = phone.getText().toString();
if(ph.trim().equals("")) {
showDialog(EMPTY_TEXT_ALERT);
} else if (ph.length() > 10) {
showDialog(TEXT_TOO_LONG_ALERT);
}
You could also make your EditText only allow numeric values. This would help you validate the numbers. You can do this in the xml file or in code.
xml
android:inputType="TYPE_NUMBER_VARIATION_NORMAL"
code
EditText.setInputType(InputType.TYPE_NUMBER_VARIATION_NORMAL);
First thing you can do, is add a validate(...) method. Inside validate(...), you need to validate all the fields and if anything is left blank then show the error message and stop app progression.
If all the fields are fine, then call your send method. And send(...) should only be sending your data, not checking validation.
I'm trying to perform a check on some information in a database. If i run the following code without it being in a loop it runs fine, but only checking the first row, what i need it to do is to check the names and dates for each row.
If i understand the while loop correctly it would move my cursor to the next row then just run the code again. Can anyone see why this is looping until my program crashes?
while (cursor.moveToNext()) {
String titlefromdb = cursor.getString(3);
if (strTitle.equals(titlefromdb)&& cursor.getString(1).equals(dateselforap)) {
Log.d("insidematch", "date and title matched");
final Dialog matchdiag = new DialogCW2Organisor.this);
matchdiag.setContentView(R.layout.apptmatch);
matchdiag.setTitle("View/Edit Appointment");
matchdiag.setCancelable(true);
TextView matchtxt = (TextView) matchdiag.findViewById(R.id.matchtxt);
matchtxt.setText("Appointment \""+ titlefromdb + "\" already exists, please choose a different event title");
Button btnmatchok = (Button) matchdiag.findViewById(R.id.btnmatch);
btnmatchok.setOnClickListener(new OnClickListener() {
//on click for cancel button
#Override
public void onClick(View v) {
matchdiag.dismiss();}
});
matchdiag.show();
} else {
addAppt(strTime, strTitle, strDet);
cursor = getAppts();
dialog.dismiss();
}
}
Try moving to the first record before calling moveToNext().
Move your functionality into a do/while loop so you can still grab the first record
if (!cursor.moveToFirst())
return; //nothing to do since the cursor is empty
do
{
String titlefromdb = cursor.getString(3);
if (strTitle.equals(titlefromdb)&& cursor.getString(1).equals(dateselforap)) {
Log.d("insidematch", "date and title matched");
final Dialog matchdiag = new DialogCW2Organisor.this);
matchdiag.setContentView(R.layout.apptmatch);
matchdiag.setTitle("View/Edit Appointment");
matchdiag.setCancelable(true);
TextView matchtxt = (TextView) matchdiag.findViewById(R.id.matchtxt);
matchtxt.setText("Appointment \""+ titlefromdb + "\" already exists, please choose a different event title");
Button btnmatchok = (Button) matchdiag.findViewById(R.id.btnmatch);
btnmatchok.setOnClickListener(new OnClickListener() {
//on click for cancel button
#Override
public void onClick(View v) {
matchdiag.dismiss();
}
});
matchdiag.show();
} else {
addAppt(strTime, strTitle, strDet);
cursor = getAppts();
dialog.dismiss();
}
} while (cursor.moveToNext());
I have also run into the infinite loop problem, which really baffled me as well, since a while !moveToNext() loop should definitely finish.
However, the workaround is to use a for loop over the length of the cursor, and process each cursor.moveToPosition(i).
for (int i = 0; i <= cursorLen; i++) {
if (!cursor.moveToPosition(i)) {
return;
}
// process your cursor
}
I feel like this must be a bug with the Cursor implementation, because a while loop over cursor.moveToNext() should always finish.
Im trying to make an app that converts distance/area/volume using spinners as a unit selection method. Calculations are meant be done and then the output sent to a textview based on what is entered into the EditText. But the output is only ever 0.0 and nothing else. Can anybody help with this ?
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
switch(pos){
case 0:
option1.setAdapter(length);
option2.setAdapter(length);
return;
case 1:
option1.setAdapter(area);
option2.setAdapter(area);
return;
default:
}
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
});
option1.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if(pos>=0) {
stringInput = edittext1.getText().toString();
if(stringInput == null || stringInput.isEmpty()) {
doubleInput = 0.0;
}
else {
doubleInput = Double.parseDouble(edittext1.getText().toString());
}
}
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
});
option2.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
switch(pos) {
case 0:
miles = doubleInput * 1;
textview1.setText("" + String.valueOf(miles));
return;
case 1:
km = doubleInput * 1.609344;
textview1.setText("" + String.valueOf(km));
return;
default:
}
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
});
At the risk of sounding like a really old man, this looks like your college homework... Is it?
Your code has changed since asking the question, which makes it pretty difficult to answer! Luckily I managed to scrape your code into Eclipse before you changed it... Anyway, in your original code your performing all your operations in the create method, at which point you haven't entered a value for edittext1 (unless it's set to some sensible default, which I presume would be 0, hence always getting zero as your answer?)
// Whilst setting up a view the create method will not have a
// reasonable value for edittext1 - or it will be your default
String stringInput = (edittext1.getText().toString());
if (stringInput.isEmpty()) {
doubleInput = 0.0; // Will always enter this line
} else {
doubleInput = Double.parseDouble(edittext1.getText().toString());
}
You've duplicated the code...
output1 = (TextView) findViewById(R.id.output1);
Actually output1 through to output10 (ie all ten lines) are duplicated.
As to your updated code, is it still giving you a problem? Are you sure that stringInput has a value? I mean have you typed something in? You could check by debugging your program..
The following is also error prone as FloatingCoder suggests, and is likely to break...
doubleInput = Double.parseDouble(edittext1.getText().toString());
A better way to do this (because it catches the exception that Java might throw) is
doubleInput = 0.0;
String inputStr = question.getText().toString();
try {
doubleInput = Double.parseDouble(inputStr);
} catch (NumberFormatException e) {
// This should probably do something more useful? i.e. tell
// the user what they've done wrong...
Log.e("Android",
"Double throws a NumberFormatException if you enter text that is not a number");
}
Oh and Android has some helper utilities for checking strings, see TextUtils, or just my example...
if (!TextUtils.isEmpty(inputStr)) { // checks for "" and null (see documentation)
doubleInput = Double.parseDouble(inputStr);
}
I'd REALLY recommend writing a simple test case for a calculation that looks incorrect, because two text boxes and a button really aren't hard to throw together and are seriously easy to debug without the need for all the spinners getting in the way... Anyway hope this helped, oh and my complete example with two edittexts and a button, I'll just post that here... Hope it helps...
private Button btnCalc;
private EditText question, answer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
answer = (EditText) findViewById(R.id.answer);
question = (EditText) findViewById(R.id.question);
btnCalc = (Button) findViewById(R.id.btnCalc);
// The OnClickListener here will be executed outside the "Create",
// i.e., when you actually click on the button, which will give you
// a chance to enter some values in the question edittext...
btnCalc.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
double in = 0.0;
try {
String inputStr = question.getText().toString();
// if you want to check it use
if (!TextUtils.isEmpty(inputStr)) {
in = Double.parseDouble(inputStr);
}
} catch (NumberFormatException e) {
// This should probably do something more useful? i.e. tell
// the user what they've done wrong...
Log.e("Android",
"Double throws a NumberFormatException if you enter text that is not a number");
}
double miles = in * 1.6;
answer.setText(String.valueOf(miles));
}
});
}
It's a little hard to tell from the code you posted, but my guess is that you are setting doubleInput when option 1 is selected. If you are entering the number after you select option 1, it will always be 0.0, as the number was not in the text area when the spinner was changed.
Use a debugger to step through the code and see if you are ever reaching the line
doubleInput = Double.parseDouble(edittext1.getText().toString());
and to check that the number is getting set properly at that point.