All the Android experts,
I'm working on Android TV app.
I face problem on Dpad navigation.
i would like to stop auto Dpad navigate while KeyDown UP and DOWN.
i wrote a listener on a focusable TextView, if TextView on key UP then scroll UP the listview, and key DOWN scroll DOWN.
but the below code seen failed to scroll my listview, my focus move to other focus point while i press DOWN.
Is there any solution that i can override the auto focus navigation? i would like my TextView ignore the auto navigation to next focus while i press key UP and DOWN.
Thank you.
textView.setOnKeyListener(new View.OnKeyListener(){
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_PAGE_UP:
listview_scrollUP();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_PAGE_DOWN:
listview_scrollDOWN();
break;
}
}
return false;
}
});
After some research, i got some idea to solve my problem.
i used setDescendantFocusability() block the rest of my fragments(viewgroup) while my dpad focus enter the targeted fragment, ideally is to space out the key UP and DOWN for my purpose usage (without processing dpad navigate next focus).
textview.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
LinearLayout menu = (LinearLayout)getActivity().findViewById(R.id.mainMenuLayout);
menu.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
}
}
});
my targeted fragment just needed LEFT and RIGHT to let dpad change to next focus, and then my UP and DOWN onKey Down is used for scrolling the listview.
setDescendantFocusability() enable while the dpad navigate focus reached the edge of my fragment focusing point.
textview.setOnKeyListener(new View.OnKeyListener(){
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch(keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
LinearLayout menu = (LinearLayout)getActivity().findViewById(R.id.mainMenuLayout);
menu.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
menuItem1.requestFocus();
break;
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_PAGE_UP:
listview_scrollUP();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_PAGE_DOWN:
listview_scrollDOWN();
break;
}
}
return false;
}
});
this is what i came out of to solve my problem.
wish this info help up other.
thank you.
Related
I have to intercept the touch on the screen, and this is my code:
mWebView = findViewById(R.id.webview);
mWebView.setWebViewClient(new WebViewClient());
mWebView.loadUrl(URL);
mWebView.setOnTouchListener(this);
mWebView.setOnKeyListener(this);
and my listeners:
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Log.i(TAG, "Hello, touch.");
onTouchEvent();
return false;
}
return false;
}
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent)
{
Log.i(TAG, "Hello, onKey.");
onTouchEvent();
return false;
}
While the on touch is working fine for touches on the screen, it dosen't intercept the touch event on the keyboard. For this reason, I've added the onkeylistener, but it's not intercepting the key events. As last thing, I don't care about what is typed, but just if the screen has been touched.
why not trying onkeyDown?
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_DOWN){
switch(keyCode)
{
case KeyEvent.KEYCODE_BACK:
if(webView.canGoBack()){
webView.goBack();
}else{
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
OR
override this method --> onUnhandledKeyEvent (WebView view,
KeyEvent event)
more details on:
https://developer.android.com/reference/android/webkit/WebViewClient.html#onUnhandledKeyEvent(android.webkit.WebView,%20android.view.KeyEvent)
OR
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
boolean dispatchFirst = super.dispatchKeyEvent(event);
// Listening here for whatever key events you need
if (event.getAction() == KeyEvent.ACTION_UP)
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_SPACE:
case KeyEvent.KEYCODE_ENTER:
// e.g. get space and enter events here
break;
}
return dispatchFirst;
}
NOTE:-
Preventing developers from accessing the events by default was made by Googlers on purpose. Because the key event input isn't the only one anymore. There're gestures, voice and more is coming. Official recommendation is to "stop relying on legacy key events for text entry at all". Check out more details here: https://code.google.com/p/android/issues/detail?id=42904#c15
With my recent experience of inexplicable and inconsistent behaviour of calling loadUrl() before setWebViewClient() I would try calling loadUrl() AFTER setting ANYTHING to do with a multi-threaded WebView. That includes setOnTouchListener() and setOnKeyListener().
I realise my answer might not help your specific problem - but it might help others who have experienced similar behaviour and are setting things before before calling loadUrl().
If you want to detect keypress then try to override
onKeyPreIme(int keyCode, KeyEvent event);
I use ViewPager for a wizard flow in the application and I want to disable page switches from any user input (How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?).
Recently I discovered that when I run the application in an emulator I can still swipe page with PC keyboard left and right arrow keys.
Can I disable it? Is it a real event that can happen on a real device?
Well, I can't reproduce your issue in a ViewPager based project running on the emulator, but since your already extending the ViewPager, you can try overriding the method below to ignore the right and left keypresses.
Untested:
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
switch( keyCode ) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_LEFT:
return true;
}
return false;
}
I would imagine that this is possible on hardware if the user has a physical keyboard connected.
Update
Try this in your extended class:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
switch( event.getAction() ) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_LEFT:
return true;
}
return super.dispatchKeyEvent(event);
}
I am trying to capture the key-press for the shift or alt keys and it seems to work just fine with the physical keyboard. Unfortunately when I test the same code with the onScreen keyboard it doesn't respond at all (I've tried a 2.1, 4.03 emulator and 2.3 physical device).
This seems to be a platform issue that probably has no workaround, but as a last ditch effort I wanted to post the question here to see if anyone has found one (I am willing to entertain any ideas).
Thanks!
Edit to clarify my point: I tried putting a breakpoint on the " if (event.getAction() == KeyEvent.ACTION_DOWN) " line, and it will always stop if I press the shift of the physical keyboard, but never when I press the shift of the onScreenKeyboard. So, the problem is that onKey is not being executed for all keypresses of the onScreenKeyboard.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mEditText1 = (EditText) findViewById(R.id.editText1);
mEditText1.setOnKeyListener( new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
Toast.makeText(IMETestActivity.this, "Enter was consumed",
Toast.LENGTH_SHORT).show();
return true;
case KeyEvent.META_SHIFT_LEFT_ON:
case KeyEvent.META_SHIFT_RIGHT_ON:
Toast.makeText(IMETestActivity.this, "Meta Shift was consumed",
Toast.LENGTH_SHORT).show();
return true;
case KeyEvent.KEYCODE_SHIFT_LEFT:
case KeyEvent.KEYCODE_SHIFT_RIGHT:
Toast.makeText(IMETestActivity.this, "Shift was consumed",
Toast.LENGTH_SHORT).show();
return true;
default:
break;
}
}
return false;
}
});
}
Try logging the keycode whenever a key is pressed to make sure that the event is registering. If it is, just add that code to your switch statement.
For example, something like System.out.println(keyCode) at the beginning of your onKeyListener. You can view the output using LogCat.
I have an EditText with android:inputType="phone" keybord. There is an "OK" on this keyboard. I like to catch pressing this OK btn. However I don't know the key event. I would like to use code like this:
setOnKeyListener(new OnKeyListener()
{
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_DOWN)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.?????????? <- this one please
return true;
default:
break;
}
}
return false;
}
});
I hope the code is different from pressing the "round-arrow"!
I checked all the key events in the docs but could not find anything.
Thanks
The 'OK' button is usually associated with finishing the input, and is different from the others. Use setOnEditorActionListener to catch it:
editText.setOnEditorActionListener( new OnEditorActionListener()
{
public boolean onEditorAction( TextView v, int actionId, KeyEvent event )
{
// Do what you want to do here
}
});
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
public boolean onKey() called twice?
Display.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
solveExpression();
return true;
}
return false;
}
});
I'm trying to solve the expression contained within the Display(EditText), by pressing the enter button on the keyboard, yet it always interprets it as though I pressed the button twice. Does anyone know why this happens?
Try...
Display.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
// Check for ACTION_DOWN only...
if (KeyEvent.ACTION_DOWN == event.getAction()) {
solveExpression();
return true;
}
}
}
});
The 'action' can be ACTION_DOWN, ACTION_UP or ACTION_MULTIPLE (the last being for when a key is pressed and held). onKey() will be called for any/all of those actions.
As the other answer mentions, it's triggering twice because it's once for down and once for up.
if (event.getAction()!=KeyEvent.ACTION_DOWN) // we catch only key down events
return true;
Thus you stop listening other keyevents as onClick.
If you want nobody else further in chain to get the event for another piece of work, you should set
return false;
not an android guy either but the fact that it registers twice makes me think that OnKey encompasses a onKeyDown and onKeyUp. Would listening to onKeyUp work for you as well?