[Tex/LaTex] Control the vertical space in multiple choice questions

examspacing

This is the screen shot of my customized multiple choice questions. (I have some modification to the exam class's multiple choice question, so that they can have images, see How can I put a figure to the right of a multiple-choice question? and the four choices are automatically aligned, see How to automatically align the four choices of a multiple choice question in exam?)
enter image description here

You see, there are three vertical spaces need to be adjusted. But I still don't know how to adjust those three spaces. Here is the minimal test code

\documentclass[a4paper, addpoints]{exam}

\usepackage{environ}
\usepackage[normalem]{ulem}
\usepackage{etoolbox}
\usepackage[export]{adjustbox}
\usepackage{enumitem}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% the accumulated answers text
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand{\answertext}{}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% adjust the lengths
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\setlength{\parskip}{1.0cm}
\renewcommand{\baselinestretch}{1.5}
\setlength{\itemsep}{2.0cm}

\renewcommand{\choiceshook}{%
    \setlength{\leftmargin}{10pt}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% True or False questions
%https://tex.stackexchange.com/questions/94374/answerline-to-the-right-of-a-question-with-dot-line-between-answer-line-and-que
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newlength\answerspace
\setlength\answerspace{0.5in}
\newcommand\dottedanswerline[1][{}]{%
% One optional argument, the default value of which is empty.
%\unskip\linebreak[0]\enspace\hbox{}\nobreak\dotfill 
\unskip\nobreak\hfil\allowbreak\hbox{}\enspace\nobreak\dotfill
\ifprintanswers
    \hbox to \answerspace{(\hfil#1\hfil)}%
  \else
    \hbox to \answerspace{(\hfil)}%
    \xappto\answertext{\thequestion,#1\space}%
  \fi
}% dottedanswerline


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% multiply choice questions
% https://tex.stackexchange.com/questions/140923/how-to-automatically-align-the-four-choices-of-a-multiple-choice-question-in-exa
% also it support adding figures in the right corner
% https://tex.stackexchange.com/questions/141870/how-can-i-put-a-figure-to-the-right-of-a-multiple-choice-question
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\newlength\choiceitemwidth
\newif\ifshowsolution \showsolutiontrue
\newcounter{choiceitem}%

\def\thechoiceitem{\Alph{choiceitem}}%
\setlength{\fboxsep}{0pt}
%\def\makechoicelabel#1{#1\uline{\thechoiceitem.}\else\thechoiceitem.\fi\space} %underline the answer item label if we want to print the answer
\def\makechoicelabel#1{#1\framebox[1.25em][l]{\thechoiceitem.}\else\makebox[1.25em][l]{\thechoiceitem.}\fi} %underline the answer item label if we want to print the answer

\def\choice@mesureitem#1{\cr\stepcounter{choiceitem}\makechoicelabel#1}%

%measure the choices, this is the first time we need to parse the \BODY
\def\choicemesureitem{\@ifstar
  {\choice@mesureitem\ifprintanswers \xappto\theanswer{\thechoiceitem}\ignorespaces}%
  {\choice@mesureitem\iffalse}}%

\def\choice@blockitem#1{%
  \ifnum\value{choiceitem}>0\hfill\fi
  \egroup\hskip0pt
  \hbox to \choiceitemwidth\bgroup\hss\refstepcounter{choiceitem}\makechoicelabel#1}

\def\choiceblockitem{\@ifstar
  {\choice@blockitem\ifprintanswers\ignorespaces}%
  {\choice@blockitem\iffalse}}

\def\choice@paraitem#1{%
  \par\noindent\refstepcounter{choiceitem}\makechoicelabel#1\hangindent=1.25em\hangafter=1\relax}% only the first line need indent

\def\choiceparaitem{\@ifstar
  {\choice@paraitem\ifprintanswers\ignorespaces}%
  {\choice@paraitem\iffalse}}


\newdimen\qanswd
\newdimen\qanswdtmp
\newbox\qimgbox
\NewEnviron{items}[1][]{%
  \def\theanswer{}
  \begingroup
    \let\item\choicemesureitem
    \setcounter{choiceitem}{0}%
    \settowidth{\global\choiceitemwidth}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}%
  \endgroup \dottedanswerline[\theanswer]
  \setbox\qimgbox\hbox{#1}%
  \setlist[trivlist]{nosep}
  \trivlist\item\relax%
  \qanswd=\linewidth%
  \advance\qanswd-\wd\qimgbox%
  % handle large images (leaving less than 30% space)
  \qanswdtmp=0.3\linewidth%
  \ifnum\qanswd<\qanswdtmp%
    %\strut\hfill% uncomment to right-align large images
    \unhbox\qimgbox%
    %\hfill\strut% uncomment this too to center them
    \par%
    \qanswd=\linewidth%
    \setbox\qimgbox\hbox{}%
  \fi%
  % end of handling for large images
  \begin{minipage}[t]{\qanswd}
  \trivlist\item\relax%
   \parindent0pt%  
  \setcounter{choiceitem}{0}%
  \ifdim\choiceitemwidth<0.25\columnwidth
    \choiceitemwidth=0.25\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else\ifdim\choiceitemwidth<0.5\columnwidth
    \choiceitemwidth=0.5\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else % \choiceitemwidth > 0.5\columnwidth
    \let\item\choiceparaitem
    \BODY
  \fi\fi
  \endtrivlist
  \end{minipage}%
  \adjustbox{valign=t}{\unhbox\qimgbox}
  \endtrivlist
}
\makeatother


\begin{document}


\section {Multiply Choice Questions}
\begin{questions}
\question 1111 text text text text text text text 
  \begin{items}
    \item foo
    \item bar
    \item*baz
    \item text text text text text text text 
  \end{items}

\question 2222 text text text text text text text text text text text text text text text text text text text
  \begin{items}
    \item*   foo
    \item   bar
    \item   baz
    \item   text
  \end{items}

\end{questions}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ifprintanswers
    % do nothing
\else
    % this print the answertext
    \answertext
\fi

\end{document}

The minimal code may look a bit complex, because the customized item environment has a lot of code.

As I know, change the code

\renewcommand{\baselinestretch}{1.5}

will change the whole three kinds a vertical spaces simultaneously. But I don't know how to adjust them individually. From the sample code, you will see the items were put in a minipage, but any one know how to adjust the margins before and after the minipage?

Thanks.

EDIT

If I follow egreg's advice(in comments), and change the code like below

\setlist[trivlist,1]{ topsep=0cm}
%\setlength{\parskip}{1.0cm}
\renewcommand{\baselinestretch}{0.6}
%\setlength{\itemsep}{2.0cm}

space bug2

But the space before and after the items are still quite big.

If I change to the code below(topsep is -1cm):

\setlist[trivlist,1]{ topsep=-1cm}
%\setlength{\parskip}{1.0cm}
\renewcommand{\baselinestretch}{0.6}
%\setlength{\itemsep}{2.0cm}

Then, I see it get a litter smaller space before the items.
space bug 2

So, I wondering why a -1cm is needed here? I mean I want to know how to exactly control the space before and after the items. Thanks.

EDIT2

I create a minimal test code and try to see how minipage and trivlist work, it looks like I can get the expect space, especially the space between question text and items are quite small, see below the code and the screen shot.

\documentclass{article}
\usepackage{enumitem}
\setlist[trivlist,1]{noitemsep,topsep=0pt,parsep=0pt,partopsep=0pt}
\renewcommand{\baselinestretch}{0.6}
\begin{document}

\noindent Question Question Question Question Question\par
\noindent
\begin{minipage}[t]{10cm}
    \trivlist %
    \item A.abc
    \item B.def
    \endtrivlist
\end{minipage}
\end{document}

This is the screen shot:

space looks quite good

It looks like this pure code does not expose the space issue.

Best Answer

I understand what you don't like in the vertical spaces (marked red). I'm not sure how you want to fix it. The following will make the marked vertical spaces look nice (although my "nice" is not necessarily the same as yours).

\renewcommand{\questionshook}{%
  \setlength{\itemsep}{\baselineskip}
  \addtolength{\itemsep}{-\parsep}
}

screenshot