我试图避免在分段命令和后面的 tcolorbox 之间出现分页符。对于“普通”框,我可以使用\nopagebreak
,例如在before
选项中:
\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum,needspace}
\tracingpages=1
\begin{document}
\lipsum[1-4]
\section{title}
\begin{tcolorbox}[before=\nopagebreak,
%breakable, %
]
\rule{1cm}{10\baselineskip}
\lipsum[1]
\end{tcolorbox}
\end{document}
但如果我激活该breakable
选项,这将失败。有一个我无法识别的断点。有人知道它在哪里以及我如何抑制它吗?\Needspace
有帮助,但必须知道 tcolorbox 开头的对象的大小。
答案1
以下补丁可用于
tcolorbox
版本3.32
及之前的版本。它已整合到tcolorbox
版本3.33 (2014/12/11)
及更高版本。要恢复之前的旧行为,可以应用3.33
该选项。ignore nobreak
正如我在评论中所写,我担心这个问题没有全局解决方案。但我尝试了一个补丁,它可能对许多用例都有帮助。补丁代码试图估计标题后所需的空间。如果框或框的第一部分很可能不适合当前页面,则应用\vspace{...}\null\vspace{-...}
您的技巧将所有内容(包括标题)移动到下一页。
如果框中包含大量不可破坏的内容(如您的示例所示),则空间估计可能会失败。在这种情况下,会发出警告以检测长文档中的此类问题。一种手动解决方案是将值放大lines before break
以匹配不可破坏的内容。目前,我还没有看到自动方法。
以下代码是一个实验性补丁。如果它被证明是稳定的,我想把它放到正式版本中,但在此之前必须进行许多测试。如果您发现(新的)问题,或者您可以改进它,请随时发表评论。主要部分是\tcb@handle@nobreak
,其余部分是一些略微更改的当前代码。
\documentclass[]{article}
\usepackage[many]{tcolorbox}
\usepackage{lipsum}
\tracingpages=1
\makeatletter
\def\tcb@do@nobreak@warning{%
\tcb@warning{Using nobreak failed. Try to enlarge `lines before break' or set page breaks manually}%
}
\def\tcb@handle@nobreak{%
\tcb@enlbreak@init%
\tcb@breakat@init%
\tcb@comp@h@page%
\tcbdimto\tcb@h@page{\tcb@h@page-\baselineskip}% security surcharge
\tcb@comp@h@total@standalone%
\tcb@check@for@final@box%
\iftcb@final@box%
\else%
\ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
\tcbdimto\tcb@h@page{\tcb@h@page+3\baselineskip}%
\vspace{\tcb@h@page}%
{\parskip\z@\nointerlineskip\noindent}%
\vspace{-\tcb@h@page}%
\fi%
\fi%
}
\def\tcb@prepare@break@operation{%
\let\tcb@nobreak@warning\@empty%
\@ifundefined{columnbreak}{\tcb@multicolfalse}{%
\ifnum\doublecol@number>\z@ %
\tcb@multicoltrue%
\else%
\tcb@multicolfalse%
\fi}%
\ifx\kvtcb@float\@empty%
\if@nobreak%
\tcb@handle@nobreak%
\let\tcb@nobreak@warning\tcb@do@nobreak@warning%
\else%
\kvtcb@beforebox%
\fi%
\def\kvtcb@beforebox{\parskip\z@\nointerlineskip\noindent}%
\noindent% applies parskip
\vskip\lineskip{\parskip\z@\par\vskip\z@}\bgroup\@nobreakfalse\addpenalty\z@\egroup% force update vertical list
\tcb@break@allowedtrue%
\tcb@enlbreak@init%
\else%
\tcb@break@allowedfalse%
\fi%
}
\def\tcb@split@start{%
\tcb@breakat@init%
\tcb@comp@h@page%
% height calculation
\tcb@comp@h@total@standalone%
%
\let\tcb@split@next=\relax%
\tcb@check@for@final@box%
\iftcb@final@box%
\tcb@drawcolorbox@standalone%
\else
\iftcb@break@allowed%
\ifdim\dimexpr\tcb@h@page-\tcb@h@padding-\tcb@h@padtitle<\kvtcb@breakminlines\baselineskip\relax%
\iftcb@multicol\columnbreak\else\pagebreak\fi%
\tcb@nobreak@warning%
\tcb@enlbreak@init\tcb@break@allowedfalse%
\tcb@comp@h@page%
\tcb@check@for@final@box%
\iftcb@final@box%
\tcb@drawcolorbox@standalone%
\else
\let\tcb@split@next=\tcb@split@first%
\fi
\else%
\let\tcb@split@next=\tcb@split@first%
\fi
\else%
\let\tcb@split@next=\tcb@split@first%
\fi%
\fi%
\tcb@split@next%
}
\def\tcb@split@first{%
\setcounter{tcbbreakpart}{1}%
\ifx\kvtcb@float\@empty%
\iftcb@vfillbeforefirst%
\let\tcb@before@first=\vfill%
\else%
\let\tcb@before@first=\@empty%
\fi%
\let\tcb@before@middle=\@empty%
\let\tcb@before@last=\@empty%
\iftcb@multicol%
\long\def\tcb@after@first{\par}% using \columnbreak here kills multicols' algortihm sometimes
\long\def\tcb@after@middle{\par\vfill}%
\else%
\long\def\tcb@after@first{\par\pagebreak\tcb@enlbreak@next}%
\long\def\tcb@after@middle{\par\vfill\eject\tcb@enlbreak@next}%
\fi%
\let\tcb@after@last=\par%
\else%
\edef\tcb@before@first{\noexpand\tcb@float@env@begin{tcbfloat}[\kvtcb@float]\noexpand\kvtcb@everyfloat}%
\let\tcb@before@middle=\tcb@before@first%
\let\tcb@before@last=\tcb@before@first%
\let\tcb@after@first=\tcb@float@env@end%
\let\tcb@after@middle=\tcb@float@env@end%
\let\tcb@after@last=\tcb@float@env@end%
\fi%
%
\edef\kvtcb@skin@@first{\kvtcb@skin@first}%
\edef\kvtcb@skin@@middle{\kvtcb@skin@middle}%
\edef\kvtcb@skin@@last{\kvtcb@skin@last}%
%
\let\tcb@h@breaksep@first=\kvtcb@bottomsep%
\tcbdimto\tcb@h@breaksep@middle{\kvtcb@bottomsep+\kvtcb@topsep}%
\let\tcb@h@breaksep@last=\kvtcb@topsep%
\tcbdimto\tcb@h@padding@first{\kvtcb@bbtop@stand+\kvtcb@bbbottom@break+\kvtcb@top@rule@stand+\kvtcb@bottom@rule@break+\tcb@h@breaksep@first+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
\tcbdimto\tcb@h@padding@middle{\kvtcb@bbtop@break+\kvtcb@bbbottom@break+\kvtcb@top@rule@break+\kvtcb@bottom@rule@break+\tcb@h@breaksep@middle+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
\tcbdimto\tcb@h@padding@last{\kvtcb@bbtop@break+\kvtcb@bbbottom@stand+\kvtcb@top@rule@break+\kvtcb@bottom@rule@stand+\tcb@h@breaksep@last+\kvtcb@boxsep*2+\kvtcb@top+\kvtcb@bottom}%
%
\tcb@split@setstate@first%
%
\splittopskip=0pt%
\splitmaxdepth=0pt%
\edef\tcb@thevfuzz{\the\vfuzz}%
\edef\tcb@thevbadness{\the\vbadness}%
%
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
%
\let\tcb@split@next=\relax%
\tcbdimto\tcb@split@dim{\tcb@h@page-\tcb@h@padding@first-\tcb@h@padtitle}%
\ifdim\tcb@split@dim<\tcb@h@upper\relax%
\tcb@split@upper@box%
\ifdim\wd\tcb@totalupperbox=0pt\relax%
\iftcb@lowerspace%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@SL%
\else%
\tcb@split@force@standalone%
\tcb@drawcolorbox@standalone%
\fi%
\else%
\ifdim\dimexpr\tcb@h@upper=0pt\relax%
\iftcb@break@allowed
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcb@swap{\tcb@totallowerbox}{\tcb@lowerbox}%
\tcbdimto\tcb@h@upper{\ht\tcb@upperbox+\dp\tcb@upperbox}%
\tcbdimto\tcb@h@lower{\ht\tcb@lowerbox+\dp\tcb@lowerbox}%
\iftcb@multicol\columnbreak\else\pagebreak\fi%
\tcb@nobreak@warning%
\tcb@enlbreak@init\tcb@break@allowedfalse%
\let\tcb@split@next=\tcb@split@start%
\else%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\else%
\tcb@sdraw@U%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\fi%
\else%
\tcb@swap{\tcb@totalupperbox}{\tcb@upperbox}%
\tcbdimto\tcb@split@dim{\tcb@split@dim-\tcb@h@upper-\tcb@h@segment}
\ifdim\tcb@split@dim<\kvtcb@breakminlines\baselineskip\relax%
\tcb@sdraw@U%
\iftcb@lowerspace%
\let\tcb@split@next=\tcb@split@SL%
\else%
\let\tcb@split@next=\tcb@split@USL%
\fi%
\else
\tcb@split@lower@box%
\ifdim\wd\tcb@totallowerbox=0pt\relax%
\tcb@split@force@standalone%
\tcb@drawcolorbox@standalone%
\else%
\tcb@sdraw@USL%
\let\tcb@split@next=\tcb@split@L%
\fi%
\fi%
\fi%
\tcb@split@next%
}
\makeatother
\begin{document}
\lipsum[1-4]
\section{title}
\begin{tcolorbox}[enhanced,breakable,%
lines before break=10,% commenting this issues a warning
]
\rule{1cm}{10\baselineskip}
\lipsum[1]
\end{tcolorbox}
\clearpage
\lipsum[1-4]
\rule{1cm}{6mm}
\section{Normal case}%
\begin{tcolorbox}[enhanced,breakable]
\lipsum[1]
\end{tcolorbox}
\end{document}