EditText onFocus doesn't work properly - java

I have an EditText which I adjust the position on screen of when the user clicks it (when it gains focus). However, the method is not working properly. My code:
etHashtag.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
Log.d("EditText", "has focus");
originalHashtagPos = etHashtag.getY();
etHashtag.setY(targetH / 2);
}else {
Log.d("EditText", "no focus");
etHashtag.setY(originalHashtagPos);
}
}
});
The log shows that the focus is gained when the user clicks the EditText, and it loses focus when the user clicks outside the view. However, the Y position is not moved everytime. It only works in about 50% of the times. Thought this would be simple?

Related

How to disable a button for the user, until editText is active?

I want to make it impossible for the user to click on a button until he does not 'get out of' or clicks away from an EditText.
Like, the button will be there, but when the user goes to enter text in an EditText, it will be grayed out, and will be clickable again only when the user leaves the editText.
I hope my question is clear. How can I do this?
Your button behaviour depends on the focus of the editext so you can use
mEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
mButton.setEnabled(false)
} else {
mButton.setEnabled(true)
}
}
});
the if is extended, consider that you can solve in just one line
mButton.setEnabled(!hasFocus)
Set OnFocusChangeListener on your EditText:
editView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
button.setEnabled(!hasFocus);
}
});
Use setOnFocusChangeListener and override the onFocusChange. Then, use the button.setEnabled

After click on editText is done when going to another edittext

I'm having a question where I couldn't find the answer online or know how to find it..
I have EditText xml attribute and I made an event listener
to this attribute by changing the color of an underline beneath it. Is there a way when the focus is removed from this EditText (i.e user click on any other element rather than this one) to remove the highlighted color for the line I colored?
On the onclick event listener? It seems weird, but I want the opposite of the onclick like onclickremove or something.
You can use the the setOnFocusChangeListener to your EditText. If lost focus,clear the color filter:
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editText.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
else{
editText.getBackground().clearColorFilter();
}
}
});
If you want to change your view color, just add the below line in onFocusChange:
view.setBackgroundColor(Color.parseColor("#ffffff"));
Hope this helps.
You need to use setOnFocusChangedListener for this. The hasFocus determines whether the focus is removed or given to a view. It being false indicates that user has left the field.
EditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus == false){
// change the color
}
}
});

Force EditText to lose focus when: some keyboard keys are pressed and when user clicks on something else in the activity

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;
}
});

Why doesn't DialogFragment.dismiss kill the dialog right away?

I am building a very basic vocabulary application. The feature I am trying to implement right now is a go to feature, that is taking the user to a specific vocab term. i am doing this by prompting the user with a dialog fragment that asks the user for a page number. (dialog fragment will get triggered via a callback, button press)
This is my code for doing so
public class GoToDialog extends DialogFragment{
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String pgn = pageNumber.getText().toString();
if(!isNumeric(pgn) || pgn.isEmpty()) {
Toast.makeText(getActivity(), "Please enter a valid number", Toast.LENGTH_SHORT).show();
} else {
int pagina = Integer.parseInt(pgn);
if(pagina <= 0 || pagina > total) {
Toast.makeText(getActivity(), String.format("Please enter a valid " +
"term number between 0 and %d", total), Toast.LENGTH_SHORT).show();
} else {
getDialog().dismiss();
getFragmentManager().executePendingTransactions();
communicator.onDialogMessage(pagina);
}
}
}
});
Here are screenshots when I run my application
Screenshot2(right after screenshot 1)
In terms of functionality The dialog loads up fine and is able to take the user to the right location. However in that example of taking the user from term 7 to term 5, the user is taken to the
right term but the dialog doesn't close as it should from getDialog().dismiss(). I know dismiss is being called because I walked through the code and communicator.onDialogMessage(pagina) returns the right term number to the activity. The dialog does close when I select another term number to go to. Does anyone see the issue? This doesn't make sense to me at all.
To close a dialog, dismiss is the correct method to use
- How to correctly dismiss a DialogFragment?
I also tried what a user suggested in Correct way to remove a DialogFragment: dismiss() or transaction.remove()?, which is to call executePendingTransactions().
If anyone's having a similar issue, the issue with my application was my OnTouchListener.
When I set up on OnTouchListener to trigger the DialogFragment, here was my original code for doing so
goTo - TextView
private void setUpGoToTouchListener() {
goTo.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
FragmentManager fm = MainActivity.this.getFragmentManager();
GoToDialog dialog = new GoToDialog();
Bundle bundle = new Bundle();
bundle.putInt("Size", defMan.getTotalCount());
dialog.setArguments(bundle);
dialog.show(fm, "Manager");
return true;
}
});
}
When the gesture(a touch) on the TextView occurs, two MotionEvents will be generated, the press, ACTION_DOWN - first finger has touched the screen, and the release, ACTION_UP - the last of the fingers has stopped touching the screen. Because two motion events occurred, two dialog fragments were created. Thats why dismiss had to be called twice in my situation to get rid of both dialog fragments. I fixed this by having a conditional test for event.getAction()

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);
}
}

Categories