此代码的目标是将三段文本排列在一行上,如果三段文本中的任何一段太长,则将中心文本降低\baselineskip
:
\documentclass{article}
\usepackage[showframe,papersize={5.5in,8.5in}]{geometry}
\newlength{\testwd}
\newcommand{\entry}[4][]{%
\setbox1=\hbox{\strut\bfseries#2}%
\setbox2=\hbox{\strut\itshape#3}%
\setbox3=\hbox{\strut#4}%
\setlength{\testwd}{\ifdim\wd1>\wd3 \wd1\else\wd3\fi}% Which is longer, L or R? Use it.
\noindent%
\if###1##\else\llap{#1\thinspace}\fi
\hbox to 0pt{\box1\hss}%
\hfill
%% If the longer side (L or R) is longer than the half the remaining area around
%% the center text, drop the center text.
\ifdim\dimexpr \testwd - (\linewidth - \wd2)/2\relax>0pt\lower\baselineskip\fi
\hbox{\box2}%
\hfill
\hbox to 0pt{\hss\box3}%
\par
}
\begin{document}
\entry{Left side text}{Center Text}{Right text}
\entry{Left side text that is rather long}{Center Text}{Right side text}
\entry{Left side text}{Center Text}{Right side text that is rather long}
\end{document}
得出的结果为:
出于好奇,我想知道是否有一种方法可以做到这一点而无需明确设置\testwd
?换句话说,是否可以将的计算\testwd
纳入是否降低中心文本的决策中?或者,有没有更有效的方法来做到这一点?(有如何使文本在同一行左对齐、居中对齐、右对齐?,但这并没有达到相同的效果,因为长行会相互覆盖,特别是中间的文本。当然,如果左右文本相互覆盖,那么一切都将不复存在。在这种情况下,这种情况不会发生,所以不是问题。)例如,这在音乐会节目中很有用。
答案1
以下测量每个文本组件的长度,并使用该长度作为将中心文本放置在\makecell[t]
具有空白第一行或按原样的结构内的条件。
\documentclass{article}
\usepackage[showframe,papersize={5.5in,8.5in}]{geometry}
\usepackage{makecell}
\newlength{\LeftItem}
\newlength{\CentreItem}
\newlength{\RightItem}
\newcommand{\entry}[3]{%
\par
\settowidth{\LeftItem}{\bfseries #1}%
\settowidth{\CentreItem}{\itshape #2}%
\settowidth{\RightItem}{#3}%
\noindent
\makebox[0pt][l]{\bfseries #1}\hfill
\makebox[0pt]{%
\ifdim\LeftItem>.5\dimexpr\linewidth-\CentreItem\relax
\makecell[t]{\strut \\ \itshape #2}%
\else
\ifdim\RightItem>.5\dimexpr\linewidth-\CentreItem\relax
\makecell[t]{\strut \\ \itshape #2}%
\else
\itshape #2%
\fi
\fi
}\hfill
\makebox[0pt][r]{#3}%
\par
}
\begin{document}
\entry{Left side text}{Center Text}{Right text}
\entry{Left side text that is rather long}{Center Text}{Right side text}
\entry{Left side text}{Center Text}{Right side text that is rather long}
\end{document}
代码将确保内容适合\linewidth
,并且元素的长度被精确测量。这可能会导致构造中所有内容仍设置在同一行上,但彼此非常接近。因此,通过以下方式添加一点缓冲区可能是可行的:
\newcommand{\entry}[3]{%
% ...
\settowidth{\CentreItem}{\itshape ~#2~}% Add space on either side of centre item
% ...
}
答案2
更新
这是经过修改的代码,其中考虑了 @DavidCarlisle 和 @JohnKormylo 的建议。我在最长的左/右和中间文本之间添加了间距;也使用了\rlap
和 ,\llap
而不是自己滚动。输出完全相同。
\documentclass{article}
\usepackage[showframe,papersize={5.5in,8.5in}]{geometry}
%% #1: optional marginal character; #2: left text; #3: center text; #4: right text
\newcommand{\entry}[4][]{%
\begingroup
\setbox0=\hbox{\strut\bfseries#2}%
\setbox2=\hbox{\strut\itshape#3}%
\setbox4=\hbox{\strut#4}%
%% Which is longer, L or R? Use it:
\setlength{\dimen0}{\ifdim\wd0>\wd4 \wd0\else\wd4\fi}%
\noindent%
\if###1##\else\llap{#1\thinspace}\fi %% Optional marginal character
\rlap{\box0}%
\hfill
%% If space between longest L/R entry and center text
%% is less than 0.5em, lower the center text by \baselineskip:
\ifdim\dimexpr \dimen0 - (\linewidth - \wd2 - 0.5em)/2\relax>0pt
\lower\baselineskip
\fi
\hbox{\box2}%
\hfill
\llap{\box4}%
\par
\endgroup
}
\begin{document}
\entry{Left side text}{Center Text}{Right text}
\entry{Left side text that is rather long}{Center Text}{Right side text}
\entry{Left side text}{Center Text}{Right side text that is rather long}
\end{document}