使用 \only 和 \enumerate 自动覆盖规范

使用 \only 和 \enumerate 自动覆盖规范

有时,当项目列表太长而无法在幻灯片上容纳时,我会执行以下操作以获得更好的效果(暂时忽略注释行):

\documentclass[t,10pt]{beamer}
\setbeamertemplate{navigation symbols}{}
\setbeamercovered{transparent}

\begin{document}
\begin{frame}
%\begin{itemize}[<+->] \item a \item b \end{itemize}    
\begin{enumerate}
 \only<1-2>{
     %\item We agree that
     \item<1>[1.] all men
     \item<2>[2.] are
 }\only<3->{
     \item<3>[3.] equal
 }
\end{enumerate}
\end{frame}
\end{document}

得出的结果为: http://i52.tinypic.com/1zvfnt0.png

不幸的是,这种构造不是很强大,从某种意义上说,在取消注释其中一行或两行注释后,我将不得不手动更改项目的编号和覆盖规范。

问题:如果不进行任何手动编号或覆盖指定,是否可以实现相同的结果?

(进一步评论:我试图解决这个问题,这是我得到的答案:

\begin{enumerate}[<+->]
 \only<.(1)-.(2)>{
   \item All men
   \item are
 }\only<.(3)>{
   \item[3.] equal
 }
 \end{enumerate}

不幸的是,仍然有很多神奇的数字,我仍然必须手动计算\items每个数字包含多少个 s 。除此之外,LaTeX 会在没有一个s 处于活动状态的幻灯片上\only抱怨缺失\item\only

\clearenumerate例如,如果有一个命令可以产生上述结果(可能要对枚举环境进行一些重大改变),那么将会非常方便:

\begin{enumerate}[<+->]
  \item all men
  \item are
  \clearenumerate
  \item equal
\end{enumerate}

但我假设这样的事情,如果可能的话,需要大量的 TeX/LaTeX 掌握。)

答案1

这是一个使用环境特性的解决方案onlyenv:它排版其内容,然后扔掉。这意味着即使没有显示任何任务,任务也会执行。因此,通过将第一个\items 放入onlyenv环境中,它们会增加计数器,但(在相关幻灯片上)实际文本会被丢弃。通过的语法,将\items 放入onlyenv环境中变得容易。棘手的部分是正确获取覆盖规范。由于分组,我不得不使用,而我真的不想这样做,这意味着对于迭代列表或在同一框架上使用它的多个列表,这可能不够强大(尽管它确实适用于不同框架上的列表)。也许有人可以稍微改进一下。actionbeamer\gdef

无论如何,这是代码。

\documentclass[t,10pt]{beamer}
%\url{http://tex.stackexchange.com/q/25548/86}
\setbeamertemplate{navigation symbols}{}
\setbeamercovered{transparent}

\def\onlybetween{+-|only@\lbst-\lbend}
\makeatletter
\def\lbend{}
\def\lbst{1}
\newcounter{listbetween}
\def\startlistbetween{%
  \setcounter{listbetween}{0}%
  \gdef\lbst{1}%
  \expandafter\ifx\csname listto\the\value{listbetween}\endcsname\relax
  \gdef\lbend{}%
\else
\expandafter\global\expandafter\let\expandafter\lbend\csname listto\the\value{listbetween}\endcsname
\fi
\def\beamer@defaultospec{<\onlybetween>}%
}

\def\listbetween{%
  \addtocounter{beamerpauses}{-1}%
  \expandafter\xdef\csname listto\the\value{listbetween}\endcsname{\the\value{beamerpauses}}%
  \addtocounter{beamerpauses}{1}%
  \xdef\lbst{\the\value{beamerpauses}}%
  \stepcounter{listbetween}%
  \expandafter\ifx\csname listto\the\value{listbetween}\endcsname\relax
  \gdef\lbend{}%
\else
\expandafter\global\expandafter\let\expandafter\lbend\csname listto\the\value{listbetween}\endcsname
\fi
}
\makeatother

\begin{document}
\begin{frame}
\begin{enumerate}
\startlistbetween
\item first
\item second
\listbetween
\item third
\item fourth
\item fifth
\listbetween
\item sixth
\item seventh
\end{enumerate}
\end{frame}
\begin{frame}
\begin{enumerate}
\startlistbetween
\item first
\item second
\listbetween
\item third
\item fourth
\item fifth
\listbetween
\item sixth
\item seventh
\end{enumerate}
\end{frame}
\end{document}

枚举环境的默认覆盖规范保存在宏中\beamer@defaultospec。幸运的是,对于我们来说,它在读入时不会展开。因此,我们可以嵌入一个宏,稍后再计算。这是控制何时onlyenv停止实际打印其内容的宏。开始时,它被设置为,1-这实际上意味着“始终打印”(请注意,这是此外覆盖规范+-两个都需要满足才能显示项目)。在遍历框架时,我们会记录希望中断的位置,并将其存储在宏中。在第二次遍历框架时(幻灯片 2),我们使用这些宏来决定位何时生效onlyenv

因此,它利用了每次制作新幻灯片时处理框架内容这一事实。在第一次运行(第一张幻灯片)时,我们会记下所有想要打破列表的地方。然后在后续运行中,我们会使用该信息来控制显示。

答案2

一种可能的解决方案(可能不是最自动化的解决方案)是使用一个命令来存储enumi计数器的值,然后使用另一个命令来设置enumi存储的值;使用这种方法您只需在适当的位置发出命令:

\documentclass[t,10pt]{beamer}
\setbeamertemplate{navigation symbols}{}
\setbeamercovered{transparent}

\newcounter{mycntr}
\newcommand\savecntr{\setcounter{mycntr}{\theenumi}}
\newcommand\usecntr{\setcounter{enumi}{\themycntr}}

\begin{document}

\begin{frame}
\begin{enumerate}
 \only<1-2>{
     %\item We agree that
     \item<1> all men
     \item<2> are\savecntr
 }\only<3->{\usecntr
     \item<3> equal,
     \item<4> or not?
 }
\end{enumerate}
\end{frame}

\end{document}

相关内容