Is there any way I can force show Android's SoftKeyboard in NumberPassword mode without having an actual EditText in my activity?
I managed to show the keyboard when the activity starts by adding android:windowSoftInputMode="stateAlwaysVisible" on my AndroidManifest.xml, make it impossible to close by overriding onKeyPreIme in my CustomView class that extends TextView, and handling the touch events by myself by overriding onKeyUp in my Activity.
If I add android:inputType="numberPassword" directly in CustomView's XML Layout, Activity's onKeyUp gets bypassed and the keyboard write characters in my CustomView and KEYCODE_ENTER closes my keyboard.
What I want to achieve is:
SoftKeyboard always out, both on Activity Start and Resume from the background
Cannot be closed with KEYCODE_ENTER or KEYCODE_BACK
9-digit layout + Backspace
Handle by myself key pressure to make it do something else instead of writing characters
Taken from https://developer.android.com/training/keyboard-input/commands.html for convenience:
Both the Activity and View class implement the KeyEvent.Callback
interface, so you should generally override the callback methods in
your extension of these classes as appropriate.
I suggest you to override the default implementation of onKeyUp in your CustomView class, and make the CustomView.onKeyUp method redirect the event to your Activity's onKeyUp method.
As an example:
public class CustomView extends TextView {
private KeyEvent.Callback myKeyEventCallback;
public void setCustomKeyEventCallback(KeyEvent.Callback callback) {
myKeyEventCallback = callback;
}
...
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return myKeyEventCallback.onKeyUp(keyCode, event);
}
}
And in your Activity do this:
CustomView view = ...; // here you take the reference to your custom view
view.setCustomKeyEventCallback(new KeyEvent.Callback() {
// ... other methods
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// this calls your activity's implementation of onKeyUp
MyActivity.this.onKeyUp(keyCode, event);
return false; // prevent event from firing twice
}
});
This will help you redirect the onKeyUp method calls from your CustomView to your Activity's onKeyUp implementation.
Related
When I try to add onTouchListner() to a button, it gets me the
Button has setOnTouchListener called on it but does not override
performClick
warning. Does anyone know how to fix it?
btnleftclick.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
Error:
Custom view has setOnTouchListener called on it but does not override
performClick If a View that overrides onTouchEvent or uses an
OnTouchListener does not also implement performClick and call it when
clicks are detected, the View may not handle accessibility actions
properly. Logic handling the click actions should ideally be placed in
View#performClick as some accessibility services invoke performClick
when a click action should occur.
This warning comes up because Android wants to remind you to think about the blind or visually impaired people who may be using your app. I suggest you watch this video for a quick overview about what that is like.
The standard UI views (like Button, TextView, etc.) are all set up to provide blind users with appropriate feedback through Accessibility services. When you try to handle touch events yourself, you are in danger of forgetting to provide that feedback. This is what the warning is for.
Option 1: Create a custom view
Handling touch events is normally something that is done in a custom view. Don't dismiss this option too quickly. It's not really that difficult. Here is a full example of a TextView that is overridden to handle touch events:
public class CustomTextView extends AppCompatTextView {
public CustomTextView(Context context) {
super(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
performClick();
return true;
}
return false;
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
#Override
public boolean performClick() {
super.performClick();
doSomething();
return true;
}
private void doSomething() {
Toast.makeText(getContext(), "did something", Toast.LENGTH_SHORT).show();
}
}
Then you would just use it like this:
<com.example.myapp.CustomTextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="Click me to do something"/>
See my other answer for more details about making a custom view.
Option 2: Silencing the warning
Other times it might be better to just silence the warning. For example, I'm not sure what it is you want to do with a Button that you need touch events for. If you were to make a custom button and called performClick() in onTouchEvent like I did above for the custom TextView, then it would get called twice every time because Button already calls performClick().
Here are a couple reasons you might want to just silence the warning:
The work you are performing with your touch event is only visual. It doesn't affect the actual working of your app.
You are cold-hearted and don't care about making the world a better place for blind people.
You are too lazy to copy and paste the code I gave you in Option 1 above.
Add the following line to the beginning of the method to suppress the warning:
#SuppressLint("ClickableViewAccessibility")
For example:
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button myButton = findViewById(R.id.my_button);
myButton.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return false;
}
});
}
Solution:
Create a class that extends Button or whatever view you are using and override performClick()
class TouchableButton extends Button {
#Override
public boolean performClick() {
// do what you want
return true;
}
}
Now use this TouchableButton in xml and/or code and the warning will be gone!
Have you tried adding :
view.performClick()
or adding suppresslint annotation :
#SuppressLint("ClickableViewAccessibility")
?
Custom view controls may require non-standard touch event behavior.
For example, a custom control may use the onTouchEvent(MotionEvent)
listener method to detect the ACTION_DOWN and ACTION_UP events and
trigger a special click event. In order to maintain compatibility with
accessibility services, the code that handles this custom click event
must do the following:
Generate an appropriate AccessibilityEvent for the interpreted click
action. Enable accessibility services to perform the custom click
action for users who are not able to use a touch screen. To handle
these requirements in an efficient way, your code should override the
performClick() method, which must call the super implementation of
this method and then execute whatever actions are required by the
click event. When the custom click action is detected, that code
should then call your performClick() method.
https://developer.android.com/guide/topics/ui/accessibility/custom-views#custom-touch-events
At the point in the overridden OnTouchListener, where you interprete the MotionEvent as a click, call view.performClick(); (this will call onClick()).
It is to give the user feedback, e.g. in the form of a click sound.
you can suppress a warning
#SuppressLint("ClickableViewAccessibility")
or call performClick()
[Example]
I have an extended view from SurfaceView like this:
public class MyView extends SurfaceView implements View.OnClickListener {
public MyView(Context context)
{
super(context);
mContext = context;
setOnClickListener(this);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case DOWN OR UP OR MOVE: <-- I do something here like move and drag and drop and
// any related behavior to MyView
}
invalidate();
return true;
}
Now I implemented OnClickListener and set it in my constructor.
OnClick method:
#Override
public void onClick(View v){
Log.e("as", "clicked");
}
But onClick method never not called. How can I solved that?
When replaced return true; with return super.onTouchEvent(event); my onClick method called, but when I want to move my custom view, onClick method again called and this is not my porpuse.
I want only when I tapped my custom view, onClick called, and when moved it not called.
Thanks In advance.
The problem is probably your onTouch Listener. You are overriding and not dealing with the onClick possibility. Additionally you are consuming the event with a return true so the onClick will never be called.
Remember that onClick is dealt in onTouchEvent implemented in the original view class.
You can check more info at:
http://developer.android.com/reference/android/view/View.html#onTouchEvent(android.view.MotionEvent)
where you can read:
public boolean onTouchEvent (MotionEvent event)
Added in API level 1 Implement this method to handle touch screen
motion events.
If this method is used to detect click actions, it is recommended that
the actions be performed by implementing and calling performClick().
This will ensure consistent system behavior, including:
obeying click sound preferences dispatching OnClickListener calls
handling ACTION_CLICK when accessibility features are enabled
Parameters event The motion event.
Returns True if the event was
handled, false otherwise.
Since you want to choose when click is performed, you should implement the performClick (like it states in the link I have referenced).
I wanted to add a neat functionality to my Dialog. When the user presses DONE button on the keyboard after editing one of EditTexts inside the dialog, it would simulate onPositiveClick of the dialog so that the data inside the EditTexts gets handled properly and the dialog is dismissed. This is much better than first entering the data and then pressing the dialogs OK button. My dialog extends DialogFragment and implements OnEditorActionListener and this is my listener method:
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((actionId & EditorInfo.IME_MASK_ACTION) == EditorInfo.IME_ACTION_DONE)//check if done was pressed
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
return false;
}
But the problem is that this method is never called when i press DONE on my keyboard. Do you know what causes that?
I have a layout in my activity with some UI elements in it. I want to handle long press for the whole activity.Also I need to handle click events for all the UI events seperately. How can I do it? Pls help.
your class can use the interface onLongClickListener
like yourclass extends Activity implements View.OnLongClickListener which has the method that get notified on long press.
Note: Don't forget to set yourView.setOnLongClickListener(this); for all the views you need
Rename your layout just the biggest of(linear layout, relative layout or...) in xml file and use this coDe
Layout ly=(Layout) findVewById(R.id.yourlayout);
ly.setOnLongClickListener (new. Onlongclicklistener(){
#Override
public boolean onTouchEvent(MotionEvent event) {
//do something
}
}
Example of code an Activity subclass can use to implement special actions for a long press
CALL key:
#Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_CALL) {
// a long press of the call key.
// do our work, returning true to consume it. by
// returning true, the framework knows an action has
// been performed on the long press, so will set the
// canceled flag for the following up event.
return true;
}
return super.onKeyLongPress(keyCode, event);
}
Check http://android-developers.blogspot.in/2009_12_01_archive.html
I want to detect Back Key event in my CustomView (e.g., EditText). In many case, it has been achieved by overriding the onKeyDown() or dispatchKeyEvent(), under the condition that my CustomView obtains focus.
CustomView.java
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if( keyCode == KeyEvent.KEYCODE_BACK) {
.....
return true;
}else{
return super.onKeyDown(keyCode, event);
}
}
However, if an Activity including the CustomView is also overriding the onKeyDown() or dispatchKeyEvent(), it couldn't work much. That is, the Activity has obtained the Back-KeyEvent before the CustomView has.
I preferentially want to catch the Back-KeyEvent before Activity does.
please tell me some ideas about this problem.
Thank you.
You need to implement this to capture the BACK button before it is dispatched to the IME:
http://developer.android.com/reference/android/view/View.html#onKeyPreIme(int,android.view.KeyEvent)
Override onKeyDown in your Activity and return false. So that the event gets propagated to other views as well.
If you handled the event, return true. If you want to allow the event
to be handled by the next receiver, return false.
You can try to use
setFocusableInTouchMode(true)
setFocusable(true)
requestFocus()
on your customview