Ellipsizeは、ピクセル単位で行を切り取る代わりに、末尾または中央に省略記号(…)を追加して、テキストがコンテナに収まらないことをユーザーに知らせるテキスト切り詰めメカニズムです。この技術は、見出し、ボタン、連絡先リスト、および幅が制限されたUIコンポーネントで使用されます。Google Material Design Guidelinesによると、ellipsizeはTextViewとUILabelの標準的な動作であり、開始、中央、終了、マーキーの4つの切り詰めモードをサポートしています。
重要なポイント
Ellipsize(ellipsis — 省略記号から)は、コンテナのサイズを超えるテキストを表示するための技術です。単に行を境界で切り取る代わりに、ellipsizeは省略記号(3つの点、Unicode U+2026)を追加して、隠れたコンテンツがあることをユーザーに示します。
この用語はAndroid SDKで確立されており、android:ellipsizeプロパティがオーバーフロー時のTextViewの動作を定義します。iOSでは、同様の機能は切り詰めと呼ばれ、NSLineBreakModeを介して管理されます。ウェブでは、値がellipsisのCSSプロパティtext-overflowが使用されます。
Ellipsizeの主な目的は、テキストが短縮されたことをユーザーに知らせることです。ピクセルベースのクリッピングでは単語が半分に切れる可能性がありますが、ellipsizeは読みやすさを保証します。省略記号は単語や文字を壊さずに、完全な単語または文字の後に配置されます。これはMaterial DesignおよびHuman Interface Guidelinesの原則に沿っています。
コンテナの幅が固定でテキストの長さが動的な場合、記事の見出し、表のセル、ラベル付きボタン、リスト内の連絡先、パンくずリスト、ファイルパスなどでellipsizeを使用してください。
Androidでは、ellipsizeはXMLのandroid:ellipsize属性またはコード内のsetEllipsize()メソッドを介して設定されます。4つのモードが利用可能で、それぞれテキストのどの側面が切り詰められるかを決定します。
ENDモード(ほとんどの場合デフォルト)は行の終わりを切り詰め、コンテナの右側に省略記号を配置します。STARTモードは先頭を切り詰めます — 省略記号は左側、表示テキストは右側です。MIDDLEは中央を切り詰め、行の先頭と末尾を表示したままにします。MARQUEEモードはテキストのアニメーションスクロールで、省略記号は表示されず、テキストは循環的にスクロールします。
<!-- XML layout -->
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="Very long text that will be truncated"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true" />
<!-- Kotlin code -->
textView.setEllipsize(TextUtils.TruncateAt.MIDDLE)
重要: ellipsizeはmaxLinesまたはsingleLineとの組み合わせでのみ機能します。行数が制限されていない場合、TextViewは高さ方向に拡大し、ellipsizeは有効になりません。Android 8.0(API 26)以降、ellipsizeはmaxLines > 1のマルチラインモードをサポートしています — 省略記号は最後の行の末尾に配置されます。
プログラムで使用するには、TextUtils.TruncateAtをEND、START、MIDDLE、MARQUEEのいずれかの値で呼び出します。値NONEはellipsizeを無効にします。
実際には、ENDは90%のケースに適しています — ユーザーはテキストが末尾で切り詰められることを期待しています。MIDDLEはファイルパス(例: "/User/.../project/main.kt")に使用され、パスの末尾が見えるようにします。STARTは共通のプレフィックスを持つ名前に使用されます(例: "...@gmail.com")。
iOSでは、ellipsizeに相当するのはUILabelクラスのlineBreakModeプロパティです(UITextViewの場合はNSTextContainer)。3つの切り詰めモードが利用可能です: .byTruncatingTail(末尾)、.byTruncatingMiddle(中央)、.byTruncatingHead(先頭)。
.byTruncatingTailモードはandroid:ellipsize="end"に対応します。.byTruncatingHeadはSTART、.byTruncatingMiddleはMIDDLEに対応します。.byClippingモードは省略記号なしでテキストを切り詰めますが、これは現代のインターフェースではほとんど使用されません。.byCharWrappingモードは切り詰めなしで文字単位で折り返します。
let label = UILabel()
label.text = "ラベル境界に収まらない長いテキスト"
label.lineBreakMode = .byTruncatingMiddle
label.numberOfLines = 1
// NSAttributedStringはlineBreakModeもサポートしています
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingTail
iOSでは、切り詰めはnumberOfLinesと連携して機能します。numberOfLines = 1の場合、テキストは1行で切り詰められます。numberOfLines = 2の場合は2行目で切り詰められます。UITextViewはNSTextContainer.lineBreakModeを使用し、これも3つの切り詰めモードすべてをサポートしています。
iOSの特徴: UILabelの.byTruncatingMiddleモードは短い文字列で予期しない動作をすることがあります — 文字列が完全に収まる場合、省略記号は表示されません。短い文字列で省略記号を確実に表示するには、sizeThatFitsを介したカスタムロジックを使用してください。
ウェブ開発では、ellipsizeはCSSプロパティtext-overflow: ellipsisをoverflow: hiddenおよびwhite-space: nowrapと組み合わせて実装されます。これはウェブインターフェースで省略記号付きで行を切り詰める標準的な方法です。
.text-cell {
width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
text-overflowプロパティはoverflow: hiddenなしでは機能しません — ブラウザはコンテンツがクリップされていることを知る必要があります。white-space: nowrapは行の折り返しを防ぎます。そうしないと、テキストが次の行に移り、オーバーフローが発生しません。
マルチラインの切り詰め(例: 2行目末尾に省略記号がある2行)には、以前は実験的な-webkit-line-clampプロパティが使用されていましたが、現在はCSS Overflow Level 4でline-clampとして標準化されています。
実際には、text-overflow: ellipsisは10年以上にわたってすべてのモダンブラウザでサポートされており、ウェブでテキストを切り詰める最も信頼性の高い方法です。
Ellipsizeモードの選択はUXに影響し、インターフェースの認識を向上させることも、ユーザーを混乱させることもあります。主なルール: ユーザーは、理解に最も必要のない部分が切り詰められることを期待します。
ENDモードは見出し、キャプション、タイトルに適しています — ユーザーは行の先頭を見てコンテキストを理解します。右側の省略記号は「続きがあるが、収まらなかった」ことを意味します。これが最も直感的で一般的なモードです。
MIDDLEモードはファイルパス、メールアドレス、長い識別子に不可欠です。行の末尾に一意の情報(ファイル名、ドメイン)が含まれている場合、ユーザーは特にそれを見るべきであり、先頭は短縮できます。例: "/User/.../important_document.pdf" — ファイル名がすぐに表示されます。
STARTモードはほとんど使用されませんが、共通のプレフィックスを持つ連絡先のリストに役立ちます — 例えば、すべてのアドレスが同じドメインに属する場合、"username@gmail.com"の代わりに"...@gmail.com"とします。ただし、このパターンは役立つよりも混乱を招くことがよくあります。Nielsen Norman Groupによると、ユーザーは左から右に読み、先頭に重要な情報を期待するため、STARTの切り詰めは認知的負荷を高めます。
MARQUEEモード(スクロールテキスト)は、更新頻度の低い単一行要素にのみ適しています: プレーヤーの現在のトラック、ニュースティッカー、ステータスバー。テーブル、リスト、フォームにマーキーを使用しないでください — アニメーションは気が散り、弱いデバイスではパフォーマンスが低下します。
最初の問題 — ellipsizeが機能しない。最も一般的な原因は行数制限の欠如です。maxLinesがないと、TextViewは高さ方向に拡大し、幅のオーバーフローが発生しません。解決策: 常にmaxLinesを指定してください(単一行の場合はsingleLine="true")。
2番目の問題 — プログラムでテキストを変更すると省略記号が表示されない。setText()を呼び出した後、TextViewが正しく再描画されない場合があります。解決策: テキストを変更した後、invalidate()またはpost(() -> requestLayout())を呼び出してください。
3番目の問題 — 異なるAndroidバージョンでの動作の違い。API 23より前は、マルチラインモード(maxLines > 1)でのellipsizeはサポートされていませんでした。解決策: 互換性のために、Build.VERSION.SDK_INTを確認し、AndroidXのViewCompat.setEllipsize()を使用してください。
4番目の問題 — カスタムフォントで省略記号が表示されない。フォントにU+2026グリフが含まれていない場合、省略記号は3つの点に置き換えられます。解決策: フォントに省略記号グリフがあるか確認するか、fontFamilyを介してフォールバックフォントを追加してください。
よくある質問
はい、maxLinesまたはsingleLineは必須です。行数を制限しないと、TextViewは高さ方向に拡張され、切り詰めは有効になりません。
Ellipsizeは切れ目に省略記号を追加し、隠れたテキストについてユーザーに知らせます。Clipはインジケーターなしで単に境界でテキストを切り取ります。
標準のtext-overflow: ellipsisは完全な単語の後に切り詰めます。単語の途中で切り詰めるには、overflow-wrap: break-wordまたは幅を測定するJavaScriptソリューションを使用してください。
はい、NSTextContainerのtextContainer.lineBreakModeプロパティを介して機能します。デフォルトでは、UITextViewは.byWordWrappingを使用します。切り詰めのためには.byTruncatingTail/Middle/Headに変更してください。
textView.setEllipsize(null)またはtextView.setEllipsize(TextUtils.TruncateAt.NONE)を呼び出します。その後、テキストは切り詰められる代わりに折り返されます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。