When I am writing something in EdiText and pressing the back button, it is hiding the keyboard, which is perfect. But I want to handle this Back Button Click when Keyboard is open for EditText. The reason is I want to clear EditText's text when the back button is pressed when the keyboard is open.
Activity method onBackPressed() is not called when keyboard is open for EditText.
I checked here but didn't help though.
Any help would be appreciated.
You can use custom edittext and implement onKeyPreIme to listen backPressed
public class MyEditText extends androidx.appcompat.widget.AppCompatEditText {
private MyEditTextListener listener;
public interface MyEditTextListener {
void callback();
}
public void setListener(MyEditTextListener listener) {
this.listener = listener;
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
listener.callback();
return true;
}
}
activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyEditText myEditText = findViewById(R.id.myEditText);
myEditText.setListener(new MyEditText.MyEditTextListener() {
#Override
public void callback() {
//handle backPressed event when keyboard have shown
}
});
}
I did few modifications to #GuanHongHuang's answer and now I am able to do this by these 3 steps:
1. Creating Custom EditText Class to handle Back Press:
public class CustomEditTextWithBackPressEvent extends androidx.appcompat.widget.AppCompatEditText {
private MyEditTextListener onBackPressListener;
public CustomEditTextWithBackPressEvent(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnBackPressListener(MyEditTextListener onBackPressListener) {
this.onBackPressListener = onBackPressListener;
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK &&
event.getAction() == KeyEvent.ACTION_UP) {
//back button pressed
if (Objects.requireNonNull(ViewCompat.getRootWindowInsets(getRootView())).isVisible(WindowInsetsCompat.Type.ime())) {
//keyboard is open
onBackPressListener.callback();
}
return false;
}
return super.dispatchKeyEvent(event);
}
public interface MyEditTextListener {
void callback();
}
}
2. Replace your normal EditText with this CustomEditTextWithBackPressEvent in XML
<CustomEditTextWithBackPressEvent
android:id="#+id/etSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1" />
3. Handle Back Press:
binding.etSearch.setOnBackPressListener(() -> {
//handle click
//your code here
});
Related
I'm working on a kotlin app, My activity is in fullscreen and I want to make a button in which the screen can't be exit or back or anything unless the button is clicked. Like the one in the video player lock type.
My first idea was to make boolean isLocked and after clicking button change this value to the opposite and override all functions/events etc which You would like to lock and if isLocked is true just don't execute them.
Here is a simple code where I locked back button (in java but it can be easily changed to Kotlin)
public class MainActivity extends AppCompatActivity
{
boolean isLocked = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
isLocked ^= true;
System.out.println(isLocked);
}
});
}
#Override
public void onBackPressed()
{
if (!isLocked)
{
super.onBackPressed();
}
}
}
I think that in a similar way You can lock every event.
You can also make something like this:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (!isLocked)
{
return super.onKeyDown(keyCode, event);
}
else
{
return true;
}
}
This will cancel every event like clicking back button or changing volume
In my activity, the soft keyboard should more or less always be open. So when a user presses the back button, the activity should finish like normally. However, the default Android behavior is to close the keyboard instead when it is open. This makes the user have to click twice to exit the activity. How can I override this behavior so that the activity always finishes when the back button is pressed, even when the soft keyboard is open? Is there some simple way to do this?
I'm sure this is a common problem, but I did not find this direct question.
I have same situation.I tried so many ways finally i got solution. Here i will share with you. I have solved this using CustomEditText.
CustomEditText.Java
public class CustomEditText extends android.support.v7.widget.AppCompatEditText {
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
OnKeyPreImeListener onKeyPreImeListener;
public void setOnKeyPreImeListener(OnKeyPreImeListener onKeyPreImeListener) {
this.onKeyPreImeListener = onKeyPreImeListener;
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
if(onKeyPreImeListener != null)
onKeyPreImeListener.onBackPressed();
return false;
}
return super.dispatchKeyEvent(event);
}
public interface OnKeyPreImeListener {
void onBackPressed();
}
}
MainActivity.Java
public class MainActivity extends BaseActivity{
private CustomEditText editSearchMenu;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editSearchMenu =
(CustomEditText)findViewById(R.id.editSearchMenu);
//Initialise interface
CustomEditText.OnKeyPreImeListener onKeyPreImeListener=new CustomEditText.OnKeyPreImeListener() {
#Override
public void onBackPressed() {
((MainActivity)getActivity()).finish();
}
};
editSearchMenu.setOnKeyPreImeListener(onKeyPreImeListener);
}
}
xml file
<com.app.helper.CustomEditText
android:id="#+id/editSearchMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/diam5dp"
android:background="#drawable/custom_rounded_edittext"
android:drawableLeft="#drawable/ico_search"
android:drawablePadding="#dimen/diam20dp"
android:drawableStart="#drawable/ico_search"
android:hint="#string/M_SEARCH_HINT"
android:padding="#dimen/diam10dp"
android:textColor="#android:color/white"
android:textColorHint="#android:color/white"
android:textSize="#dimen/diam16sp" />
Hope this will help you...this works in every devices i have tested my self...other solutions are creating problems in some devices..there will be some other solution also...if you get something let me know...
You should implement TextWatcher.
Here is the the code of you requirement.
public class MainActivity extends AppCompatActivity implements TextWatcher{
EditText editTextt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextt = (EditText) findViewById(R.id.editTextt);
editTextt.addTextChangedListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(before == count + 1)
{
finish();
}
}
}
I use this method to hide the keyboard
//hides keyoard
private void hideSoftKeyboard(View v) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
Try this.
mEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
finish();
return false;
}
});
You can hide Keyboard and finish Activity.
If you use Dialog,you can do like this.
mDialog.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (isShowDialog) {
isShowDialog = false;
mDialog.dismiss();
context.finish();
}
}
return false;
}
});
Note: It also can use in Dialog.Dismiss Dialog and do something.And you can use v、 keyCode、 event.And it can be used by most View.
I am starting my softkeyboard in my ActivityB with this lines in my manifest
<activity android:name=".ActivityB"
android:label="#string/title_activity_activity_b"
android:windowSoftInputMode="stateAlwaysVisible" >
</activity>
Now I would like that when I press a back button I exit(finish) the activity immediately. I would like to press back button only once to exit the activity.
Right now I have to first press back button once to lower the soft-keyboard and press the back button again for the second time to exit activity.
Is this possible and how can I do that? I tried various common techniques from this site but none of them worked. I use LG L50 for development.
EDIT: I am extending activity and not appcompatactivity
EDIT 2: The program works now, here is the code
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}}
MyEditText.java
package com.example.actionbarimagetest;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
public class MyEditText extends EditText implements OnClickListener {
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void FlashBorder()
{
//do some custom action
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
EditText txt = (EditText) v;
txt.selectAll();
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
System.out.println("KEYCODE BACK");
((Activity)getContext()).finish();
return true;
}
return super.onKeyPreIme(keyCode, event);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<com.example.actionbarimagetest.MyEditText
android:id="#+id/edtTaskName"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
</LinearLayout>
Just override activity method and finish explicitly
#Override
public void onBackPressed() {
finish();
}
UPDATED2
Yes, this doesn't work for such case. But I've tried few solutions and one of them did work. You need to extend EditText and override method:
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
((Activity)getContext()).finish();
return true;
}
return super.onKeyPreIme(keyCode, event);
}
Note:
don't forget to replace your previous EditText in layout xml with new extented class
call the following function on your backbutton wherever and whatever:
yourMethod()
{
// close keyboard
InputMethodManager mgr = (InputMethodManager) TempActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(searchBox.getWindowToken(), 0);
//close activity
YourActivity.finish();
}
for backpressed of android device do as:
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
yourMethod();
YourActivity.finish();
}
Activity.onBackPressed() won't work, because it's being called after (and if) nothing else handled the back button (which IME does).
Override Activity.dispatchKeyEvent() instead:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.dispatchKeyEvent(event);
}
I created an activity which should have the keypad always popped up. So, I used requestFocus() for the edittext. But I don't want only keypad disappear. Instead I want the whole activity to finish() when back button is pressed even when keypad is present. I tried this answer, but it didn't work. I tried this too though it looked a bit extra work, but this isn't working with textwatcher. Below is the edittext. I kept it's dimension attributes to 0dp because to avoid showing user even the password field. Any help on achieving this is appreciated. Please let me know if any further information is needed.
<EditText
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/passwordet"
android:inputType="number"
/>
P.S: Overriding onBackPressed() doesn't work because it doesn't get fired when keypad is present on Activity.
You can override the onBackPressed method to finish the activity:
#Override
public void onBackPressed() {
finish();
}
Extend EditText and add following method.
public class MyEditText extends EditText {
OnKeyListener onKeyListener = null;
public static int BACK_KEY = 10001;
public void setOnKeyListener(OnKeyListener l) {
super.setOnKeyListener(l);
onKeyListener = l;
Log.i(TAG, "setOnKeyListener Called");
}
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
Log.i(TAG, "onKeyPreIme");
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_UP) {
if (onKeyListener != null) {
onKeyListener.onKey(this, BACK_KEY, event);
}
return false;
}
return super.dispatchKeyEvent(event);
}
}
And from activity
editText.setOnKeyListener(this);
and handle on onKey method
You need to create a custom EditText in order to capture keyBoardDismissEvent.
You can try something like this:
public class CustomEditText extends EditText {
private OnKeyboardDismissListener listener;
public void setOnKeyBoardDismissListener(OnKeyboardDismissListener listener) {
this.listener = listener;
}
public CustomEditText(Context context) {
super(context);
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && listener != null)
listener.onKeyBoardDismiss();
return super.onKeyPreIme(keyCode, event);
}
static interface OnKeyboardDismissListener {
void onKeyBoardDismiss();
}
}
In layout
<YourPackageName.CustomEditText android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Inside Activity:
CustomEditText editText = (CustomEditText) findViewById(R.id.editText);
editText.setOnKeyBoardDismissListener(new OnKeyboardDismissListener() {
#Override
public void onKeyBoardDismiss() {
MainActivity.this.finish();
}
});
The application is a step sequencer application with 16 radio groups with 8 buttons in each group. It works perfectly except once a group has a button selected I cant turn it off unless I use the clear button I have created to clear all radiogroups. What I would like to add is some code that says when a selected radio button is selected again it simply turns off like a toggle. I tried using toggles but then other issues arose with that method. Below are two attempts but both simply stops me using the button
final RadioGroup radioGroup1 = (RadioGroup) findViewById(R.id.RadioGroup1);
RadioButton D1 = (RadioButton) findViewById(R.id.RadioButtonD1);
Button D1 = (Button) findViewById(R.id.RadioButtonD1);
D1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View v){
PdBase.sendFloat("D1", 74);
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton D1 = (RadioButton) findViewById(selectedTypeId);
if (D1 != null) // This will be null if none of the radio buttons are selected
radioGroup1.clearCheck();
PdBase.sendFloat("D1", 0);
}
});
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
lC1.setOnClickListener(new View.OnClickListener() {
public void onClick (View v) {
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
if (selectedTypeId == -1) {
PdBase.sendFloat("lC1", 72);
}
else if (selectedTypeId == R.id.RadioButtonlowC1) {
radioGroup1.clearCheck();
PdBase.sendFloat("lC1", 0);
}
}
});
I recently had the same need - to have a radio group where the selected item could be deselected by tapping it again. I found that I couldn't accomplish that using listeners but I was able to do it using a custom RadioButton, like so...
public class ToggleableRadioButton extends RadioButton {
// Implement necessary constructors
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
Notice that the button is toggled in different ways depending on its current state - i.e., calling setChecked(true) on the button vs. calling clearCheck() on the group. If setChecked() is used in both cases, a button that was just deselected cannot be immediately re-selected - the logic in RadioGroup seems to immediately deselect it.
To use this button, just replace your <RadioButton> tags with <your.package.ToggleableRadioButton> in your layout XML.
I just used the answer from #spaaarky21
and my full code look like this and it is working fine!
Java Class
public class ToggleableRadioButton extends RadioButton {
public ToggleableRadioButton(Context context) {
super(context);
}
public ToggleableRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
And for the XML layout
<com.smart_dent.adapters.ToggleableRadioButton android:id="#+id/tejido_blando_perfil_convexo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tejido_blando_convexo_label" />
In this case you just need to change the package, I this is easy to find, it is just at the top of the Java Class Flie (if you created it from Android Studio)
It actually can be done with listeners but with an OnTouchListener, which will trigger before the button's state has changed, instead of the usual OnClickListener. The following works for me:
View.OnTouchListener radioButtonOnTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (((RadioButton) v).isChecked()) {
// If the button was already checked, uncheck them all
radioGroup.clearCheck();
// Prevent the system from re-checking it
return true;
}
return false;
}
};
radioButton1.setOnTouchListener(radioButtonOnTouchListener);
radioButton2.setOnTouchListener(radioButtonOnTouchListener);
Where radioGroup is the parent of radioButton1 and radioButton2
Edit from #spaaarky21 answer
#Override
public void toggle() {
if (isChecked()) {
if (getParent() instanceof RadioGroup) {
((RadioGroup) getParent()).clearCheck();
}
// add else here when a single radioButton without radioGroup
else {
setChecked(false);
}
} else {
setChecked(true);
}
}
This is also doing the job:
public final class ToggleAbleRadioButton extends AppCompatRadioButton {
public ToggleAbleRadioButton(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
#Override public void toggle() {
setChecked(!isChecked());
}
}
You can use a boolean to toggle the button on and off.
Add a boolean somewhere in your code:
var radioButton1IsSelected = false
Then setup the onClickListener for the button:
radioButton1.setOnClickListener {
radioButton1IsSelected = !radioButton1IsSelected
radioButton1.isChecked = radioButton1IsSelected
}