Android TV Gridview dpad composed items - android

I'm sorry if this question has been answered before. Honestly, I have searched this issue a lot and although there are similar cases, none of them helped me.
I am developing an Android Application for a TV. I have created a GridView because I want to show some thumbnails of pictures and videos. Each item in the gridview has a picture and a text info below.
The problem is that I can't get the dpad to work properly. If I set android:focusable="true" in the items, I can navigate through the GridView, but I can't display the image/video after pressing enter or using the mouse (no call to "onItemClick()"). If I do not set android:focusable="true", I can't navigate through the GridView (maybe cuz I do not see it) and also I can't press enter and see the image/video, but I do can click with the mouse the item and see the image/video.
What can I do to make the dpad work properly?
Thank you very much in advance. I have been struggling with this since a big while, I would sincerely appreciate your help.

I faced the exact same problem yesterday. What you need to do is add an onKeyListener to the GridView and inside the onKey function handle the key presses. I'll share what I did with it so that you can build on it.
gridView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){
Toast.makeText(getActivity(), "CENTER", Toast.LENGTH_SHORT).show();
if(gridView.getSelectedItemPosition() == -1){
if(gridView.getCount() > 0)
gridView.setSelection(0);
else
return false;
}
CURRENT_VIDEO_NUM = gridView.getSelectedItemPosition();
}
else{
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_RIGHT:
Toast.makeText(getActivity(), "RIGHT", Toast.LENGTH_SHORT).show();
if(event.getAction() == 0){
try {
if (gridView.getSelectedItemPosition() < gridViewAdapter.getCount() - 1) {
gridView.setSelection(gridView.getSelectedItemPosition() + 1);
return true;
}
} catch (Exception e) {
gridView.setSelection(gridViewAdapter.getCount() - 1);
return true;
}
}
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
Toast.makeText(getActivity(), "LEFT", Toast.LENGTH_SHORT).show();
if(event.getAction() == 0){
try {
if (gridView.getSelectedItemPosition() > 0) {
gridView.setSelection(gridView.getSelectedItemPosition() - 1);
return true;
}
} catch (Exception e) {
gridView.setSelection(0);
return true;
}
}
break;
case KeyEvent.KEYCODE_DPAD_UP:
Toast.makeText(getActivity(), "UP", Toast.LENGTH_SHORT).show();
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
Toast.makeText(getActivity(), "DOWN", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(getActivity(), "ELSE" + keyCode, Toast.LENGTH_SHORT).show();
break;
}
}
return false;
}
});
Now let me explain whats happening here.
1) I check if the center button is pressed, if thats the case, I'll perform the action that is to be performed when an item is clicked.
2) If RIGHT button is pressed, the selection is moved to right and the same for the left one.
3) UP and DOWN are a little less trivial. Since I was just building a demo, I didn't spend time on it. Won't be a problem though, just increment/decrement the total number of columns of the grid view keeping in mind the max/min of the items.
Try building on it and if you face any issue, do let me know.

Related

How to define up and down arrow in custom android keyboard

I have created android keyboard and I am creating arrows to move the cursor in the user input, I could do the left and right but I couldn't know how to write the code for the up and down .. here is the code
switch (arrow){
case KEY_LEFT:
CharSequence leftText = getCurrentInputConnection().getTextBeforeCursor(1000, 0);
int leftLen = leftText.length() ;
getCurrentInputConnection().setSelection(leftLen-1, leftLen-1);
break;
case KEY_RIGHT:
CharSequence rightText = getCurrentInputConnection().getTextBeforeCursor(1000, 0);
int rightLen = rightText.length() ;
getCurrentInputConnection().setSelection(rightLen+1, rightLen+1);
break;
case KEY_UP: case KEY_DOWN:
break;
}
can any one help me implementing the down and up ??
If you just want to move cursors
https://developer.android.com/reference/android/inputmethodservice/InputMethodService.html#sendDownUpKeyEvents(int)
Try use sendDownUpKeyEvents method
sendDownUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT);
Will simply do the work.
First of all, I recommend doing something like this to check for key presses
myEditText.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:
moveCursorLeft();
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
moveCursorRight();
return true;
case KeyEvent.KEYCODE_DPAD_UP:
moveCursorUp();
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
moveCursorDown();
return true;
}
}
return false;
}
});
I'm going off the assumption that you're programming a text editor of some sort.
The implementation for up and down depends on what you want those buttons to do, and how you've implemented things so far. For example, you could have each line as its own EditText that is kept track of in an ArrayList. Then, each time you add a new line, you can add a new EditText to the ArrayList. And when a user presses up or down, you can just change the index of the ArrayList by 1 in the correct direction.
I imagine that would be a pretty inefficient way of doing it, but it would be easy to define what up and down do. It's difficult to say more about what you should do without seeing more of your code.

