BrowseFragment следующий фокус вопросов

Я работаю с Android Leanback API, и у меня есть некоторые головные боли с BrowseFragment. По какой-то причине я не могу переместить фокус с BrowseFragment на ImageButton, который находится прямо над ним. Так как предполагается, что это на телевизоре, пользователи смогут перемещаться только путем смещения фокуса с помощью D-pad, нет возможности просто нажать на кнопку.

У меня есть следующий макет в одном из моих фрагментов, который в основном создает верхнюю строку, содержащую заголовок, кнопку, на которой я хочу сфокусироваться, и изображение логотипа, за которым следует BrowseFragment под ним (я меняю его во время выполнения, когда FrameLayout).

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@android:color/transparent"
          android:orientation="vertical"
          android:paddingLeft="3dp"
          android:paddingRight="3dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:layout_marginLeft="@dimen/lb_browse_padding_start"
    android:layout_marginTop="@dimen/lb_browse_padding_top"
    android:layout_marginRight="@dimen/lb_browse_padding_end"
    >

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/lb_browse_title_text_size"
    android:layout_gravity="left"
    android:layout_centerVertical="true"
    android:id="@+id/category_title"/>

    <ImageView
        android:id="@+id/imageLogo"
        android:layout_width="108dp"
        android:layout_height="44dp"
        android:layout_gravity="right"
        android:layout_alignParentRight="true"
        android:src="@drawable/cc_logo_focused"
        android:layout_centerVertical="true"/>

    <ImageButton
        android:layout_width="@dimen/cc_genre_theme_search_image_width"
        android:layout_height="@dimen/cc_genre_theme_search_image_height"
        android:src="@drawable/search_icon_focus"
        android:layout_gravity="right"
        android:background="@drawable/button_color"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/category_title"
        android:contentDescription="Search button"
        android:scaleType="fitCenter"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:adjustViewBounds="true"
        android:padding="5dp"
        android:clickable="true"
        android:layout_centerVertical="true"
        android:id="@+id/gt_search_button"
        android:backgroundTintMode="add"
        android:backgroundTint="@color/colorTranslucentBackground"/>


</RelativeLayout>

<FrameLayout
    android:id="@+id/CategoryFragment"
    android:name="android.support.v17.leanback.BrowseFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</LinearLayout>

Есть идеи, как правильно настроить приложение? Спасибо!

3 ответа

Решение

Я решил использовать следующие две функции для решения этой проблемы. Публикация здесь на случай, если у кого-то возникнет аналогичная проблема в будущем.

browseFragment - это переменная экземпляра в классе Fragment, частью которого являются эти методы.

private final int maxHookIntoFocusTries = 5;
private int hookIntoFocusTries = 0;

private void initFocusManagement() {
    View view = browseFragment.getView();
    Handler handler = new Handler();
    if(view == null){
        //Wait for the view to be added
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                initFocusManagement();
            }
        };
        handler.postDelayed(runnable, 250);
    }
    if ( view instanceof ViewGroup) {
        boolean found = hookIntoFocusSearch((ViewGroup) view);
        if ( found ){
            Timber.d("Successfully fixed focus");   //This is just a log
        }else if(hookIntoFocusTries < maxHookIntoFocusTries){
            //Allow multiple attempts to hook into the focus system
            //I want to say this was needed for when the browse fragment was
            //created but the child content hadn't been populated yet.
            //Been a while since I've messed with this code though
            hookIntoFocusTries++;
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    initFocusManagement();
                }
            }, 250);
        }
    }

}

private boolean hookIntoFocusSearch(ViewGroup vg) {
    boolean found = false;
    for ( int i=0; i<vg.getChildCount(); i++ ) {
        View view = vg.getChildAt(i);
        if ( view instanceof BrowseFrameLayout) {
            BrowseFrameLayout bfl = (BrowseFrameLayout)view;
            bfl.setOnFocusSearchListener(new BrowseFrameLayout.OnFocusSearchListener() {
                @Override
                public View onFocusSearch(View focused, int direction) {
                    if ( direction == View.FOCUS_UP ) {
                        return searchButton;
                    } else {
                        return null;
                    }
                }
            });
            found = true;
            break;
        } else if ( view instanceof ViewGroup ) {
            boolean foundInRecurse = hookIntoFocusSearch((ViewGroup)view);
            if ( foundInRecurse ) {
                found = true;
                break;
            }
        }
    }
    return found;
}

РЕДАКТИРОВАТЬ: Обновлен код, чтобы включить обработчик повтора

У меня были такие же проблемы, как у вас, и я был вдохновлен вашим кодом. Я внес некоторые коррективы.

в BrowseFragment, который я расширил, у меня есть этот метод:

public void workaroundFocus(){
    if(getView() != null) {
        View viewToFocus  = getActivity().findViewById(R.id.view_to_focus);
        BrowseFrameLayout browseFrameLayout = getView().findViewById(android.support.v17.leanback.R.id.browse_frame);
        browseFrameLayout.setOnFocusSearchListener((focused, direction) -> {
            if (direction == View.FOCUS_UP) {
                return viewToFocus;
            }
            else {
                return null;
            }
        });
    }
}

А потом:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    workaroundFocus();
    /*
      Rest of code
    */
}

Таким образом, нет необходимости использовать обработчики и таймеры.

       - I was also facing the same issue as I was not able to navigate from Left to right but when I press the Right arrow button but the focus moved to downside views instead of right side views. 

 - I achieve it using setOnKeyListener and the code snipped as mentioned below:

 - in the below, img_mygame is in focus and I want to move focus to the right side which is img_controller.

 
 img_mygame.setOnKeyListener((view, keyCode, event) -> {
            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                img_controller.requestFocus();
                img_mygame.setNextFocusRightId(R.id.img_controller);
                return true;
            }

            return false;
        });

   
Другие вопросы по тегам