返回博客首页
← 所有文章

Harness the power of CollectionView(第二部分) - Android 的可滑动单元格

2023年5月17日 — 作者:Nathan Walker

这是重点介绍CollectionView(一种功能强大的列表控件,具有循环利用行功能,可在每个平台上提供最佳体验,以满足各种需求)系列的第二部分。

  • → 第二部分 - Android 的可滑动单元格

👉 演示仓库

继续讨论 Android 的可滑动单元格,我们再次可以利用layoutStyle将行为注册到我们的控件。

利用 layoutStyle 自定义行为

CollectionView 支持一个layoutStyle属性,允许您针对控件注册自定义平台行为,例如

<CollectionView layoutStyle="swipe" />

这可以是任何用于标识自定义注册布局样式的字符串值。

CollectionView.registerLayoutStyle('swipe', {
  createLayout: () => {
    // return a customized platform layout
    return layout;
  },
});

Android 上可能的布局可以在RecyclerView.LayoutManager系列中找到。它提供了一个抽象基类,用于各种布局,如GridLayoutManagerLinearLayoutManagerStaggeredGridLayoutManager

可以找到许多涵盖此内容的教程;这里只是一些

NativeScript 最棒的一点是,您可能想要执行的许多操作的文档和教程已经可以在各种平台源中找到,因为毕竟,NativeScript 使用 JavaScript 为您提供了平台!

为可滑动单元格实现 GridLayoutManager

我们可以直接在 TypeScript 代码库中创建一个。

// Convenient Java/Kotlin package usage with NativeScript
import GridLayoutManager = androidx.recyclerview.widget.GridLayoutManager;

// Construct a GridLayoutManager
new GridLayoutManager(Utils.android.getApplicationContext(), 1);

使用上面提到的教程作为我们的指南,我们将通过配置回调来实现 1 个尾部滑动操作,如所示。这就是我们希望我们的createLayout看起来的样子

CollectionView.registerLayoutStyle("swipe", {
  createLayout(view: CollectionView) {
    const recyclerView = <RecyclerView>view.nativeView;

    // Create a swipe to delete handler
    const swipeToDeleteCallback = SwipeToDeleteCallback.initWithOwner(
      new WeakRef(view)
    );

    // Register the handler with our RecyclerView
    const itemTouchHelper = new ItemTouchHelper(swipeToDeleteCallback);
    itemTouchHelper.attachToRecyclerView(recyclerView);

    // Upon a full swipe, add a nice animation when the row removes itself
    recyclerView.addItemDecoration(
      new SwipeToDeleteAnimation()
    );

    return new GridLayoutManager(Utils.android.getApplicationContext(), 1);
  }
})

实现 ItemTouchHelper

将 Kotlin/Java 代码引入 TypeScript 文件以供 NativeScript 使用非常巧妙。我们可以使用示例博文来做到这一点,部分内容如下

import ItemTouchHelper = androidx.recyclerview.widget.ItemTouchHelper;
import RecyclerView = androidx.recyclerview.widget.RecyclerView;
import Canvas = android.graphics.Canvas;

@NativeClass()
class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {

  // Common way to statically init a class with a WeakRef to the owner
  static initWithOwner(owner: WeakRef<CollectionView>) {
    const swipe = new SwipeToDeleteCallback(
      ItemTouchHelper.UP |
        ItemTouchHelper.DOWN |
        ItemTouchHelper.START |
        ItemTouchHelper.END,
      ItemTouchHelper.LEFT
    );
    swipe.owner = owner;
    return swipe;
  }

  onChildDraw(
    c: Canvas,
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder,
    dX: number,
    dY: number,
    actionState: number,
    isCurrentlyActive: boolean
  ) {
    // configure swipeable regions as needed using standard drawable methods
  }
}

完整的示例说明了可能的范围,让您可以完全控制所需目标平台执行的每个细微方面。

如果我们在 Android 上运行此代码(ns debug android),并使用 CollectionView 标记,并使用TailwindCSS进行样式设置,以匹配我们在第一部分中使用的样式,如下所示

<CollectionView [items]="items" layoutStyle="swipe">
  <ng-template let-item="item">
    <GridLayout rows="auto,auto,auto" class="pl-4 pr-2 py-4 v-center">
      <Label
        [text]="item.name"
        class="text-[17px] text-black font-bold align-middle"
      ></Label>
      <Label
        row="1"
        [text]="item.subject"
        class="text-base text-black leading-none align-middle"
      ></Label>
      <Label
        row="2"
        [text]="item.body"
        class="text-base leading-none text-gray-500"
        maxLines="2"
      ></Label>
      <GridLayout rowSpan="3" columns="auto,auto" class="align-top h-right">
        <Label
          [text]="item.date | date : 'shortDate'"
          class="text-sm align-middle text-gray-500"
        ></Label>
      </GridLayout>
    </GridLayout>
  </ng-template>
</CollectionView>

我们将看到以下内容

此时,您可以根据项目需要进一步添加其他滑动区域。

接下来,我们将研究“视图模式”,它使我们能够在多列布局或单跨行设置之间切换。

关于 nStudio

nStudio 由开源合作者于 2016 年创立,因建立了一个健康的开源治理模型以服务于围绕 NativeScript 的全球社区利益而闻名。如果您需要项目的专业帮助,nStudio 提供涵盖多个学科的服务,可以通过[email protected]联系我们。