禁用动作列表的滚动效果

ziL*_*iLk 6 android android-tv leanback

我有一个GuidedStepSupportFragment这样的片段。

public class SampleStepFragment extends GuidedStepSupportFragment {

    @NonNull
    @Override
    public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
        String title = "Title";
        String breadcrumb = "Breadcrumb";
        String description = "Description";
        Drawable icon = getActivity().getDrawable(R.drawable.ic_videocam_black_24dp);

        return new GuidanceStylist.Guidance(title, description, breadcrumb, icon);
    }

    @Override
    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {

        addAction(actions, ACTION_CONTINUE, "Action1");
        addAction(actions, ACTION_BACK, "Action2");

    }
}
Run Code Online (Sandbox Code Playgroud)

动作1

问题:当我滚动操作列表时,它显示如下;

动作1

但我想要这样的东西;

预期的

如何在我的操作列表中禁用此效果?

谢谢

Jen*_*nsV 3

我做到了,但要弄清楚并不容易。

没有受支持的方法来做到这一点,因为实际上使这成为可能的 API 是包私有的或故意隐藏不让公众使用。(你可以自己做,但最终你只是从 Leanback 库中复制类。)

解决方案:

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

完整示例

说明:

AGuidedStepSupportFragment请求 aGuidedActionsStylist负责渲染右侧的列表项。来源

造型师膨胀包含源的GuidedActionsStylist布局lb_guidedactions.xmlVerticalGridView

扩展并创建一个作为其布局管理器VerticalGridView。遗憾的是,这是私有的和最终的包......(android为什么......?)。它具有用于确定滚动行为方式的方法。来源BaseGridViewGridLayoutManagerGridLayoutManagersetFocusScrollStrategy

查看不同的焦点滚动策略:

/**
 * 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;
Run Code Online (Sandbox Code Playgroud)

因此,由于 API 是隐藏的,我们只需使用反射来公开该setFocusScrollStrategy方法并将其设置为FOCUS_SCROLL_ITEM.

但我们不能立即执行此操作,因为如果没有默认的滚动设置,列表项将弹出到布局的顶部并且不会保持居中。所以我添加了 500 毫秒的延迟,这太可怕了...如果您设法找出何时最好触发此延迟,请告诉我。