为设计添加交互处理程序

在本节中,我们将学习如何通过交互处理程序向我们的设计添加交互。

NewsApp with tap interaction

交互处理程序提供了一种方法来指定可以在组件的哪个位置进行交互(点击、双击等)。交互处理程序可以添加到设计中的任何图层。

添加处理程序

交互处理程序可以添加到任何图层。这允许设计师指定组件的哪些部分是可交互的。

  1. 选择**hero-item** 变体(框架),点击**参数**旁边的**+**,然后选择tap-handler 来添加交互处理程序。这允许开发人员编写对用户点击卡片做出反应的代码。

    The Figma plugin with the hero-item variant selected
  2. 在**audio-item** 变体中的**menu** 图标图层上重复上一步。这允许开发人员在用户点击菜单图标时显示菜单。

    The Figma plugin with the menu icon variant selected
  3. 如果您选择**on Menu tapped** 处理程序,您会注意到它只适用于**audio-item** 变体,因为其他变体没有菜单图标。但是,**on NewsCard tapped** 应用于所有三个变体。这意味着您可以提供一个处理程序(在代码中)在点击任何三个变体时运行,从而消除代码和参数的重复。我们将在接下来的在 Android Studio 中更新组件部分更详细地了解其工作原理。

    The Figma plugin with the tap handler selected

保存命名版本

现在让我们将此版本标记为准备好导入到代码中。

  1. 打开 Figma Relay 插件(如果尚未打开)。

  2. 点击对话框右下角的“与开发者共享”。

  3. 在**与开发者共享屏幕**上,输入版本的名称和描述。

    **示例标题**: 添加交互

    **示例描述**: 向卡片添加了两个交互处理程序

  4. 点击**保存**。

  5. 在 MAC 上按**CMD-L**,在 Windows 上按**CTRL-L** 将组件链接复制到剪贴板。

在 Android Studio 中更新组件

现在让我们更新**NewsCard**组件

  1. 在 Android Studio 中,确保“项目”工具窗口处于**Android**视图。然后右键点击app/ui-packages/news_card/,在上下文菜单的底部附近,点击**更新 UI 包**。

    Update UI Package option in the context menu
  2. 点击生成项目按钮 来构建您的项目。这将采用更新的 UI 包并生成更新版本的组合代码。

    Build button in the toolbar
  3. 查看app/java/com/example/hellonews/newscard/NewsCard.kt 并查看交互处理程序是如何作为参数添加到**NewsCard** (onNewsCardTapped, onMenuTapped) 的。

    // Design to select for NewsCard
    enum class View {
      HeroItem, ArticleItem, AudioItem
    }
    
    /**
    *   Displays a summary of a news article.
    *
    *   This composable was generated from the UI package 'news_card'.
    *   Generated code; do not edit directly
    */
    @Composable
    fun NewsCard(
      modifier: Modifier = Modifier,
      view: View = View.HeroItem,
      thumbnail: Painter = EmptyPainter(),
      headline: String = "",
      author: String = "",
      date: String = "",
      onNewsCardTapped: () -> Unit = {},
      onMenuTapped: () -> Unit = {}
    ) {
    ...
    

集成到应用中

现在让我们向我们的交互添加一些处理程序。

  1. app/java/com/example/hellonews/ui/home/HomeScreen.kt中,向下滚动到PostListArticleStories,大约在第 175 行。

    ...
    @Composable
    fun HomeScreen(...)
    
    @Composable
    private fun PostList(...)
    
    @Composable
    private fun PostListArticleStoriesSection(...)
    
    @Composable
    private fun SearchArticlesSection(...)
    
    @Composable
    private fun PostListArticleStories(
      postTop: Post,
      posts: List<Post>,
      createOnTapped: (String, String) -> () -> Unit
    ) {...}
    
    @Composable
    private fun AudioStoriesTitle(...)
    
    @Composable
    private fun PostListAudioStories(...)
    
    @Composable
    fun Dialog(...)
    ...
    
  2. 对于postTop,添加onNewsCardTapped 的处理程序。createOnTapped 打开一个对话框,其参数作为标题和正文。

    @Composable
    private fun PostListArticleStories(
      postTop: Post,
      posts: List<Post>,
      createOnTapped: (String, String) -> () -> Unit
    ) {
      ...
      Column(
          horizontalAlignment = Alignment.Start,
          modifier = ...
      ) {
          Spacer(modifier = Modifier.size(12.dp))
          NewsCard(
              thumbnail = painterResource(postTop.imageId),
              headline = postTop.title,
              author = postTop.metadata.author.name,
              date = postTop.metadata.date,
              onNewsCardTapped = createOnTapped("Card Tapped", postTop.title),
              view = View.HeroItem
          )
          Spacer(modifier = Modifier.size(12.dp))
          ...
      }
    }
    
  3. 对于每个帖子,添加onNewsCardTapped 的处理程序。

    @Composable
    private fun PostListArticleStories(
      postTop: Post,
      posts: List<Post>,
      createOnTapped: (String, String) -> () -> Unit
    ) {
      ...
      Column(
          horizontalAlignment = Alignment.Start,
          modifier = ...
      ) {
          ...
    
          posts.forEach { post ->
              NewsCard(
                  thumbnail = painterResource(post.imageId),
                  headline = post.title,
                  author = post.metadata.author.name,
                  date = post.metadata.date,
                  onNewsCardTapped = createOnTapped("Card Tapped", post.title),
                  view = View.ArticleItem
              )
              Spacer(modifier = Modifier.size(12.dp))
          }
      }
    }
    
  4. 仍在HomeScreen.kt中,向下滚动到PostListAudioStories,大约在第 260 行。

    ...
    @Composable
    fun HomeScreen(...)
    
    @Composable
    private fun PostList(...)
    
    @Composable
    private fun PostListArticleStoriesSection(...)
    
    @Composable
    private fun SearchArticlesSection(...)
    
    @Composable
    private fun PostListArticleStories(...)
    
    @Composable
    private fun AudioStoriesTitle(...)
    
    @Composable
    private fun PostListAudioStories(
      posts: List<Post>,
      createOnTapped: (String, String) -> () -> Unit
    ) {...}
    
    @Composable
    fun Dialog(...)
    ...
    
  5. 对于每个帖子,添加onNewsCardTapped 的处理程序。由于 Audio 变体具有菜单,因此将createOnTapped 分配给onMenuTapped

    @Composable
    private fun PostListAudioStories(
      posts: List<Post>,
      createOnTapped: (String, String) -> () -> Unit
    ) {
      Column(
          horizontalAlignment = ...,
          modifier = ...
      ) {
          posts.forEach { post ->
              NewsCard(
                  thumbnail = painterResource(post.imageId),
                  headline = post.title,
                  author = post.metadata.author.name,
                  date = post.metadata.date,
                  onNewsCardTapped = createOnTapped("Card Tapped", post.title),
                  onMenuTapped = createOnTapped("Menu Tapped", post.title),
                  view = View.AudioItem
              )
              Spacer(modifier = Modifier.size(12.dp))
          }
      }
    }
    
  6. 点击▶构建应用并在模拟器中运行。

    Run button in toolbar
    News app in action in preview

    太棒了!您已经学习了 Relay 的高级功能。

您可以在Relay 工作流程部分了解更多有关如何使用 Relay 的信息。如果您有任何反馈,我们也非常乐意听到。