5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

長いテキストを展開できる「続きを読む」を持ったViewを作る

Last updated at Posted at 2024-04-03

はじめに

SwiftUIを使用して、コンテンツの一部のみを初めに表示し、ユーザーが「続きを見る」を選択することでメッセージ全体を表示するViewを考えていたときのコードになります。
ユーザーが「続きを見る」をタップすると、メッセージが展開されると共に「続きを見る」表示もサッと消えます。

利用環境

Xcode 15.3
Swift 5.10

「続きを見る」ボタンを持ったViewの作成

import SwiftUI

struct MessageView: View {
  // 表示するメッセージを定義します。
  let message: String
  
  // メッセージの表示状態を制御するための状態変数です。
  @State private var isExpanded = false

  var body: some View {
    VStack(alignment: .leading) {
      // メッセージを表示します。`isExpanded`の値に応じて行数の制限を変更します。
      Text(message)
        // 行数制限を設定します。
        // ここでは初期表示2行で設定しています。
        .lineLimit(isExpanded ? nil : 2)
        // アニメーションを設定します。
        .animation(.easeInOut, value: isExpanded)
        // テキストが適切に折り返されるようにします。
        .fixedSize(horizontal: false, vertical: true)
        // テキストを左揃えにします。
        .frame(maxWidth: .infinity, alignment: .leading)

      // メッセージが展開されていない場合、「続きを見る」ボタンを表示します。
      if !isExpanded {
        Button(action: {
          // ボタンが押されると、メッセージの表示状態を切り替えます。
          isExpanded.toggle()
        }) {
          Text("続きを見る")
            .foregroundColor(.secondary)
        }
      }
    }
  }
}

MessageViewの呼び出し

import SwiftUI

struct ContentView: View {
  var body: some View {
    // サンプルテキストです。このテキストを`MessageView`に渡して表示します。
    let sampleText = "ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。ここに長いテキストを入れます。"
    MessageView(message: sampleText)
      .padding()
  }
}

スクリーンショット

Simulator Screenshot.jpg

Simulator Screenshot3.jpg

「続きを読む」を行末に置くパターン

import SwiftUI

struct MessageView: View {
  // 表示するメッセージを定義します。
  let message: String
  
  // メッセージの表示状態を制御するための状態変数です。
  @State private var isExpanded = false

  var body: some View {
    HStack(spacing: 0) {
      Text(message)
        // 行数制限を設定します。
        // ここでは初期表示1行で設定しています。
        .lineLimit(isExpanded ? nil : 1)
        // アニメーションを設定します。
        .animation(.easeInOut, value: isExpanded)
        // テキストがオーバーフローした場合、末尾を省略します。
        .truncationMode(.tail)
        // テキストが適切に折り返されるようにします。
        .fixedSize(horizontal: false, vertical: true)
        // テキストを左揃えに設定し、展開時に横幅を広げます。
        .frame(maxWidth: isExpanded ? .infinity : nil, alignment: .leading)

      // メッセージが展開されていない場合、「続きを見る」ボタンを表示します。
      if !isExpanded {
        Button(action: {
          // ボタンが押されると、メッセージの表示状態を切り替えます。
          isExpanded.toggle()
        }) {
          Text("続きを読む")
            .font(.subheadline)
            .foregroundColor(.secondary)
        }
      }
    }
    .frame(maxWidth: .infinity, alignment: .leading)
  }
}

スクリーンショット

Simulator Screenshot - iPhone 15 - 2024-04-03 at 08.43.05.png

最後に

行末に「続きを見る」を設ける方法は、初期表示2行の際に期待通りの表示とならないなど、まだまだ改善が必要そうです。
また、新たな発見がありましたら書き留めたいと思います。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?