向设计添加交互处理程序

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

NewsApp with tap interaction

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

添加处理程序

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

  1. 选择 **hero-item** 变量(框架),点击 **+** 按钮,然后在 **Parameter** 旁边选择 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 中,确保 **Project** 工具窗口处于 **Android** 视图中。然后右键点击 app/ui-packages/news_card/,并在上下文菜单的底部附近点击 **更新 UI 包**。

    Update UI Package option in the context menu
  2. 点击 Make Project button 构建您的项目。这会使用更新的 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 的信息。如果您有任何 反馈,我们也乐意收到您的意见。