2016-07-22 3 views
2

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

У меня есть следующий макет в одном из моих фрагментов, который в основном создает верхнюю строку, содержащую заголовок, кнопку, на которую я хочу сосредоточиться, и изображение логотипа, за которым следует 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; 
} 

EDIT: Обновленный код включает обработчик повтора

+0

Где и когда вы называете это, вы можете объяснить немного –

+0

@Ammarali Прошло некоторое время с тех пор, как я испортил его, но, просматривая код, похоже, мне нужно было вызвать его из фрагмента, содержащего BrowseFragment, в любое время: A) Объект BrowseFragment уже был инициализирован, и мы возобновляем фрагмент B) После инициализации фрагмента просмотра (я отредактирую приведенный выше код, чтобы включить обработчик повтора, когда мы все еще ожидаем, что представление будет настроено. оптимальный, но он работает) – vdwtanner

0

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

в 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 
    */ 
} 

Этот путь не существует никакой необходимости в использовании обработчиков и таймеров.

Смежные вопросы