I have 5 EditTexts and I type in them using 5 buttons, so I don't need the keyboard.
How can I disable it completely, even when I click on the EditText? On EditText click I want only to focus it so that it has the cursor on. (I implemented everything so that when I click one of the 5 buttons, the focus goes on the next EditText).
The problem is that when I click on an EditText the keyboard pops up. I think I have to do it in java. Thank you!!!
MyEditor.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
int inType = MyEditor.getInputType(); // backup the input type
MyEditor.setInputType(InputType.TYPE_NULL); // disable soft input
MyEditor.onTouchEvent(event); // call native handler
MyEditor.setInputType(inType); // restore input type
return true; // consume touch event
}
});
Try :
editText.setShowSoftInputOnFocus(false);
editText.setInputType(InputType.TYPE_NULL);
editText.setFocusable(false);
Related
I wish to create a simple game for Android, where the player will be shown a table of buttons. He should have the ability to swipe/drag his fingers over some buttons, and the result of his move should only be displayed after he stops touching the screen.
I can see when Action_UP and Action_Down is called, but I can't use Action_HOVER_MOVE:
View.OnTouchListener OTL = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction()==MotionEvent.ACTION_DOWN
|| motionEvent.getAction()==MotionEvent.ACTION_HOVER_MOVE)
{
Button B = (Button)view;
if (B.isActivated())
{
String letter = B.getText()+"";
word+=letter;
}
B.setActivated(false);
Toast t = Toast.makeText(MainActivity.this,word,Toast.LENGTH_SHORT);
t.show();
}
if (motionEvent.getAction()==MotionEvent.ACTION_UP)
{
Toast t = Toast.makeText(MainActivity.this,word,Toast.LENGTH_SHORT);
t.show();
word="";
resetButtons();
}
return true;
}
};
How to detect swipe over other buttons?
Per the docs, you probably want ACTION_MOVE
int ACTION_MOVE
Constant for getActionMasked(): A change has happened during a press gesture (between ACTION_DOWN and ACTION_UP). The motion contains the most recent point, as well as any intermediate points since the last down or move event.
You're having trouble with ACTION_HOVER_MOVE because:
int ACTION_HOVER_MOVE
Constant for getActionMasked(): A change happened but the pointer is not down (unlike ACTION_MOVE). The motion contains the most recent point, as well as any intermediate points since the last hover move event.
This action is always delivered to the window or view under the pointer.
This action is not a touch event so it is delivered to onGenericMotionEvent(MotionEvent) rather than onTouchEvent(MotionEvent).
Source: https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_MOVE
I know this question has been asked in many different ways before, but even though I have looked at many other related questions about EditText focus, I have not found my solution.
Here is what I want to achieve:
When the user is done Editing an EditText I want it to loose focus.
When the user hits outside the EditText I want such EditText to lose
focus.
Whenever the soft-keyboard hides or is hidden I want EditText
to lose focus.
Whenever the User hits ENTER or BACK ARROW in the soft-keyboard, the EditText focus should be cleared
This is what I currently have:
I have two EditText in an activity, which I will call EditText_1 and EditText_2 for simplicity so that we know which EditText I am talking about.
When the user starts the activity, the EditText_1 would have no focus, a blinking cursor and the soft-keyboard would be hidden. I have already fixed that problem using;
android:focusableInTouchMode="true"
and
android:focusable="true"
After the previous fix in part1, when I start the activity and click on any EditText, it will gain focus, however, when I am done editing such clicked EditText and the soft-keyboard hides, the EditText will not lose focus and the cursor will still be blinking.
Another example happens when I am editing an EditText and click any other button outside the editText, it will not force EditText to lose focus or hide the keyboard.
The current solution I have is
public void onFocusChange(View v, boolean hasFocus){...}
so that, it will call some method such as force the EditText to lose focus:
EditText.clearFocus();
and do not show that annoying blinking cursor once I know EditText loses its focus:
EditText.setCursorVisible(false);
However, because hitting Done or outside EditText do not force it to lose focus, onFocusChange will not be called all the times(as in the examples provided).
Some of the solutions I cannot accept are:
Set the cursor visibility to false in the XML activity file and never and anywhere change it back to true.
setCursorVisible(false);
I want the cursor to be seen when needed and to be hidden when it is not needed.
Have a button that needs to be clicked by the user so that inside such button all methods needed will be called. I mean, it is not user-friendly at all. Users do not want to be forced to click a button just to hide all focus, blinking cursors...
Here comes the part many of you will tell me, every single of these issues have been solved in different questions. HOWEVER, I have not been able to implement multiple solutions which will do all points previously stated.
To make editText lose focus when you press outside of the keyboard you can try to setOnTouchListener to the view that is visible when the keyboard is shown. For example, it might be the parent layout, listView, recyclerView or any other significant in size view. In order to do that, just add code below inside of your onCreate method in activity:
findViewById(R.id.loginLayout).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
usernameEditText.clearFocus();
passwordEditText.clearFocus();
return false;
}
});
To make editText lose focus and/or hide keyboard when pressing some button on keyboard you can use the following code. There is an example of listener for Enter key. You may find all the other keys on official documentation.
yourEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
if (event.getAction() == KeyEvent.ACTION_UP) {
yourEditText.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
return false;
}
});
This Solution works For SOFTKEYS, some code is from here
The final solution to hide keyboard and clear focus from the EditText would be;
yourEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
name.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Log.d(TAG, "actionID: " + actionId +" KeyEvent: " + event);
}
return false;
}
});
I have an ImageView overlay inside of a RelativeLayout and want to prevent any clicks from going through the ImageView to the Buttons etc that are behind it (thus in effect disabling the entire RelativeLayout).
Is the a simpler way of doing this then iterating the RelativeLayout views and setting them to disabled as I currently am doing using this code:
RelativeLayout rlTest = (RelativeLayout ) findViewById(R.id.rlTest);
for (int i = 0; i < rlTest.getChildCount(); i++) {
View view = rlTest.getChildAt(i);
view.setEnabled(true);
}
you can set the image to be
android:clickable="true"
Simply call rlTest.setClickable(false). This will prevent the click to be propagate to the children
There is a much cleaner way
You can use:
android:onClick="preventClicks"
in XML and in your Activity
public void preventClicks(View view) {}
This works with fragments.
Example inside this Activity has multiple fragments overlapping one another, just by adding the XML attribute in the background of your fragment it will still call the Activity.preventClicks and will prevent touches on fragments behind it
The following solution works in the general case:
_container.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// NOTE: This prevents the touches from propagating through the view and incorrectly invoking the button behind it
return true;
}
});
It basically blocks any touches from propagating through the view by marking the touch event as handled.
This works on both UI controls and layout containers (ie: LinearLayout, FrameLayout etc.).
The solution to set "clickable" as false did not work for me for layout containers either in code or in the view XML.
I assume that you are using onClickListeners.
How about using onTouchListener instead of onClickListeners. By doing this you will have a control over how deep down in your hierarchy the touch even can be visible. For example, if you have toch listeners on a relative-layout(RL) and a image-view(IV)(contained in RL), and you assign touchListeners to both. Now if you return true from IV's touch event, the lower down member RL will not receive the touch event. However if you return false from from IV's touch event, the lower down member RL will receive the touch event.
Hope this helps!
Just add these two listeners:
// Set an OnTouchListener to always return true for onTouch events so that a touch
// sequence cannot pass through the item to the item below.
view.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.onTouchEvent(event);
return true;
}
});
// Set an OnHoverListener to always return true for onHover events so that focus cannot
// pass through the item to the item below.
view.setOnHoverListener(new OnHoverListener() {
#Override
public boolean onHover(View v, MotionEvent event) {
v.onHoverEvent(event);
return true;
}
});
You could use databindings and consume the clicks like this:
android:onClick="#{() -> true}"
In C#, I use an empty delegate:
objectName.Click += delegate {};
I haven't encountered any problems with it but it does prevent clicks from filtering through to underlying controls.
you can also se the root click listener to null:
// Do not process clicks on other areas of this fragment
binding.root.setOnClickListener(null)
This works 100%.
It doesnt affect other listeners that are already set on the fragment's views.
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.
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);
}
}