How to send key event to an edit text - java

For example, send a backspace key to the edit text control to remove a character or send a char code like 112 to append a character in the edittext control programmatically.
Actually, I need a method like
void onKeyReceived(int keyCode)
{
// here I would like to append the keyCode to EditText, I know how to add a visible character, but what about some special keys, like arrow key, backspace key.
}

To send a simulated backspace key press to an EditText you have to send both key press and release events. Like this:
mEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_DEL, 0));
mEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_DEL, 0));
This can be used to send any other key code, not just delete.

Your question is not all that clear, but I think you want to modify/append text to a TextView when certain buttons are pressed. If so, you want a combination of some of the existing answers.
#Override
public void onCreate(Bundle savedInstanceState) {
...
(TextView) textView = (TextView) findViewById(R.id.myTextView);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch(keyCode) {
case KeyEvent.KEYCODE_BACK:
// user pressed the "BACK" key. Append "_back" to the text
textView.append("_back");
return true;
case KeyEvent.KEYCODE_DEL:
// user pressed the "BACKSPACE" key. Append "_del" to the text
textView.append("_del");
return true;
default:
return super.onKeyDown(keyCode, event);
}
}
Whether to return true for each case you have handled (as above) or to always return super.onKeyDown(keyCode, event); after your switch statement will depend on your exact requirements. Check the documentation for the behaviour of onKeyDown
If, instead of appending text in each case you want to delete a character, or move the cursor, you could do that in each case statement. Have a look at the TextView documentation for the different methods you can call. Also look at the KeyEvent documentation for a list of the keys you can check for.

I think you need use addTextChangedListener to EditText.
Refer the answer of EditText input with pattern android and Live editing of users input

virsir , I suppose you are looking for dispatching hard keys programmatically.
For that you may try dispatch (KeyEvent.Callback receiver, KeyEvent.DispatcherState state, Object target) with an example at Back and other hard keys: three stories
Hope that helps.

Check for key events in your activity. for example, this code listens for back keypress:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}

just use the setText method to do this. If you are wanting to simulate a backspace you could do something like this.
String curText = mEditText.getText();
if(!curText.equals("")){
mEditText.setText(curText.subString(0, curText.length - 1));
}

to simulate backspace key, just ad code
editText.setText(editText.getText().substring(0,editText.getText().length()-1))
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
to simulate adding a character, put the code
editText.setText(editText.getText() + (char) charCode)
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);

Take a look at this article: creating-input-method.html. Basically, you can either manually send KeyEvents or you can manually edit and commit text around the cursor in the application's Input View.These are all done via your IME's InputConnection.
Hope this helps,

if you want a click listener, the best way to do it is this:
View textfield = findViewById(R.id.textfield);
textfield .setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
/*your code for the click event here*/ }});
if you want a backspace button, do this:
public void backSpace() {
EditText textfield = (EditText)findViewById(R.id.textfield);
try {
textfield.getText().delete(textfield.getSelectionEnd() - 1, textfield.getSelectionStart());
} catch (Exception e) {
try {
textfield.getText().delete(textfield.length() - 1, textfield.length());
} catch (Exception myException) {
//textfield.getText().delete(textfield.length(), textfield.length() - 1);
}
}
}
if you want to append a character in the EditText, do this:
EditText textfield = (EditText)findViewById(R.id.textfield);
textfield.setText(textfield.getText().concat("112"));

try implementing TextWatcher interface.
it has 3 methods which you need to override.
public void afterTextChanged(Editable s) {
Log.v("afterTextChanged","here");
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.v("beforeTextChanged","here");
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
I think this will work.

Related

Why KeyListener.onKey triggers twice?

I want to handle the click on the "ok" key of the onscreen keyboard. For that purpose I added a KeyListener to the text field:
textField = (EditText) view.findViewById(R.id.text_field);
textField.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View view, int keyCode, KeyEvent event) {
boolean handled = false;
if (keyCode == KeyEvent.KEYCODE_ENTER) {
okPressed(view);
handled = true;
}
return handled;
}
});
And in the okPressed method I'm checking the content:
private void okPressed(View view) {
String value = textField.getText().toString().trim();
if (value.equals("")) {
Toast.makeText(view.getContext(), "Error", Toast.LENGTH_SHORT).show();
return;
}
}
And now for the case that my text field is not empty, everything works fine. But in the case the field contains no text, my okPressed method is executed twice. But why?
Per KeyEvent's documentation:
Each key press is described by a sequence of key events. A key press starts with a key event with ACTION_DOWN.
The last key event is a ACTION_UP for the key up.
You should check the result of getAction() to filter for only the key action you want (i.e., ACTION_UP if you only want to trigger when the user releases or ACTION_DOWN if you want to trigger as soon as they touch the button).

