how setOnKeyListener works - java

we got homework to make convertor of weights where the fields are updated while typing the number (no need to click "calculate" or anything). one of the students offered the code below.
the code works: when putting a number in field 1, field 2 changes while typing.
what i dont understand is how does that work?
in the onKey method, no value is given to View int and keyEvent
so how does the listener "knows" on which view to and what keys to listen to or what event to activate ?
public class Screen extends Activity {
double weight = 2.20462;
EditText kgEdit, lbsEdit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
kgEdit = (EditText) findViewById(R.id.kgEdit);
lbsEdit = (EditText) findViewById(R.id.lbsEdit);
kgEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String kg = kgEdit.getText().toString();
if (kg.isEmpty()) {
lbsEdit.setText("");
} else {
double num = Double.valueOf(kgEdit.getText().toString()) * weight;
lbsEdit.setText(num + "");
}
return false;
}
});
lbsEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
String lbs = lbsEdit.getText().toString();
if (lbs.isEmpty()) {
kgEdit.setText("");
} else {
double num = Double.valueOf(lbsEdit.getText().toString()) / weight;
kgEdit.setText(num + "");
}
return false;
}
});
}
}

I'm going to focus on just 1 of the text fields to answer this. Look at this first line:
kgEdit = (EditText) findViewById(R.id.kgEdit);
All this does is get a reference to the EditText for entering kg. Now that there is a reference, we can call methods on that object.
Next, we have this:
kgEdit.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// ...
}
}
What the above does is the following. Take our reference to the EditText for kilograms that we retrieved in our first line. The method setOnKeyListener does the following (from here): "Register a callback to be invoked when a hardware key is pressed in this view."
What this means is that you've now told the view that you want to be informed every time the user presses a key while this EditText has the focus. You make this call to the Android API and in the background Android handles everything you're asking. It will call the method with the View view, int keyCode and KeyEvent event. You give it a method that then handles those inputs. So nowhere in your code do you need to call the method, Android calls it in the background where you'll never have to see or worry about it.
Now, because you called the method on kgEdit, that means the following code will ONLY be called when kgEdit is focused and keys are typed, so there's no confusion with the other EditText. It gets its own method call later, just below. Here's the rest of the code inside the setOnKeyListener:
String kg = kgEdit.getText().toString();
if (kg.isEmpty()) {
lbsEdit.setText("");
} else {
double num = Double.valueOf(kgEdit.getText().toString()) * weight;
lbsEdit.setText(num + "");
}
return false;
What this does is get the current text in kgEdit, which has already been updated with the key the user pressed. And it just checks if the text is empty, and if so remove the text in lbsEdit. If it's not empty, then get the text, convert it to a number, convert the number from kg to lbs and update lbsEdit

You have to use addTextChangedListener like this-
EditText editText = (EditText) findViewById(R.id.editText1);
editText.addTextChangedListener(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(Editable s) {
//do here your calculation
String data = s.toString();
}
});

Related

How to use a value from one method to other?

