Search code examples
androidandroid-support-libraryandroiddesignsupportandroid-navigationview

Correctly creating a dpad-compatible UI


I want to develop an application that can be 100% functional even using a dpad, but not for TV devices, so I don't want to rely on Leanback library. I have already followed the guidelines here in order to focus the proper elements of my UI.

I am using the support design library and I'm having several issues with my NavigationView:

  • When I open the drawer for the first time, it has the first item checked, but another item focused
  • If I close and open the drawer again, there is no item checked and focus is lost

This is what I'm doing to handle the focus:

private void initDrawer(){
    drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
    navigationView = (NavigationView)findViewById(R.id.navigation_view);
    navigationView.setNavigationItemSelectedListener(this);
    drawerToggle = new ActionBarDrawerToggle(MainActivity.this, drawerLayout, R.string.app_name, R.string.app_name){
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            //This is not working properly
            navigationView.requestFocus();
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            //This seems to work
            mContentLayout.requestFocus();
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);
}

This is what I'm doing to toggle the drawer opening/closing using an hardware button:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event){
    if(keyCode==KeyEvent.KEYCODE_BUTTON_Y){
        drawerToggle.syncState();
        if(drawerLayout.isDrawerOpen(GravityCompat.START)){
            drawerLayout.closeDrawer(GravityCompat.START);
        }
        else {
            drawerLayout.openDrawer(GravityCompat.START);
        }
        return true;
    }
    else return super.onKeyUp(keyCode, event);
}

I would like to focus the first item on the NavigationView everytime I open the drawer. What am I missing?


Solution

  • This is a known bug of design support library, apparently.

    Google claims it's been fixed in 23.1.1 but it doesn't work.

    I had to make these changes in my onDrawerOpened method:

    @Override
    public void onDrawerOpened(View drawerView) {
        super.onDrawerOpened(drawerView);
        if(navigationView.requestFocus()){
            NavigationMenuView navigationMenuView = (NavigationMenuView)navigationView.getFocusedChild();
            navigationMenuView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        }
    }