我经常有枚举列表,其中列表中的项目高度不均匀,通常是因为显示数学项目,例如dfrac
。 (是的,我知道内联显示的显示数学的印刷问题,但这种布局是我正在准备的文档类型的要求。)为了使列表间距均匀,我目前使用vphantom
,如下面的 MWE 所示:
\documentclass{article}
\usepackage{enumitem}
\usepackage{mathtools}
\begin{document}
\begin{enumerate}[label=\Alph*)]
\item $x = y^2 + 4y + 13 \vphantom{\sqrt{\dfrac{x-4}{2}}}$
\item $x = 2\left(y + 1\right)^2 + 4 \vphantom{\sqrt{\dfrac{x-4}{2}}}$
\item $y = 2\left(x + 1 \right)^2 - 4 \vphantom{\sqrt{\dfrac{x-4}{2}}}$
\item $y = -\sqrt{\dfrac{x-4}{2}}+2$
\end{enumerate}
\end{document}
我想做的是让最终用户无需一直记住添加vphantom
。据我所知,我需要一个命令来跟踪列表中每行的高度,将最大的一行保存到辅助文件中,并在每个项目中插入一个支柱,该支柱的大小取自保存的值。有没有一个包已经可以做到这一点?或者,我该如何创建这样的命令?(我还没有掌握辅助文件。)
编辑:
Heiko 的解决方案给了我完成这项工作所需的线索。下面是我为包装整个过程所做的工作,这样我就不必每次都费心定义:
\documentclass{article}
\usepackage{enumitem}
\usepackage{mathtools}
\usepackage{etoolbox}
\usepackage{xparse}
\newcommand{\choicestext}{}
\newcommand{\phantomtext}{}
\newcommand{\choice}[1]{%
\xappto\choicestext{\unexpanded{\item #1\vph}}%
\xappto\phantomtext{\unexpanded{\{#1\}}}
}
\newenvironment{choices}{%
\renewcommand{\choicestext}{}%
\renewcommand{\phantomtext}{}%
}{%
\def\vph{\vphantom{\smash[b]\phantomtext}}%
\begin{enumerate}[label=\Alph*)]
\choicestext
\end{enumerate}
}
\begin{document}
\begin{choices}
\choice{$x = y^2 + 4y + 13$}
\choice{$x = 2\left(y + 1\right)^2 + 4$}
\choice{$y = 2\left(x + 1 \right)^2 - 4$}
\choice{$y = -\sqrt{\dfrac{x-4}{2}}+2$}
\end{choices}
\end{document}
答案1
可以将公式放入本地定义的宏中。然后,\vphantom
只需使用它们全部,而不需要知道哪个公式具有最大的高度和深度。
\documentclass{article}
\usepackage{enumitem}
\usepackage{mathtools}
\begin{document}
\begin{enumerate}[label=\Alph*)]
\def\fa{$x = y^2 + 4y + 13$}
\def\fb{$x = 2\left(y + 1\right)^2 + 4$}
\def\fc{$y = 2\left(x + 1 \right)^2 - 4$}
\def\fd{$y = -\sqrt{\dfrac{x-4}{2}}+2$}
\def\vph{\vphantom{\fa\fb\fc\fd}}
\item\fa\vph
\item\fb\vph
\item\fc\vph
\item\fd\vph
\end{enumerate}
\end{document}
从图中可以看出,使用最大的公式会浪费大量垂直空间,因为第四个公式的深度很大,与公式之间的间距无关。可以通过以下方法解决此问题:
\documentclass{article}
\usepackage{enumitem}
\usepackage{mathtools}
\begin{document}
\begin{enumerate}[label=\Alph*)]
\def\fa{$x = y^2 + 4y + 13$}
\def\fb{$x = 2\left(y + 1\right)^2 + 4$}
\def\fc{$y = 2\left(x + 1 \right)^2 - 4$}
\def\fd{$y = -\sqrt{\dfrac{x-4}{2}}+2$}
\def\vph{\vphantom{\smash[b]{\fa\fb\fc\fd}}}
\item\fa\vph
\item\fb\vph
\item\fc\vph
\item\fd\vph
\end{enumerate}
\end{document}
如上例所示,对所有公式使用相同的最大高度和深度的做法通常会浪费空间。更好的目标是优化公式之间的空间,即深度与以下高度的总和,换句话说\baselineskip
。
可以利用 TeX 的行距算法:如果两行太窄(\lineskiplimit
),则 TeX 不会使用\baselineskip
来实现均匀间距,而是插入\lineskip
。以下算法使用不同的 来设置两次 ,以\lineskip
检测不均匀间距。然后,\baselineskip
增加 ,直到它足够大以实现均匀间距。
采用这种方式时,代码中不应该设置
\baselineskip
或者\lineskip
明确要求间隔均匀,否则优化会失败。
\documentclass{article}
\usepackage{enumitem}
\usepackage{mathtools}
\makeatletter
\newif\ifEvenSpacing@Uneven
\newcommand*{\EvenSpacing}[1]{%
\par
\begingroup
\EvenSpacing@Try{#1}%
\@whilesw\ifEvenSpacing@Uneven\fi{%
\advance\baselineskip by .1pt
\advance\normalbaselineskip by .1pt
\EvenSpacing@Try{#1}%
}%
#1\par
\endgroup
}
\newcommand*{\EvenSpacing@Try}[1]{%
\lineskip=0pt
\normallineskip=0pt
\settototalheight{\dimen0}{\parbox{\linewidth}{#1}}%
\lineskip=1pt
\normallineskip=1pt
\settototalheight{\dimen2}{\parbox{\linewidth}{#1}}%
\ifdim\dimen0=\dimen2
\EvenSpacing@Unevenfalse
\else
\EvenSpacing@Uneventrue
\fi
}
\makeatother
\begin{document}
\EvenSpacing{\begin{enumerate}[label=\Alph*)]
\item $x = y^2 + 4y + 13$
\item $x = 2\left(y + 1\right)^2 + 4$
\item $y = 2\left(x + 1 \right)^2 - 4$
\item $y = -\sqrt{\dfrac{x-4}{2}}+2$
\end{enumerate}}
\end{document}
可以通过使用指数搜索来改进算法,直到\baselineskip
太大。然后,二分搜索找到最佳的
\baselineskip
。