[Tex/LaTex] Multiple navigation dots in Beamer for one frame

beamermini-framesnavigationoverlays

I am currently working on a Beamer presentation for which I use the navigation dots. I understood how to generate them using subsections, and if I want to have one dot per frame I found this answer (or I can just add one subsection before each frame.

Now I have some frames with multiple slides (or overlays) using either \only<> or \invisible<> commands. How can I get as many navigation dots as slides (and working properly with the slides)?

Here is a MWE:

\documentclass{beamer}
\usetheme{Copenhagen}
\useoutertheme[compress,subsection=false]{smoothbars}

\begin{document}
\section{First Frames}
\subsection{Frame 1}
\begin{frame}{Frame 1}
\only<1>{Slide 1}
\only<2>{Slide 2}
\end{frame}

\subsection{Frame 2}
\begin{frame}{Frame 2}
\only<1>{Slide 3}
\only<2>{Slide 4}
\end{frame}
\end{document}

And the outputs:

Output

To make things clear: On this example I have only two dots for four slides. How can I get four dots turning on and off properly according to the slides.

NOTE I am aware that it would be possible to redo all the frames to get only one slide per frame but I would like to know if another solution exists.

Best Answer

I wouldn't advise doing that: Overlays are there to realize animations like the step-by-step uncovering of a text, so all the overlays belong to one single logical unit and should only be represented by one mini frame in order not to confuse the audience.

However it is possible to realize your requirements by patching the beamer internals responsible for generating the mini frames:

\documentclass{beamer}
\usetheme{Copenhagen}
\useoutertheme[compress,subsection=false]{smoothbars}

% Multiple navigation dots in Beamer for one frame
% (http://tex.stackexchange.com/a/135999)
\usepackage{forloop}
\makeatletter
\newcounter{miniframe@page}
\newcounter{miniframe@firstslide}
\newcounter{miniframe@lastslide}
\def\miniframe@parserange(#1/#2){\setcounter{miniframe@firstslide}{#1}\setcounter{miniframe@lastslide}{#2}\stepcounter{miniframe@lastslide}}
\def\slideentry#1#2#3#4#5#6{%
  %section number, subsection number, slide number, first/last frame, page number, part number
  \ifnum#6=\c@part\ifnum#2>0\ifnum#3>0%
    \miniframe@parserange(#4)%
    \forloop{miniframe@page}{\value{miniframe@firstslide}}{\value{miniframe@page}<\value{miniframe@lastslide}}{%
      \advance\beamer@xpos by1\relax%
  \hbox to 0pt{%
    \beamer@tempdim=-\beamer@vboxoffset%
    \advance\beamer@tempdim by-\beamer@boxsize%
    \multiply\beamer@tempdim by\beamer@ypos%
    \advance\beamer@tempdim by -.05cm%
    \raise\beamer@tempdim\hbox{%
      \beamer@tempdim=\beamer@boxsize%
      \multiply\beamer@tempdim by\beamer@xpos%
      \advance\beamer@tempdim by -\beamer@boxsize%
      \advance\beamer@tempdim by 1pt%
      \kern\beamer@tempdim
      \global\beamer@section@min@dim\beamer@tempdim
      \hbox{\edef\beamer@goto{{Navigation\theminiframe@page}}\expandafter\hyperlink\beamer@goto{%
          \usebeamerfont{mini frame}%
          \ifnum\c@section=#1%
            \ifnum\c@subsection=#2%
              \usebeamercolor[fg]{mini frame}%
              \ifnum\c@page=\c@miniframe@page%
                \usebeamertemplate{mini frame}%\beamer@minislidehilight%
              \else%
                \usebeamertemplate{mini frame in current subsection}%\beamer@minisliderowhilight%
              \fi%
            \else%
              \usebeamercolor{mini frame}%
              %\color{fg!50!bg}%
              \usebeamertemplate{mini frame in other subsection}%\beamer@minislide%
            \fi%
          \else%
            \usebeamercolor{mini frame}%
            %\color{fg!50!bg}%
            \usebeamertemplate{mini frame in other subsection}%\beamer@minislide%
          \fi%
        }}}\hskip-10cm plus 1fil%
  }}\fi\fi%
  \else%
  \fakeslideentry{#1}{#2}{#3}{#4}{#5}{#6}%
  \fi\ignorespaces
  }
\makeatother

\begin{document}
\section{First Frames}
\subsection{Frame 1}
\begin{frame}{Frame 1}
\only<1>{Slide 1}
\only<2>{Slide 2}
\end{frame}

\subsection{Frame 2}
\begin{frame}{Frame 2}
\only<1>{Slide 3}
\only<2>{Slide 4}
\end{frame}
\end{document}

output of page 2 (slide 1, overlay 2)

Explanation of the code

The internal beamer macro \slideentry (beamerbasenavigation.sty, ll. 661-707) is modified to generate one mini frame per frame/overlay instead of only one for each slide. This is done by reading the first and last page of the slide supplied in the fourth argument of \slideentry (l. 16) and looping over this page range in a \forloop (ll. 17-52). The rest of the code is largely unmodified, apart from the generation of the link (l. 31) and the check whether to highlight the currently generated mini frame (l. 36). Note that the code only works with the compress option (that means you won't get a line break in the mini frames after each subsection).