2

I have been using LaTeX beamer for my presentations for some time. My standard slide layout consists of bullet-points on one side, with a 'hook' image on the other. To keep visual interest, I alternate the columns between slides.

A minimal code snippet looks like this:

\documentclass[a4paper]{beamer}

\usepackage{graphicx}

\title{My Title}
\author{Me}
\begin{document}

\maketitle

\begin{frame}    
\begin{columns}
\begin{column}[c]{7cm}
\begin{itemize}
   \item Point One
   \item Point Two
\end{itemize}
\end{column}
\begin{column}[c]{3cm}
\includegraphics[width=3cm]{stock/default.png}
\end{column}
\end{columns}
\end{frame}

\begin{frame}
\begin{columns}
\begin{column}[c]{3cm}
\includegraphics[width=3cm]{stock/default.png}
\end{column}
\begin{column}[c]{7cm}
\begin{itemize}
   \item Point Three
   \item Point Four
\end{itemize}
\end{column}
\end{columns}
\end{frame}


\end{document}

Obviously, for longer presentations this alternation can be annoying to code. Also, inserting or removing a slide from the presentation means that the rest of the slides have to be manually realigned. (At the moment I mainly use a vim macro to do it.)

Is there any way to have a variable or parameter that would automatically toggle to correctly swap the columns from slide to slide? I've toyed with the idea of defining a new frame type that takes an 'alignment' argument as well as the relevant text and images, but how to do that, and whether a persistent 'variable' can be kept and set in a LaTeX document, is a significant leap beyond my existing LaTeX knowledge.

migrated from stackoverflow.com Jun 25 '14 at 15:55

This question came from our site for professional and enthusiast programmers.

1

You can collect the contents of the image column using an environment like imagecolumn and the text column using textcolumn, and then print the columns via \printcolumns as specified below:

enter image description here

\documentclass{beamer}
\usepackage{environ}
\title{My Title}
\author{Me}

\newlength{\imagecolwidth}\setlength{\imagecolwidth}{3cm}
\newlength{\textcolwidth}\setlength{\textcolwidth}{7cm}

\makeatletter
\NewEnviron{imagecolumn}{\expandafter\gdef\expandafter\imagecolcontent\expandafter{\BODY}}
\NewEnviron{textcolumn}{\expandafter\gdef\expandafter\textcolcontent\expandafter{\BODY}}
\newcommand{\printcolumns}{%
  \begin{columns}
    \ifodd\value{page}
      \begin{column}[c]{3cm}
        \imagecolcontent
      \end{column}
      \begin{column}[c]{7cm}
        \textcolcontent
      \end{column}
    \else
      \begin{column}[c]{7cm}
        \textcolcontent
      \end{column}
      \begin{column}[c]{3cm}
        \imagecolcontent
      \end{column}
    \fi
  \end{columns}
}
\makeatother
\begin{document}

\maketitle

\begin{frame}
  \begin{imagecolumn}
    \includegraphics[width=\columnwidth]{example-image-a}
  \end{imagecolumn}
  \begin{textcolumn}
    \begin{itemize}
       \item Point One
       \item Point Two
    \end{itemize}
  \end{textcolumn}

  \printcolumns
\end{frame}

\begin{frame}
  \begin{imagecolumn}
    \includegraphics[width=\columnwidth]{example-image-b}
  \end{imagecolumn}
  \begin{textcolumn}
    \begin{itemize}
       \item Point Three
       \item Point Four
    \end{itemize}
  \end{textcolumn}

  \printcolumns
\end{frame}

\end{document}
  • This seems to do pretty much exactly what I was looking for, although while I'm at it I'd probably be tempted to wrap up the frame definitions into a macro. Just one question -- what are the '\makeatletter' and '\makeatother' commands? (EDIT: latex-community.org/forum/viewtopic.php?f=5&t=3732 seems to answer the question very well.) – tealeaf Jun 26 '14 at 19:14
  • 1
    @user3775311: See What do \makeatletter and \makeatother do? – Werner Jun 26 '14 at 19:22
  • @user3775311: True. I've wrapped it into an environment, but you can do the same via a macro. – Werner Jun 26 '14 at 19:22
1

You can define each type of frame as a macro in the preamble, where each element that may change is an argument. Assuming that for a consistent format you want always columns of the same width, you need only two arguments: #1 the item list and #2 the image. Then, in the body of the document you only need write \yourmacro{\item ... \item ...}{image}. An example:

\documentclass[a4paper]{beamer}
\title{Your Title}
\author{You}
\newcommand\LI[2]{
\begin{frame}    
\begin{columns}
\begin{column}[c]{7cm}
\begin{itemize}#1\end{itemize}
\end{column}
\begin{column}[c]{3cm}
\includegraphics[width=\linewidth]{#2}
\end{column}
\end{columns}
\end{frame}
}
\newcommand\IL[2]{
\begin{frame}
\begin{columns}
\begin{column}[c]{3cm}
\includegraphics[width=\linewidth]{#2}
\end{column}
\begin{column}[c]{7cm}
\begin{itemize} #1 \end{itemize}
\end{column}
\end{columns}
\end{frame}
}

\begin{document}

\maketitle

\LI{\item Point One \item Point Two}{example-image-a} 
\IL{\item Point Three \item Point Four}{example-image-b} 

\end{document}

If you need this work done with only one macro, one solution if make a conditional loop, for example with \iftoggle. A simple example: the next MWE show a macro that macro \OddEven{1}{2} print 12the first time, but the same command print 21 the second time, the third time 12 again, etc.

\documentclass[a4paper]{beamer}
\usepackage{etoolbox}
\newtoggle{FrameChange}
\toggletrue{FrameChange}
\newcommand\OddEven[2]{
%\iftoggle{FrameChange}%
{#1#2\togglefalse{FrameChange}} % if true
{#2#1\toggletrue{FrameChange}}} % if false

\begin{document}
\OddEven{1}{2} 
\OddEven{1}{2} 
\OddEven{1}{2} 
\OddEven{1}{2} 
\OddEven{1}{2} 
\end{document}

Thus, you only need change #1#2 and #2#1 by the whole content of the \LI and \IL macros from the above example:

\documentclass[a4paper]{beamer}
\usepackage{etoolbox}
\newtoggle{FrameChange}
\toggletrue{FrameChange}

\newcommand\OddEven[2]{\iftoggle{FrameChange}{
\begin{frame}    
\begin{columns}
\begin{column}[c]{7cm}
\begin{itemize}#1\end{itemize}
\end{column}
\begin{column}[c]{3cm}
\includegraphics[width=\linewidth]{#2}
\end{column}
\end{columns}
\end{frame}
\togglefalse{FrameChange}}{

\begin{frame}
\begin{columns}
\begin{column}[c]{3cm}
\includegraphics[width=\linewidth]{#2}
\end{column}
\begin{column}[c]{7cm}
\begin{itemize} #1 \end{itemize}
\end{column}
\end{columns}
\end{frame}
\toggletrue{FrameChange}}}

\begin{document}

\OddEven{\item Point One \item Point Two}{example-image-a} 
\OddEven{\item Point Three \item Point Four}{example-image-b} 

\end{document}
  • Thanks! This is almost the sort of thing that I had in mind, but still seems to require manually choosing '\LI' or '\IL'. I think that a wrapper around this that automatically works out which to choose would work well. Some combination of this and Werner's answer will probably sort me out. – tealeaf Jun 26 '14 at 19:12
  • @user3775311, You can convert the two macros in one conditional macro. See the edited answer. – Fran Jun 26 '14 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.