So i was developing a bmi calculator activity in android studio. And i ran into a problem where i got a value of two variable inside from two methods for different TextView which was defined in the class. That shouldn't be problem but once i switch to another TextView in app. The first one sends a zero value, which is the problem, Anyone knows how to fix it? Thanks !
The two methods in onCreate which give value:
inheight.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
height = Double.parseDouble(inheight.getText().toString());
if(KeyEvent.KEYCODE_DEL== keyCode)
{
if(inheight.getText().length() != 0)
inheight.setText(inheight.getText().subSequence(0,inheight.getText().length()-1));
}
return true;
}
});
inweight.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
weight = Integer.parseInt(inweight.getText().toString());
if(KeyEvent.KEYCODE_DEL == keyCode)
{
if(inweight.getText().length() != 0)
inweight.setText(inweight.getText().subSequence(0,inweight.getText().length()-1));
}
return true;
}
});
And the Calculate method where i try to calulate
public void calculate()
{
if(height!=0 && weight !=0)
{
// do this
}
else
{
Toast.makeText(this, "Error: Values Cannot Be Zero!", Toast.LENGTH_LONG).show();
}
So when i run it always shows the toast message :(. Please Help!
As stated in the android documentation, View.OnKeyListener is useful only for hardware keyboards , and a software input method (like the one android uses), has no obligation to trigger this listener.
So instead of using View.OnKeyListener to get your values i would try a different approach (i.e getting the values after pressing a button, implementing View.OnClickListener )
Also are you sure that only the first TextView gives you the zero value, or both ?

I'm trying to get a button to go to next activity given conditions are true but it won't work

This is the code that should let me go to next activity with 3 methods I made. The checkEditText method should take an editText parameter and change it to a string and then make sure it is not empty. The checkTextLetters should take the editText parameter and then make sure it contains only letters and/or spaces. Then the method configureNextButton should only run if the 2 previous methods are true:
private boolean checkEditText(EditText text){
if(text.getText().toString().trim().length() > 0)
{
return true;
}
//try and print to screen "name is left blank//
return false;
}
I would think this method would return true whenever I type asdf or something in the plain text:
private boolean checkTextLetters(EditText text){
String line = text.getText().toString();
//checks to make sure that the string contains only the characters a-z and A-Z and/or spaces
boolean checkChars = line.matches("[a-zA-Z]");
boolean checkSpaces = line.matches("\\s+");
if(checkChars && checkSpaces){
return true;
}
else if(checkChars){
return true;
}
return false;
}
This method should just take the text from the plain text that I typed in and check to make sure it only contains letters and spaces:
private void configureNextButton(boolean textCheck, boolean checkIfLetters){
//create if statement to not activate button if editText is empty
if(!textCheck || !checkIfLetters) {
return;
}
//will create variable 'mainButton' from the id of 'button' on MainActivity
Button mainButton = findViewById(R.id.button);
//sets the 'mainButton' to respond to a click
mainButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//states that when 'mainButton' is clicked, it begins Intent to switch to Main2Activity
startActivity(new Intent(MainActivity.this, Main2Activity.class));
}
});
}
This is the method where the button should take me to the next activity. I save 'checkEditText' method and 'checkTextLetters' to boolean variables and pass them on as the parameters for this method so that if they equal true then the code will let the button take it to the next activity and if either are false then it won't do anything:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editTextLines = findViewById(R.id.editText);
//call method to use 'button' to go to next activity given all conditions are true
boolean checkNotEmpty = checkEditText(editTextLines);
boolean checkIfLetters = checkTextLetters(editTextLines);
configureNextButton(checkNotEmpty,checkIfLetters);
}
Here is the main method where I put it all together and run it. It will work when I just set the checkNotEmpty and checkIfLetters to either true or false. Whenever I try and declare their value by calling my two methods then the button won't do anything.
I changed the code and got rid of the 'checkEditText' and 'CheckTextLetters' methods in place of a TextWatcher method in the main method. It works but has bugs. 1. When it first runs, I can press the button and it goes to the next activity. 2. I can enter any letter and nums but won't accept just nums. I want the EditText to simply, not work if it is empty, allow only letters and spaces
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = findViewById(R.id.editText);
final Button button = findViewById(R.id.button);
button.setClickable(false);
editText.addTextChangedListener(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(Editable s) {
if(s.toString().length() == 0)
button.setClickable(false);
else{
String line = s.toString();
boolean value = line.matches("[a-zA-Z]");
// set bool 'value' to check for alphabet letters
if(value)
button.setClickable(true);
}
}
});
//call method to use 'button' to go to next activity given all conditions are true
configureNextButton();
I think you need to use TextWatcher.
See this example code: Implement this with your logic and change existing function to accept String instead of EditText.
btnSubmit.setClickable(false);
edtText.addTextChangedListener(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(Editable s) {
if(s.toString().length() == 0){
btnSubmit.setClickable(false);
}
else
{
//Validate if its Alphabets only - if returned true,
boolean value = validateAlphabetsOnly(s.toString());
if(value)
{
btnSubmit.setClickable(true);
}
}
}
});
In onCreate, activity is just created. User hasn't got any chance to write in EditText yet. So you will need to use TextChangedListener for EditText.

How to allow EditText to be empty and show setError message?