Simple edit text?

I am getting the users information from an edit text. I do have a listener that gets their entered information after clicking submit, but I want to also get the entered info after clicking back or clicking somewhere else:
For example, if the users clicks on the black space, I want to get the text they entered. If they type "hello", and click back rather than "enter", I still want to get the text hello. If, however, they don't type anything, I don't care about their input. How can I achieve this?
Thanks,
Ruchir
First add these as a class variables
private String inputText;
private EditText yourEditText;
Get the instance of your EditText View
yourEditText = (EditText)findViewById(R.id.your_editText);
When a button is clicked, you can get the content of the EditText field like this
Button mButton = (Button)findViewById(R.id.m_button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
inputText = yourEditText.getText().toString();
}
});
If a user press the Back button, you can get the input if any like this
#Override
public void onBackPressed() {
inputText = yourEditText.getText().toString();
super.onBackPressed();
}
Then check if there is any value assigned to your String variable
if(inputText.equals("") || inputText == null){
// there is no value
}else{
// there is value entered.
}
To extend my solution for clicking some where else
add a class variable
private boolean isEditTextHasFocus;
then create a focus listener which will check if the Edittext has focus
private View.OnFocusChangeListener focusListener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus){
isEditTextHasFocus = true;
} else {
isEditTextHasFocus = false;
}
}
}
Add this line in onCreate(Bundle savedInstanceState) method
yourEditText.setOnFocusChangeListener(focusListener);
Then override to onTouchEvent(MotionEvent event) listener and access the Edittext input when the key up action is called
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if(!isEditTextHasFocus){
inputText = yourEditText.getText().toString();
}
}
return true;
}
I hope this will give you a further idea to find your unique solution.
Overriding what happens when the back button is pressed is bad practice and is unnecessary for what you want to do.
You need to use a special listener called onFocusChangedListener. This function is called anytime an element gains or loses focus. In this case for your editText it will be called whenever someone clicks on it or away. Pressing the back button or leaving the editText in any way will call this function. In the following code I check if
if(!username.hasFocus())
which makes it so the value is only saved when focus from the editText is lost rather than everytime focus is changed.
You haven't added any of your own code so I am just going to use obvious placeholder variables in my code example.
Edittext username = (EditText findViewById(R.id.YOUR_EDITTEXTS_ID);
String previousValue = ""; // to keep track of value change
String usernameValue = "";
username.setOnFocusChangeListener(new View.OnFocusChangeListener(
{
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (username.hasFocus()){
//take note of value for comparison when clicking away
previousValue = username.getText().toString();
} else if (!username.hasFocus()){
// check if value has changed
if (!previousValue.equals(username.getText().toString()){
usernameValue = username.getText().toString();
}
}
}
});

Implementing Search Button on my Keyboard

I'm trying to implement a search button in place of the regular enter button on my inbuilt android keyboard. I tried doing:
resultView.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// TODO Auto-generated method stub
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
System.out.println("You searched for this!");
return true;
}
return false;
}
But the regular 'enter' button is still appearing. I do not want to use XML and i'm creating my UI completely on JAVA. What should i do? Help would be appreciated. Thanks!
EditText view = new EditText(this);
view.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
view.setSingleLine(true);
And you are good to go, you set SingleLine attribute to change the new line button "default behavior in multi-line editext" to search button .
Sounds like you need to set the imeOptions programmatically. Try something like this:
editText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
You might have to play around with the available options to get exactly what you want.

TextView editable onLongClick -- But one small issue when BACK button pressed

