Using the following code I could put the ToC lines in the center in beamer
:
\begin{frame}
\begin{center}
\tableofcontents
\end{center}
\end{frame}
But how to make these ToC lines left aligned and still in the center?
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityUsing the following code I could put the ToC lines in the center in beamer
:
\begin{frame}
\begin{center}
\tableofcontents
\end{center}
\end{frame}
But how to make these ToC lines left aligned and still in the center?
A small calculation could advance the margins sufficiently to obtain the centered & left-aligned \tableofcontents
display.
\documentclass{beamer}% http://ctan.org/pkg/beamer
\newsavebox{\longestsec}% Box to save longest sectional heading
\begin{document}
\begin{frame}
\frametitle{Table of contents}
\begin{lrbox}{\longestsec}Last section in the presentation\end{lrbox}% Capture longest title
\setlength{\leftskip}{\dimexpr.5\textwidth-.5\wd\longestsec\relax}% Advance left margin accordingly
\tableofcontents
\end{frame}
\section{First section}
\begin{frame}
\frametitle{First slide}
This is a slide.
\end{frame}
\section{Last section in the presentation}% Longest sectional title
\begin{frame}
\frametitle{Another slide}
This is another slide
\end{frame}
\end{document}
The reason for this round-about way is because beamer
collapses the spacing when putting \tableofcontents
within a minipage
or varwidth
(from the varwidth
package).
Here is an automated way of capturing the width of the longest section:
\documentclass{beamer}% http://ctan.org/pkg/beamer
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\makeatletter
\newlength{\secnamelength}
\newsavebox{\longestsec}% Box to save longest sectional heading
\patchcmd{\beamer@section}% <cmd>
{\beamer@savemode}% <search>
{\begin{lrbox}{\longestsec}#1\end{lrbox}%
\ifdim\wd\longestsec>\secnamelength\relax\setlength{\secnamelength}{\wd\longestsec}\fi%
\beamer@savemode}% <replace>
{}{}% <success><failure>
\AtEndDocument{% http://tex.stackexchange.com/q/137495/5764
\immediate\write\@auxout{\global\secnamelength=\the\secnamelength}%
}
\makeatother
\begin{document}
\begin{frame}
\frametitle{Table of contents}
\setlength{\leftskip}{\dimexpr.5\textwidth-.5\secnamelength\relax}% Advance left margin accordingly
\tableofcontents
\end{frame}
\section{First section}
\begin{frame}
\frametitle{First slide}
This is a slide.
\end{frame}
\section{Last section in the presentation}% Longest sectional title
\begin{frame}
\frametitle{Another slide}
This is another slide
\end{frame}
\end{document}
The above stores the length of the longest section in \secnamelength
that is written to the .aux
at the end of the document. A patch of \beamer@section
(with the aid of etoolbox
is necessary to grab the maximum length of a section name and drop it into the .aux
\AtEndDocument
so it can be retrieved in a successive run.
By patching \beamer@sectionintoc
command, I could use varwidth
inside center
environment to make ToC lines left aligned and in the center.
The only limitation of this solution is, ToC lines could not be wrapped.
\documentclass{beamer}
\usepackage{varwidth}
\usepackage{etoolbox}
\makeatletter
%\patchcmd{\beamer@sectionintoc}{\vskip1.5em}{\vskip0.5em}{}{}
\patchcmd{\beamer@sectionintoc}{%
\hbox{\vbox{%
\def\beamer@breakhere{\\}%
\beamer@tocact{\ifnum\c@section=#1\beamer@toc@cs\else\beamer@toc@os\fi}{section in toc}}}%
}{%
\hbox{%
\def\beamer@breakhere{}%
\beamer@tocact{\ifnum\c@section=#1\beamer@toc@cs\else\beamer@toc@os\fi}{section in toc}}%
}{}{}
\makeatother
\setbeamertemplate{section in toc}[sections numbered]
\begin{document}
\begin{frame}
\frametitle{Table of contents}
\begin{center}
\begin{varwidth}{\textwidth}
\tableofcontents[sectionstyle=show,subsectionstyle=hide]
\end{varwidth}
\end{center}
\end{frame}
\section{First section}
\begin{frame}
\frametitle{First slide}
This is a slide.
\end{frame}
\section{Second section in the presentation}
\begin{frame}
\frametitle{Another slide}
This is another slide.
\end{frame}
\section{Last section}
\begin{frame}
\frametitle{Last slide}
This is the last slide.
\end{frame}
\end{document}
\vfill
s between the sections back? For some reason they are gone after using the patch. I have tried adding it back manually by inserting it into the second clause of the patch etc. but that apparently makes either the patch not applying (is there no warning?) or it does not work.
As shown in my comment, the automatism provided by Werner can be problematic if you have short names like \section[shortName]{longName}
e.g. for beamer slide headlines. It always takes the first argument, which would then be the short name.
I implemented a quick solution now (with etoolbox
and ifthen
), which will take the second argument if provided:
\makeatletter
\newlength{\secnamelength}
\newsavebox{\longestsec}% Box to save longest sectional heading
\patchcmd{\beamer@section}% <cmd>
{\beamer@savemode}% <search>
{
\ifstrempty{#2}{%
\begin{lrbox}{\longestsec}#1\end{lrbox}
\ifthenelse{
\wd\longestsec > \secnamelength
}{
\setlength{\secnamelength}{\wd\longestsec}
}{}%else
}{
\begin{lrbox}{\longestsec}#2\end{lrbox}
\ifthenelse{
\wd\longestsec > \secnamelength
}{
\setlength{\secnamelength}{\wd\longestsec}
}{}%else
}
\beamer@savemode
}% <replace>
{}{}% <success><failure>
\AtEndDocument{% http://tex.stackexchange.com/q/137495/5764
\immediate\write\@auxout{\global\secnamelength=\the\secnamelength}%
}
\makeatother
\tableofcontents
inside aminipage
-environment which can be centered via\centering
.