AndroidTV可滑動內(nèi)容編輯

前言

最近在寫AndroidTV的項目,遇到一個實現(xiàn)類似于移動端拖拽移動的效果,如下圖所示。

1.gif

TV與手機端最大的不同在手機是觸控的,TV需要獲取焦點。研究了一下,手機端是通過 RecyclerViewitemTouchHelper來實現(xiàn)這個效果的。那么TV該如何實現(xiàn)這個效果呢?

實現(xiàn)

在TV端雖然也可以使用RecyclerView,但是VerticalGridViewHorizontalGridView才是谷歌推薦在TV使用的。因此,我們把目標(biāo)放在這兩個控件當(dāng)中。小編這里使用的是VerticalGridView控件,布局文件就不粘貼了,完整代碼可以拉到最下方。

實現(xiàn)這個功能分為兩步:
自定義VerticalGridView并重寫focusSearch方法,focus變化時觸發(fā)位置互換;
ArrayObjectAdapter 中調(diào)用Moved實現(xiàn)數(shù)據(jù)更新。
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);
        }
    }

這篇文章到這里就結(jié)束了,寫的不好的地方歡迎大家指出,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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容