java 实现字符串自动换行(根据像素大小)
方法一:使用graphics2d绘图的方式实现
方法一会根据环境的字体来实现,如果是linux环境会出现异常
import lombok.extern.slf4j.Slf4j;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Description:根据像素大小字符串实现换行
* @date 2022-12-03 11:08
*/
@Slf4j
public class SubStrUtil {
private static int index = 0;
/**
* 1、根据宽度截取字符串
*
* @param text 文本
* @param font 字体
* @param appointRow 行数
* @param map 结果集
* @param rows 行号
* @param lineHeight 行高
* @param maxWith 行宽
*/
public static Map<String, Object> creatMyImage(String text, Font font, int appointRow, Map<String, Object> map, int rows, int lineHeight, int maxWith) {
index = 0;
BufferedImage bufferedImage = new BufferedImage(595, 842, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2d = bufferedImage.createGraphics();
graphics2d.setColor(new Color(37, 37, 37));
graphics2d.setFont(font);
graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
map = myDrawString(graphics2d, text, lineHeight, maxWith, appointRow, 0, 0, map, rows);
return map;
}
/**
* 2、根据宽度截取字符串
*
* @param graphics2d
* @param text 文本
* @param lineHeight 行高
* @param maxWidth 行宽
* @param maxLine 最大行数
* @param left 左边距
* @param top 上边距
*/
private static Map<String, Object> myDrawString(Graphics2D graphics2d, String text, int lineHeight, int maxWidth,
int maxLine, int left, int top, Map<String, Object> map, int rows) {
if (text == null || text.length() == 0) {
return map;
}
FontMetrics fm = graphics2d.getFontMetrics();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char strChar = text.charAt(i);
sb.append(strChar);
int stringWidth = fm.stringWidth(sb.toString());
if (i < 3) {
log.error("i:" + i);
log.error("stringWidth:" + stringWidth);
log.error("text:" + text);
log.error("sb.toString():" + sb.toString());
log.error("--------------------------------------------------------------");
}
int strLength = text.substring(0, i).length();
if (strLength >= 53 || strChar == '\n' || stringWidth >= maxWidth) {
if (strChar == '\n') {
i += 1;
}
if (maxLine > 1) {
rows = rows + 1;
char value = ' ', value1 = ' ';
try {
value = text.substring(i).charAt(0);
value1 = text.substring(i - 1).charAt(0);
} catch (Exception e) {
/*e.printStackTrace();*/
System.err.println("----" + e.getMessage());
}
if (isChinesePunctuation(value) && checkCharCN(value1)) {
map.put("row" + rows, text.substring(0, i - 1));
myDrawString(graphics2d, text.substring(i - 1), lineHeight, maxWidth, maxLine - 1, left, top + lineHeight, map, rows);
} else {
map.put("row" + rows, text.substring(0, i));
myDrawString(graphics2d, text.substring(i), lineHeight, maxWidth, maxLine - 1, left, top + lineHeight, map, rows);
}
map.put("index", index);
} else {
rows = rows + 1;
map.put("row" + rows, text.substring(0, i));
index = index + i;
map.put("index", index);
}
return map;
}
}
map.put("remainingText", sb);
return map;
}
// 2.1 判断字符是否是中文
public static boolean checkCharCN(char c) {
String s = String.valueOf(c);
String regex = "[\u4e00-\u9fa5]";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
return m.matches();
}
// 2.2 判断字符是否是中文标点符号
public static boolean isChinesePunctuation(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
|| ub == Character.UnicodeBlock.VERTICAL_FORMS) {
return true;
} else {
return false;
}
}
}
方法二:根据字体的具体像素和屏幕像素实现
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Description:根据像素大小字符串实现换行
* @date 2022-12-03 11:08
*/
@Slf4j
public class SubStrUtil {
public static String Substr(Map parm, double screenWith) {
String text = StringUtil.doString(parm, "text");
//占位符
String placeholder1 = StringUtil.doString(parm, "placeholder1");
String placeholder2 = StringUtil.doString(parm, "placeholder2");
//统计字符串像素
double num = 0;
int startIndex = 0;
int endIndex = 0;
int textLength = text.length();
int countLine = 0;
StringBuilder result = new StringBuilder();
for (int i = 0; i < textLength; i++) {
if (num >= screenWith) {
if (countLine == 0) {
String substring = text.substring(startIndex, endIndex);
result.append(placeholder1 + substring + "</br>");
countLine = i;
startIndex = i;
num = 0;
} else {
String substring = text.substring(startIndex, endIndex);
result.append(placeholder2 + substring + "</br>");
countLine = i;
startIndex = i;
num = 0;
}
} else if ((num < screenWith) && (i == textLength - 1)) {
if (countLine == 0) {
String substring = text.substring(startIndex, endIndex + 1);
result.append(placeholder1 + substring + "</br>");
countLine = i;
startIndex = i;
} else {
String substring = text.substring(startIndex, endIndex + 1);
result.append(placeholder2 + substring + "</br>");
countLine = i;
startIndex = i;
}
}
double resultNum = countCharPx(text.charAt(i));
endIndex = i + 1;
num += resultNum;
}
return result.toString();
}
/**
* 说明:默认字体为【font-family: 方正楷体简体; font-size: 11.0pt; font-weight: 400;】
* <p>
* 汉字:[19968,40869]
* 数字:[48,57]
* 大写字母:[65,90]
* 小写字母:[97-122]
* 连字符-:45
* 圆括号:40,41
* 全角圆括号(中文括号):65288,65289
* 英文逗号 44
* 英文句号 46
* 中文逗号 65292
*
* @param chars 单个字符
* @return
*/
public static double countCharPx(char chars) {
double maxWith = 0;
//中文标点(包含中文文字)所占像素大小
double chineseSymbolsPx = 14.67;
//英文标点所占像素大小
double englishSymbolsPx = 3.56;
//数字所占像素大小
double numPx = 8.61;
//连接符所占像素大小
double linePx = 6.34;
//大写字母所占像素大小
double upperCharPx = 10.33;
//小写字母所占像素大小
double lowerCharPx = 8.11;
//其他符号所占像素大小
double otherSymbolsPx = 9.36;
//中文标点符号合集
List chineseSymbols = Arrays.asList(8211, 8212, 8216, 8217, 8220, 8221,
8230, 12289, 12290, 12296, 12297, 12298,
12299, 12300, 12301, 12302, 12303, 12304,
12305, 12308, 12309, 65281, 65288, 65289,
65292, 65294, 65306, 65307, 65311);
int charType = (int) chars;
if (chineseSymbols.contains(charType) || (charType >= 19968 && charType <= 40869)) {
//汉字/中文标点
maxWith = chineseSymbolsPx;
} else if (charType >= 48 && charType <= 57) {
//数字
maxWith = numPx;
} else if (charType >= 65 && charType <= 90) {
//大写字母
maxWith = upperCharPx;
} else if (charType >= 97 && charType <= 122) {
//小写字母
maxWith = lowerCharPx;
} else if (charType == 44 || charType == 46) {
//英文逗号/句号
maxWith = englishSymbolsPx;
} else {
maxWith = otherSymbolsPx;
}
return maxWith;
}
}