onSingleTapConfirmed invoked also for click on 3-dots action bar button, which cause lot of trouble

In my app i show\hide sys-ui such as navigation\status bar.
i'm doing it by consuming the 'onSingleTapConfirmed' event and managed to toggle betwwen hide\show these ui-sys :
#Override
public boolean onSingleTapConfirmed(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (sysBarsAreVisible) {
hideSystemUI();
} else {
showSystemUI();
}
break;
}
return true;
}
This works just fine. navigation and status bars show and hide as i expected.
the problem is that when i try to press the 3dot button (...) in the action-bar the single-tap event is invoking and hiding the action-bar and the float menu that show-up and is gone right after.
any idea how can i solve it ? how to recognize that the 3-dot button is pressed and skip the all show\hide operation.
Thanks
I solved similar problem by calculating if touch coordinates are within view bounds or outside.
According to Adam Fręśko answer..
i added the folowing lines to my code:
#Override
public boolean onSingleTapConfirmed(MotionEvent event) {
Log.d(TAG, "raw Y: " + event.getRawY());
Log.d(TAG, "bar height: " + actionBar.getHeight());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (event.getRawY() > actionBar.getHeight() * 1.2) {
if (sysBarsAreVisible) {
hideSystemUI();
} else {
showSystemUI();
}
return true;
}
}
return false;
}
i compared the original raw Y coordinate against the action-bar's height to know if the user's action was outside the action-bar bounds.
I also multiple action-bar's height in 1.2 to extend the bounds for those who have big fingers :-).
Works perfect, Thanks!
The better approach is to consume the event at the ACTION_UP, cause the ACTION_DOWN can be consumed by the ActionBar making the ACTION_UP not being fired in your listener.

Scroll to next item in list using Next key from softkeyboard

I have the following issue:
I have a listview with custom rows, and on each row there are several edit texts (one or two).
I want to be able to scroll to next element every time I touch the next button from the soft keyboard.
I have implemented the following code:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (displayFlag == GuiConstants.GUI_QUICK_DISPLAY) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.FLAG_EDITOR_ACTION: {
scrollToNext();
return true;
}
}
}
}
return super.dispatchKeyEvent(event);
}
private void scrollToNext() {
int currentPosition = listView.getFirstVisiblePosition();
if (currentPosition == listView.getCount() - 1)
return;
listView.setSelection(currentPosition + 1);
}
The problem is that the list scrolls and works great until a row has to be created (it is not yet visible). At this point the Next button is replaced by Done button.
Does anybody have any idea what can I do?
Or maybe can somebody point a tutorial where I can find more about this issue?
Thanks,
Arkde
use custom EditText here is the code that might help you
EditText test = new EditText(context){
#Override
public void onEditorAction(int actionCode) {
// TODO Auto-generated method stub
super.onEditorAction(actionCode);
if(actionCode == EditorInfo.IME_ACTION_NEXT){
}
}
};

Capturing special key presses (shift, alt) of the Soft / OnScreen keyboard

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.

Determine when touch down happens and then when it is released

I thought my code would work, but I guess not. I'm just trying to get it to read when the phone is touched. An animation will happen while its held. Then I would like it to determine when it is released so the animation will stop. My code looks like this with toasts as fillers until I get it working.
ImageView image = (ImageView)findViewById(R.id.pImage);
image.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
Toast.makeText(PalsPage.this, "Is DOWN", Toast.LENGTH_SHORT).show();
break;
}
case MotionEvent.ACTION_UP: {
Toast.makeText(PalsPage.this, "Is UP", Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
Any help would be appreciated. Thanks
I think you are getting only the "Is DOWN" Toast.
The problem is in the return value.
You have to return truefor the code to work. otherwise the ACTION_UP event will not come to this view's listener.
you should return true so your image view keeps the events. i imagine your getting the first toast but not the second.

Categories

Resources