How to use D-pad navigate switch between listview's row and it's decendants (Google-TV support)
Asked Answered
D

3

10

I have a listview which has an imageview inside each list item, when user click on that imageview, it will pop-up a menu.

It works very well on a normal android device with a touch screen.

But now I want to support google-tv, which app should be control by D-pad.

When I use D-pad to navigate through listview, only the entire row can be focus, I can't get the imageview inside listview be focus.

I try to add android:focusable="true" to imageview, but it cause the entire listview can't receive onItemClick event.

Does anyone know how to move the focus between listview rows and item inside listview using d-pad also keeps listview and imageview clickable?

Thanks a lot!

Diablerie answered 18/1, 2013 at 4:23 Comment(0)
D
4

I got my Listview work with D-pad which can switch focus inside a list item. This is how I solve it. First, let your list view is item focusable.

NOTE: If you trying to set ItemsCanFocus to false later in your code, your will find your list item can't get focus anymore even if your set back to true again, so don't do that.

mDpadListView.setItemsCanFocus(true);

Then you need a field to keep tracking which list item is current selected. Here I put the ViewHolder in the listItem's tag in Adapter.

mDpadListView.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view,
            int position, long id) {
        if (view.getTag() != null) {
            DpadListAdapter.ViewHolder holder = (ViewHolder) view.getTag();
            if (holder.shortCut != null && holder.shortCut.isShown()) {
                currentSelectView = view;
            } else {
                currentSelectView = null;
            }
        } else {
            currentSelectView = null;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});

Third, override onKeyDown() in Activity Method to control up, down, left, right key for D-pad.

When user press right button on D-pad, I let the listview to clearFoucs() and let the ImageView inside to obtain focus.

When user press up, down or left, the ImageView in list item will clear it's focus and the listView obtain focus again.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_DPAD_RIGHT:
        if (currentSelectView != null) {
            DpadListAdapter.ViewHolder holder = 
                (ViewHolder)      currentSelectView.getTag();
            mDpadListView.clearFocus();
            holder.shortCut.setFocusable(true);
            holder.shortCut.requestFocus();
            return true;
        }
        break;
    case KeyEvent.KEYCODE_DPAD_LEFT:
    case KeyEvent.KEYCODE_DPAD_UP:
    case KeyEvent.KEYCODE_DPAD_DOWN:
        if (currentSelectView != null) {
            DpadListAdapter.ViewHolder holder = 
                    (ViewHolder) currentSelectView.getTag();
            if (holder.shortCut.hasFocus()) {
                holder.shortCut.clearFocus();
                holder.shortCut.setFocusable(false);
                mDpadView.requestFocus();
                return true;
            }
        }
        break;
    default:
        break;
    }
    return super.onKeyDown(keyCode, event);
}
Diablerie answered 22/8, 2013 at 3:5 Comment(4)
Hi, i need help, i want to know how if i select an item with d-pad, then background color changes.Benner
you need to use a state list drawable on your item's background image, give android:state_focused="true" a different image from normal state. ref: developer.android.com/guide/topics/resources/…Diablerie
Hi, what is currentSelectViewDebacle
currentSelectView is the view your app currently have focus on it, provide by adapter. If your current focus in on the second item of listview, then the view contains the second item is the currentSelectView.Diablerie
I
8

You have to set the following for your ListView:

listView.setItemsCanFocus(true);

With that focusable views inside of your listItems won't be ignored.

Inure answered 19/1, 2013 at 4:35 Comment(1)
don't know how i didn't see that one in the docs, but it works great. the only other thing i'm having to do in my case is to override getVerticalFadingEdgeLength, while random returning 42 seems get it to behave. this tricks the list view in to always having enough of the next row down/up available for focusing. otherwise if the last row lines up exactly with the top/bottom of the screen the focus gets stuck.Gocart
D
4

I got my Listview work with D-pad which can switch focus inside a list item. This is how I solve it. First, let your list view is item focusable.

NOTE: If you trying to set ItemsCanFocus to false later in your code, your will find your list item can't get focus anymore even if your set back to true again, so don't do that.

mDpadListView.setItemsCanFocus(true);

Then you need a field to keep tracking which list item is current selected. Here I put the ViewHolder in the listItem's tag in Adapter.

mDpadListView.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view,
            int position, long id) {
        if (view.getTag() != null) {
            DpadListAdapter.ViewHolder holder = (ViewHolder) view.getTag();
            if (holder.shortCut != null && holder.shortCut.isShown()) {
                currentSelectView = view;
            } else {
                currentSelectView = null;
            }
        } else {
            currentSelectView = null;
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});

Third, override onKeyDown() in Activity Method to control up, down, left, right key for D-pad.

When user press right button on D-pad, I let the listview to clearFoucs() and let the ImageView inside to obtain focus.

When user press up, down or left, the ImageView in list item will clear it's focus and the listView obtain focus again.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_DPAD_RIGHT:
        if (currentSelectView != null) {
            DpadListAdapter.ViewHolder holder = 
                (ViewHolder)      currentSelectView.getTag();
            mDpadListView.clearFocus();
            holder.shortCut.setFocusable(true);
            holder.shortCut.requestFocus();
            return true;
        }
        break;
    case KeyEvent.KEYCODE_DPAD_LEFT:
    case KeyEvent.KEYCODE_DPAD_UP:
    case KeyEvent.KEYCODE_DPAD_DOWN:
        if (currentSelectView != null) {
            DpadListAdapter.ViewHolder holder = 
                    (ViewHolder) currentSelectView.getTag();
            if (holder.shortCut.hasFocus()) {
                holder.shortCut.clearFocus();
                holder.shortCut.setFocusable(false);
                mDpadView.requestFocus();
                return true;
            }
        }
        break;
    default:
        break;
    }
    return super.onKeyDown(keyCode, event);
}
Diablerie answered 22/8, 2013 at 3:5 Comment(4)
Hi, i need help, i want to know how if i select an item with d-pad, then background color changes.Benner
you need to use a state list drawable on your item's background image, give android:state_focused="true" a different image from normal state. ref: developer.android.com/guide/topics/resources/…Diablerie
Hi, what is currentSelectViewDebacle
currentSelectView is the view your app currently have focus on it, provide by adapter. If your current focus in on the second item of listview, then the view contains the second item is the currentSelectView.Diablerie
F
0

You can use the properties to access the D-pad as below in your layout file:

        android:nextFocusLeft="@+id/abc"
        android:nextFocusRight="@+id/xyz"
        android:nextFocusUp="@+id/pqr"
        android:nextFocusDown="@+id/mno"
        android:nextFocusForward="@+id/finish"

This all the properties will help you to access the D-pad in Google-TV.

Fussy answered 18/1, 2013 at 5:2 Comment(1)
the listview and listview's content are not in the same xml, so I don't know how to move the focus from listview itself into listview's content(like an imageview or textview).Diablerie

© 2022 - 2024 — McMap. All rights reserved.