Мне это удалось, и это было нелегко понять.
Не существует поддерживаемого способа сделать это, поскольку API-интерфейсы, которые на самом деле делают это возможным, являются частными пакетами или намеренно скрыты от публичного использования. (Вы можете сделать это самостоятельно, но в конечном итоге вы просто скопируете классы из библиотек для откидывания назад.)
Решение:
@Override
public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
addAction(actions, GuidedAction.ACTION_ID_CONTINUE, "Action1");
addAction(actions, GuidedAction.ACTION_ID_CANCEL, "Action2");
// Run code delayed on mainThread (any other/better method can/should be used)
// It's delayed because if focus scroll is disabled, the list will stick to the top of the layout
new Handler(Looper.getMainLooper()).postDelayed(this::disableFocusScroll, 500);
}
private void disableFocusScroll() {
RecyclerView.LayoutManager layoutManager = SampleStepFragment.this.getGuidedActionsStylist().getActionsGridView().getLayoutManager();
try {
Method method = layoutManager.getClass().getMethod("setFocusScrollStrategy", int.class);
method.invoke(layoutManager, 1 /* FOCUS_SCROLL_ITEM */);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "disableFocusScroll: ", e);
}
}
Полный пример
Объяснение:
GuidedStepSupportFragment
запрашивает GuidedActionsStylist
, который отвечает за отображение элементов списка с правой стороны. источник
GuidedActionsStylist
Стилист увеличивает макет lb_guidedactions.xml
, который содержит VerticalGridView
источник
VerticalGridView
расширяет BaseGridView
и создает GridLayoutManager
в качестве менеджера компоновки. Этот GridLayoutManager
, к сожалению, является закрытым и окончательным пакетом... (андроид, почему..?). Он имеет метод setFocusScrollStrategy
, который используется для определения поведения прокрутки.источник
Посмотрите различные стратегии прокрутки фокуса:
/**
* Always keep focused item at a aligned position. Developer can use
* WINDOW_ALIGN_XXX and ITEM_ALIGN_XXX to define how focused item is aligned.
* In this mode, the last focused position will be remembered and restored when focus
* is back to the view.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_ALIGNED = 0;
/**
* Scroll to make the focused item inside client area.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_ITEM = 1;
/**
* Scroll a page of items when focusing to item outside the client area.
* The page size matches the client area size of RecyclerView.
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final static int FOCUS_SCROLL_PAGE = 2;
Итак, поскольку API скрыт, мы просто используем отражение, чтобы открыть метод setFocusScrollStrategy
и установить для него значение FOCUS_SCROLL_ITEM
.
Однако мы не можем сделать это немедленно, так как без настройки прокрутки по умолчанию элементы списка будут всплывать в верхней части макета и не будут оставаться в центре. Поэтому я добавил задержку в 500 мс, что ужасно... Если вам удастся узнать, когда лучше всего это активировать, дайте мне знать.
person
JensV
schedule
15.04.2020