I have been search SO for days and have finally compiled enough answers to accomplish what I wanted. First off, it seems to be an often asked question but not really answered (at least not the way I was looking for it). I thought I would share my findings but I also have one small issue left that I would like to ask for help with. Here goes:
I have a TextView which displays a score. It starts at 0 and at an onClick event the score increments and updates the TextView (score is tracked as a byte - valScore).
onLongClick: This was the challenge. I want the user to be able to do a LongClick to correct/change the score. I first found a solution that utilized another layout.xml file with just an EditText element and the OK and CANCEL buttons. This was very cumbersome to change the score as it involved the LongClick, then the dialog opens, then you had to click on the EditText element to open the keyboard, then you enter the value, click DONE and then click OK. I shortened it by figuring out how to open the software keyboard automatically when the dialog opened. However, you still had to click DONE and then OK. I didn't like this action so I continued searching.
Days later I came up with a bit of code and then more and with a lot of playing/hacking around I came up with the following solution:
// set the onLongClickListener for tvScoreHome
tvScoreHome.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
tvScoreHome.setInputType( InputType.TYPE_CLASS_NUMBER );
tvScoreHome.setFocusable(true);
tvScoreHome.setFocusableInTouchMode( true );
tvScoreHome.requestFocus();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
imm.showSoftInput(tvScoreHome, InputMethodManager.SHOW_FORCED);
tvScoreHome.setText("");
tvScoreHome.setOnEditorActionListener( new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
valScoreHome = Byte.valueOf( tvScoreHome.getText().toString() );
// This part will hide the keyboard after input
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
tvScoreHome.setFocusable( false );
tvScoreHome.setFocusableInTouchMode( false );
tvScoreHome.setText( Byte.toString(valScoreHome) );
return true;
}
return false;
}
});
return true;
}
});
This works EXACTLY how I want. User performs LongClick the keyboard opens, the user enters the new value and clicks DONE. The TextView is updated and it works great!
The problem arises if the user changes their mind and hits the BACK button on the device. The keyboard closes (GOOD), but then the focus remains on the TextView instead of removing the focus like I do if the DONE button is pressed. So if you cancel out of a change every click after that results in the keyboard opening again instead of just incrementing the score -- until you actually type a value into the keyboard and click DONE (then the regular behavior takes over again. I need to setFocusableInTouchMode to FALSE if the BACK button is pressed.
The other issue is that the setText() method is executed even if the BACK button is pressed if a different value has been typed in. Even though valScoreHome isn't updated the TextView changes. On the next increment it goes to the correct number again, but the setText() should not execute if the BACK button is pressed.
Can someone help me figure this out please?
Both issues can be handled by subclassing TextView.
The back button press that closes the keyboard is handled by overriding onKeyPreIme.
To avoid updating the text when the user closes the keyboard, the score value is saved in the variable mScore, but only if the TextView is currently not focusable. That means, the TextView "remembers" the current value of the score, that was not entered by the user. When the user closes the the keyboard, the text is set back to the saved value.
public class ScoreTextView extends TextView {
private CharSequence mScore;
public ScoreTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setText(CharSequence text, BufferType type) {
if (!isFocusable()) {
mScore = text;
}
super.setText(text, type);
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
setFocusable(false);
setFocusableInTouchMode(false);
setText(mScore);
}
return super.onKeyPreIme(keyCode, event);
}
}

Updating TextView on keyDown?

I am trying to update a TextView which will show the system volume. I have managed to capture the current system volume and display it, but it doesn't update when the volume is turned up/down (obviously).
I know there is an easy solution somewhere I just cant think! onKeyListeners?
I am now using this but it doesnt work:
TextView sysVol = (TextView)findViewById(R.id.systemVolume);
sysVol.setOnKeyListener(new OnKeyListener()
{
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
//system volume
int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int i = curVolume * 4;
String aString = Integer.toString(i);
TextView sysVol = (TextView)findViewById(R.id.systemVolume);
sysVol.setText(aString);
return true;
}
return false;
}
});
Well, the pseudo approach would be the following scenario:
1) Attach a listener to the view
2) Filter the different events in the callback
3) Update the TextView upon the (event==volume_up OR event==volume_down)
Basically, you'd want to implement the View.onKey()-method for this to be a minor bump in the road, instead of the current roadblock-state.
Summary: Add the following snippet to your code (some modification needed)
public YourClassHere extends SomethingCool implements OnKeyListener /*<-- important part*/
{
public boolean onKey(View v) {
// do something when the selected button is pushed
return true;
}
}
I think the problem is that the textview is not refreshing after you have changed the text. Try putting sysVol.requestLayout() after you changed the text to refresh the textview. Also, I don't think you are suppose to put return false after the closing bracket of the onKey() method.

Categories