より良いユーザー体験を求めて "角丸" を深掘りする
先日、他社のFlutter製のアプリを触っていて、よくできているなーと感心していました。
いい意味でFlutter感がないなと。
しかし、そのことをデザイナーの友だちに伝えたところ、「まだFlutter感ある!」と言っていたのです。
さすがデザイナーだなと感心していたのですが、その視点はどこに向けられているのかを深掘りしてみました。
角丸に現れるFlutterっぽさ
この2つのオブジェクト、よく見ると微妙に角丸が違うのがわかりますでしょうか。
右の方が優しい印象を受けます。
この2つの違いはCorner smoothingを取り入れているかどうかになります。
もうちょいわかりやすいようにオブジェクトを重ねてみました。
どちらもRadiusは20pxですが、青色の方ははCorner smoothingを取り入れています。
青色の方が丸くなっていく角度が滑らかになっています。
角を滑らかにするCorner smoothing
Corner smoothingとは普通の角丸よりも滑らかにする技術で、iOS7のアプリアイコンから導入されました。
人間にとって尖っているものは触ると痛いため、嫌悪感を抱きます。
デジタルでも同じ印象を受けます。そのため角丸をつけて柔らかい印象を作ります。
Corner smoothingを使うことで、より柔らかく、優しい印象の見た目にすることが可能です。
この方法を知り、いろんな"角丸"のスクショを撮るようになったのですが、Corner smoothingを使っているもの、使っていないもの様々で面白いです。
Corner smoothingを使っている"角丸"
ChatGPTのメッセージ入力TextField
iOS純正のリマインダーアプリ
Arcのタブ
Corner smoothingではないもの
Slackのチャンネル名
ElevatedButton
RoundedRectangleBorderはCorner smoothingではない
先ほどのデザイナーが感じるFlutterぽさとはCorner smoothingにありました。
Flutterで角丸を作る際によく使うRoundedRectangleBorder
はCorner smoothingではありません。
そのため、Corner smoothingを実装するには他の方法を取る必要があります。
逆にSwiftUIを使えば、デフォルトでCorner smoothingが採用されているため、意識せずに使うことができます。
(SwiftUIに詳しいわけではないので間違っていたら指摘ください)
ElevatedButton(
child: const Text('Button'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: () {},
),
Flutter標準の方法では微妙...
Flutter標準のWidgetでCorner smoothingを作る方法は存在しています。
それがContinuousRectangleBorder
です。
しかしContinuousRectangleBorder
をそのまま使うと同じRadiusのpxを指定しても、全く異なった見た目になってしまいます。
以下はRoundedRectangleBorder
とContinuousRectangleBorder
を同じ10指定で実装したボタンです。
下がContinuousRectangleBorder
です。
そもそも全然見た目が違うことがわかります。
同じ10pxを指定した場合でも見た目が大きく違う。(下がContinuousRectangleBorder)
ElevatedButton(
child: const Text('Normal'),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: () {},
),
const SizedBox(height: 8),
ElevatedButton(
child: const Text('Corner smoothing'),
style: ElevatedButton.styleFrom(
shape: ContinuousRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
onPressed: () {},
),
打開策はある。
ContinuousRectangleBorder
をそのまま使うことはできませんが、他のの方法を検討してみます。
方法1: ContinuousRectangleBorder x 2.3529
ContinuousRectangleBorder
をそのまま使うことはできませんが、指定するRadiusにx 2.3529
してあげると綺麗な形に近づくそうです。
ElevatedButton(
child: const Text('Corner smoothing'),
style: ElevatedButton.styleFrom(
shape: ContinuousRectangleBorder(
// ここ
borderRadius: BorderRadius.circular(10 * 2.3529),
),
),
onPressed: () {},
),
参考: https://github.com/rydmike/squircle_study?tab=readme-ov-file#continuousrectangleborder-x-23529
方法2: package①(figma_squircle)
その他の方法としてPackageを使うこともできます。
Corner smoothingを実現するpackageでメジャーなものとしてFigmaSquircle
があります。
デザインツールのFigmaでもCorner smoothingを設定できるのですが、Figmaの計算方法に合わせた実装がされているみたいです。
使う際の懸念としてはRadiusに指定するpxが大きすぎるとレイアウトが崩れるみたいです。
なので崩れない範囲で使用する必要があります。
30を指定した場合に崩れている
ElevatedButton(
child: const Text('Corner smoothing'),
style: ElevatedButton.styleFrom(
shape: SmoothRectangleBorder(
borderRadius: SmoothBorderRadius(
cornerRadius: 10,
cornerSmoothing: 0.6,
),
),
),
onPressed: () {},
),
方法3: package②(smooth_corner)
他のpackageにsmooth_corner
というのもあります。
こちらはfigma_squircle
のようは崩れはありません。
懸念点としてはlerpが実装されていないため、アニメーションに対応していない点が挙げられます。
その他の方法
他にも色々な方法を検討しているGitHubのリポジトリがあり、導入する際に参考になりそうだなと思ったので貼っておきます。
それぞれの方法でメリット・デメリットがあるので、検討して導入するのが良さそうです。
最後に
Corner smoothingを導入するべきかはプロジェクトによると思いますが、エンジニアから「Flutterでもこんなことができますよ!」とデザイナーに提案できるとより良い議論ができるのではないでしょうか。
Flutterは特にiOS周りに詳しいデザイナーから嫌厭されがちですが、工夫すればできることはたくさんあります。
もちろんそのためにはエンジニアがよりデザインを理解し、デザイナーに歩み寄る必要があります。
他にも深掘り記事を出しているのでよかったらみていってください。
そのついでに記事にいいねをしてくれると嬉しいです。
Corner smoothingについてもっと知りたい方へ
株式会社SODAの開発組織がお届けするZenn Publicationです。 是非Entrance Bookもご覧ください! → recruit.soda-inc.jp/engineer
Discussion
普段なかなか意識することがない (or 優先度が下がりがち) ですが、こういう細部のクオリティも大事にしていきたいですね!
SwiftUI ではおっしゃる通りデフォルトで continuous スタイルが適用されますし、意図的に circular にすることも可能です (こういうところは Apple らしいですね) 。
ありがとうございます!
やはりデフォルトで対応されているのは良いですね...!
SwiftUI周りの知見が全くないので、助かります!!❤️