For many days now, I have been struggling to understand why the help that I found online didn't solve my issue, so I thought my best bet would be to ask here.
As a side note, I'm aware that my variable names aren't the best,and I am in general a newbie when it gets to Android development, but I think I can understand and I'm able sort issues fairly easily - except perhaps this thing.
I'm creating a simple app that allows me to get the total of profits of an item sold, so it would take the shipping price into consideration and do the calculation automatically. For this, when the shipping price would be left empty (blank), I would want to return a message saying it can't be empty, and a '0' must be entered to do the calculation. (My EditText field only allows numbers to be entered)
public class MainActivity extends AppCompatActivity {
double shippingNum;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
shippingPrice = (EditText) findViewById(R.id.shippingPrice);
}
calculateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
shippingNum = Integer.parseInt(shippingPrice.getText().toString());
if(shippingPrice.getText().toString().equals("") ||
shippingPrice.getText().length() == 0){
//shippingPrice.setText("0");
shippingPrice.setError("You can't leave this field empty! Enter something!");
}
I have also tried other variations such as:
if(TextUtils.isEmpty(shippingPrice.getText().toString().trim())){
shippingPrice.setError("You can't leave this field empty! Enter something!");
shippingPrice.setText("0");
}
But none of these seem to have allow me to leave the field empty without crashing. I've tried a dozen of different methods which I have realised that they were a waste of time as they wouldn't work - at least I've learned where I can use them.
Any help is much appreciated and thank you.
You could try just doing, check the length of the edit text, if zero display a toast saying enter more if not do the next part of the program:
if(getText().length() == 0){
Toast.makeText(getActivity(), "Enter values into field!",
Toast.LENGTH_LONG).show();
}
else{
// continue with the desired function of the program
}
Add this below method in your class :
public static boolean checkBlankValidation(EditText editText) {
if (TextUtils.isEmpty(editText.getText().toString().trim())) {
return false;
} else {
return true;
}
}
And call this method like below :
if (!checkBlankValidation(shippingPrice)) {
shippingPrice.requestFocus();
Toast.makeText(this, "Field should not be empty", Toast.LENGTH_SHORT).show();
return false;
} else {
return true;
}
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText editText = findViewById(R.id.edittext);
editText.addTextChangedListener(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) {
if (s.toString().trim().length() <= 0) {
editText.setError("This Field is required");
editText.requestFocus();
} else
editText.setError(null);
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
}

Android - Bolding Part of Text in EditText

There's a similar answer here, but it doesn't state what I'm about to ask.
I have a 'Bold Text' option in my Android view and if a user selects that option, a boolean gets set as true in the code behind.
Using a TextWatcher, how can I change the text typed by the user to bold after a specific point in the EditText. If the user turns it off, the text typed after should be in normal styling. Everything depends on the boolean value.
Here's what I have so far:
Boolean isBolded = false;
// Code that turns the bold option true and false...
contentBox = (EditText) findViewById(R.id.contentBox);
contentBox.addTextChangedListener(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) {
if(isBolded)
{
//Start bolding the text typed after that point
}
else
{
//Stop styling the text typed after that point
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
The difficulty would be to determine the points in the EditText where the user decides to turn bolding off and on while typing. What do you guys have in mind?
Set Html.fromHtml("<b>This part will be bold</b> This won't!") as the Text.

Detect a new line in android text view

I am trying to create my first Android application in which it will help me do some outlining.
Quite simply I am trying to write some sort of detection that when a line starts with a hyphen, the next time there is a new line a hyphen will be placed in front of that new line.
I am looking for any pointers or directions for where I should be looking, as this is my first app.
Or in another sense what would be the best way to detect text being typed and change the EditText based on it.
Since OnKeyListener does not work for Soft keyboard, I recommend using the TextWatcher.
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if( -1 != charSequence.toString().indexOf("\n") ){
// Do your stuff
}
}
When you want to replace this sequence by some other string, try this:
public void afterTextChanged(Editable editable) {
int i = editable.toString().indexOf("\n");
if ( i != -1 ) {
editable.replace(i, i+1, "");
}
}
You could use the text watcher class of android which can be attached to a event.
EditText mPasswordLength = (EditText)findViewById(R.id.password_length);
mPasswordLength.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s){
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count){
}
});
The method you can use to edit the text is onTextChanged. More detailed description about when and why these events are fired is explained in this post.. Read the answer with max up votes.
You want an OnKeyListener for the EditText, then in the listener's onKey(View v, int keyCode, KeyEvent event) method, see if it is the event is KeyEvent.ACTION_DOWN and the keyCode is for KeyEvent.KEYCODE_ENTER, if so then append a '-' to the end of the edittext.

Categories

Resources