AndroidTV可滑动内容编辑

2024-01-10  本文已影响0人  神SKY

前言

最近在写AndroidTV的项目,遇到一个实现类似于移动端拖拽移动的效果,如下图所示。

1.gif
TV与手机端最大的不同在手机是触控的,TV需要获取焦点。研究了一下,手机端是通过 RecyclerViewitemTouchHelper来实现这个效果的。那么TV该如何实现这个效果呢?

实现

在TV端虽然也可以使用RecyclerView,但是VerticalGridViewHorizontalGridView才是谷歌推荐在TV使用的。因此,我们把目标放在这两个控件当中。小编这里使用的是VerticalGridView控件,布局文件就不粘贴了,完整代码可以拉到最下方。

实现这个功能分为两步:
自定义VerticalGridView并重写focusSearch方法,focus变化时触发位置互换;
ArrayObjectAdapter 中调用Moved实现数据更新。
public View focusSearch(View focused, int direction) {
        View itemView = findContainingItemView(focused);
        if (itemView != null && isSwapMode()) {
            return swapItemsIfNeeded(itemView, direction);
        }
        return super.focusSearch(focused, direction);
    }

    private View swapItemsIfNeeded(View focused, int direction) {
        int position = getChildAdapterPosition(focused);
        ItemAnimator animator = getItemAnimator();
        if ((animator == null || !animator.isRunning())
                && canMoveInDirection(position, direction)) {
            int spanCount = getSpanCount();
            switch (direction) {
                case FOCUS_LEFT:
                    moveItem(position, position - 1);
                    break;
                case FOCUS_UP:
                    moveItem(position, position - spanCount);
                    break;
                case FOCUS_RIGHT:
                    moveItem(position, position + 1);
                    break;
                case FOCUS_DOWN:
                    moveItem(position, position + spanCount);
                    break;
                default:
                    break;
            }
        }
        return focused;
    }

    private boolean canMoveInDirection(int position, int direction) {
        int spanCount = getSpanCount();
        LayoutManager m = getLayoutManager();
        assert m != null;
        if (direction == FOCUS_LEFT) {
            return position % spanCount > 0;
        } else if (direction == FOCUS_UP) {
            return position - spanCount >= 0;
        } else if (direction == FOCUS_RIGHT) {
            return !(position % spanCount >= (spanCount - 1) ||
                    position >= m.getItemCount() - 1);
        } else if (direction == FOCUS_DOWN) {
            return position + spanCount <= m.getItemCount() - 1;
        }
        return false;
    }

    private void moveItem(int fromPosition, int toPosition) {
        if (adapter != null) {
            adapter.move(fromPosition, toPosition);
        }
    }

这篇文章到这里就结束了,写的不好的地方欢迎大家指出,Demo下载地址:Demo。最后,希望这篇文章对各位看官们有所帮助。如果看官们可以给小编一个小小的支持那就更好了。

参考

https://stackoverflow.com/questions/54236100/how-do-i-move-grid-items-on-android-tv
https://www.mi-dong.com/post/android/android-tv-recyclerview-item-move/
https://blog.51cto.com/u_12855/6662173

上一篇 下一篇

猜你喜欢

热点阅读