【SwiftUI】alignment(左寄せ・右寄せ)が効かない

この記事の概要

VStack内のTextの.multilineTextAlignmentプロパティが、全然効かなくて、色々と試行錯誤をしました。とりあえずはそれっぽい仕様が出来たのですが、あまり有効な手段ではないです。※この問題に対する解決法は現在調査中です。分かり次第追記します。

目次

  • この記事の概要
  • 目次
  • やろうとしたこと
  • コード全文
  • 対処法
  • 懸念点
  • まとめ
  • 参考文献

やろうとしたこと

この記事を執筆した2020年3月23日現在、週刊少年ジャンプ連載の古舘春一さん原作のアニメ「ハイキュー!!」シリーズの、4期にあたる「ハイキュー!! TO THE TOP」が放送されていたので、SwiftUIの練習がてら、このアニメを紹介する簡単なアプリケーションのUIを、実装しようとした。
[図1]現在のライブプレビュー画面
©古舘春一/集英社・「ハイキュー!!」製作委員会・MBS

さて見て分かる通り、すべての要素が中央揃えになっていることが分かるだろうか。自分はこのデザインはあまり意図しておらず、Text:作品概要の位置を左寄せに、Text:絶賛放送中の位置を右寄せにしようとした。

コード全文


import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(alignment: .center, spacing: 10.0) {
            Text("ハイキュー!! TO THE TOP")
                .font(.title)
                .fontWeight(.black)
                .foregroundColor(Color.orange)
            
            Text("絶賛放送中")
                .font(.subheadline)
                .multilineTextAlignment(.trailing)
                .frame(width: 400, height: 30, alignment: .trailing)
            
            Divider()
            

            TopImage()
                
            Text("作品概要")
                    .font(.headline)
                    .frame(width: 400, height: 30, alignment: .leading)
        
            Text("春の高校バレー宮城県予選、激闘を制し悲願の全国大会出場を決めた烏野高校排球部。全国大会を控えた彼らのもとに、影山の全日本ユース強化合宿招集の報せが舞い込んだ。さらに月島にも宮城県1年生選抜強化合宿への招集がかかる。同じ1年生との差に焦る日向は、宮城県1年生選抜強化合宿に押しかけるも……!?全国大会本番に向け、日向、影山、そして烏野高校排球部の更なる挑戦が始まる!!")
                
                Divider()
              
                VStack(alignment: .center) {
                    Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                        Text("このアニメをお気に入りに登録する")
                            .foregroundColor(Color.white)
                            .padding()
                            .background(Color.red)
                            .cornerRadius(10)
                    }
                }
                
                Spacer()

        }
        .padding()
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


コードが冗長なのは、SwiftUIを触るのが初めてであるしご愛嬌ということで少し勘弁していただきたいが、こんなコードを書いた。

調べてみたところSwiftUIでは、一番最初に書いたVStackのalignmentが大きな影響力を持っている、らしい。
   VStack(alignment: .center, spacing: 10.0) {

ここの.centerが絶対?

対処法

結論から言うと、位置を変更したいコードの二箇所に、
            
       Text("絶賛放送中")
                .font(.subheadline)
                .multilineTextAlignment(.trailing)
                .frame(width: 400, height: 30, alignment: .trailing)
            
            Divider()
            

            TopImage()
                
            Text("作品概要")
                    .font(.headline)
                    .frame(width: 400, height: 30, alignment: .leading)


.frameプロパティで幅(width)・高さ(height)・位置(alignment)を設定してあげることであった。

が、賢明な方ならお察しだと思うが、この方法で実装すると

[図2] 絶賛放送中・作品概要の寄せはうまくいっているように見える
©古舘春一/集英社・「ハイキュー!!」製作委員会・MBS

一見うまくいっているように見えるが、実はこのライブプレビュー画面は、iPhone11Maxで起動したものなのである。つまり、これをiphone8などのサイズで起動すると、どうなるだろうか。

[図3] iphone8で起動すると
©古舘春一/集英社・「ハイキュー!!」製作委員会・MBS

見ての通り、400ポイントの各Textは、iphone8の375ポイントの画面幅に対して、左右12.5ポイント分はみ出してしまいます。
なので、

//width 400→375に変更          
       Text("絶賛放送中")
                .font(.subheadline)
                .multilineTextAlignment(.trailing)
                .frame(width: 375, height: 30, alignment: .trailing

            
            Divider()
            

            TopImage()
                
            Text("作品概要")
                    .font(.headline)
                    .frame(width: 375, height: 30, alignment: .leading)


375に変更することで、

[図4]width:375にしてみた
©古舘春一/集英社・「ハイキュー!!」製作委員会・MBS

はみださずにレイアウトを表示することができた。

この状態で、iphone11Maxに戻すと、

[図5] iphone 11 Maxに戻した
 余白が現れていい感じになる。

width350をくらいに設定しておくことで、iphone7でも余白が現れる。

懸念点

ここで紹介した方法はスマートな方法ではありませんので、画面の幅を起動時に取得してグローバル変数に代入したものを、widthに入れる方法をはじめ、様々な方法を検討する必要があると思われる。

まとめ

もし、cssのように !importantのような制約を、SwiftUIでも使えたら強いと思いました。

参考文献

・ハイキュー!! 公式サイト
https://haikyu.jp/

・iPhone/iPad/Apple Watch解像度(画面サイズ)早見表 https://qiita.com/tomohisaota/items/f8857d01f328e34fb551



コメント

このブログの人気の投稿

【Unity】シーンギズモがデフォルトで表示されない時

【Swift4】argument passed to call that takes no arguments の解決策

【Rails5】SyntaxError: (): mapping values are not allowed エラーの解決法