根据您的评论Adjust components basing on devices 中的要求,首先将以下Java 类添加到您的项目中。它包含的内容超出您的需要,您可以根据需要对其进行自定义。最重要的是这条线:int defaultScreenWidth = Display.getInstance().convertToPixels(70);。不言自明:它表示参考尺寸,在本例中为 70mm。
import com.codename1.io.Log;
import com.codename1.ui.CN;
import com.codename1.ui.Display;
import com.codename1.ui.Font;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
/**
*
*
*/
public class CSSUtilities {
// Note: we assume that the only target platforms are native iOS, native Android and Javascript
public static final boolean isAndroidTheme = UIManager.getInstance().isThemeConstant("textComponentOnTopBool", false);
public static final boolean isIOSTheme = !isAndroidTheme;
private static int percentage = calculateAdaptionPercentage();
/**
* Call this method if you need to recalculate the adapting percentage
*/
public static int recalculatePercentage() {
percentage = calculateAdaptionPercentage();
return percentage;
}
/**
* Load multiple CSSes, note that "iOS" css is loaded only if the native iOS
* theme is used, the "Android" css is loaded only if the native Android
* theme is used, the "WebApp" css is loaded only if the app is running on
* Javascript; for info about build.xml:
* https://stackoverflow.com/questions/53480459/multiple-codename-one-css
*
* @param css file names, WITHOUT SLASHES AND WITHOUT .css EXTENSION!!!
*/
public static void loadMultipleCSSes(String... css) {
try {
UIManager.initFirstTheme("/" + css[0]);
Resources resource = Resources.openLayered("/" + css[0]);
UIManager.getInstance().setThemeProps(adaptTheme(resource.getTheme("Theme")));
Resources.setGlobalResources(resource);
Log.p("Loaded " + css[0] + ".css", Log.DEBUG);
if (isIOSTheme) {
Log.p("The currently used native theme is iOS", Log.DEBUG);
}
if (isAndroidTheme) {
Log.p("The currently used native theme is Android", Log.DEBUG);
}
for (int i = 1; i < css.length; i++) {
if (css[i].equals("iOS")) {
if (!isIOSTheme) {
continue;
} else {
Log.p("Loading CSS for iOS native theme only", Log.DEBUG);
}
}
if (css[i].equals("Android")) {
if (!isAndroidTheme) {
continue;
} else {
Log.p("Loading CSS for Android native theme only", Log.DEBUG);
}
}
if (css[i].equals("WebApp")) {
if (!isJavascript()) {
continue;
} else {
Log.p("Loading CSS for web-app only", Log.DEBUG);
}
}
Resources res = Resources.openLayered("/" + css[i]);
if (!css[i].equals("MyController")) {
UIManager.getInstance().addThemeProps(adaptTheme(res.getTheme("Theme")));
} else {
UIManager.getInstance().addThemeProps(res.getTheme("Theme"));
}
Log.p("Loaded " + css[i] + ".css", Log.DEBUG);
}
// Log.p("CssUtilities.loadMultipleCSSes - success, loaded in the order: " + css.toString(), Log.INFO);
} catch (Exception ex) {
Log.p("CssUtilities.loadMultipleCSSes - ERROR", Log.ERROR);
Log.e(ex);
Log.sendLogAsync();
}
}
/**
* Calculate the percentage to adapt the font sizes to the screen width. The
* maximum decrease of the sizes is about 30%, increasing is disabled.
*
* @return percentage from -30 to 0
*/
private static int calculateAdaptionPercentage() {
int defaultScreenWidth = Display.getInstance().convertToPixels(70);
int currentScreenWidth = Display.getInstance().getDisplayWidth();
int currentInMM = currentScreenWidth / Display.getInstance().convertToPixels(1);
int percentage = currentScreenWidth * 100 / defaultScreenWidth - 100;
if (percentage < -30) {
percentage = -30;
} else if (percentage > 0) {
percentage = 0;
}
Log.p("Estimated screen width: " + currentInMM + " mm", Log.INFO);
Log.p("Font percentage: " + percentage + "%", Log.INFO);
return percentage;
}
/**
* Modify a theme changing the font sizes, margins and paddings
*
* @param themeProps
* @return the new theme
*/
private static Hashtable adaptTheme(Hashtable hashtable) {
Hashtable<String, Object> result = new Hashtable<>();
Set<String> keys = hashtable.keySet();
Iterator<String> itr = keys.iterator();
String key;
Object value;
while (itr.hasNext()) {
key = itr.next();
value = hashtable.get(key);
// Log.p("key: " + key + ", value is: " + value.getClass().getName() + ", " + value.toString());
if (value instanceof Font && ((Font) value).isTTFNativeFont() && percentage < 0) {
Font font = (Font) value;
float newSize = (int) (font.getPixelSize() * (100 + percentage) / 100);
result.put(key, font.derive(newSize, font.getStyle()));
} else if (key.endsWith("#margin") || key.endsWith(".margin")
|| key.endsWith("#padding") || key.endsWith(".padding")) {
if (value instanceof String) {
// Log.p("input: " + value);
// Log.p("output: " + resizeMarginPadding((String) value));
result.put(key, resizeMarginPadding((String) value));
}
} else {
result.put(key, value);
}
}
return result;
}
/**
* Returns a resized dimension (like a width or height)
*
* @param size, the unit of measurement (px, mm, pt, etc.) does not matter
* @return
*/
public static int getResized(int size) {
return size * (100 + percentage) / 100;
}
/**
* Returns a resized dimension (like a width or height)
*
* @param size, the unit of measurement (px, mm, pt, etc.) does not matter
* @return
*/
public static float getResized(double size) {
return (float) (size * (100 + percentage) / 100);
}
/**
* Returns a resized dimension (like a width or height)
*
* @param size, the unit of measurement (px, mm, pt, etc.) does not matter
* @param convertToPx if true, convert the given size from mm to pixels
* @return
*/
public static int getResized(int size, boolean convertToPx) {
if (!convertToPx) {
return getResized(size);
} else {
return getResized(Display.getInstance().convertToPixels(size));
}
}
/**
* Resizes the given margin or the padding
*
* @param input in a form like 0.0,1.0,0.9,15.0
* @return the given input if it's not a valid margin or padding, or a new
* String with the margins or paddings recalculated
*/
private static String resizeMarginPadding(String input) {
String result = "";
StringTokenizer st = new StringTokenizer(input, ",");
// Do we have 4 numbers?
if (st.countTokens() == 4) {
while (st.hasMoreTokens()) {
// Is this token a number like 1.5, 0.0, etc.?
String token = st.nextToken();
try {
Float number = Float.valueOf(token);
number = getResized(number);
number = ((int) (number * 10)) / 10.0f;
result += number;
if (st.countTokens() != 0) {
result += ",";
}
} catch (NumberFormatException e) {
return input;
}
}
} else {
return input;
}
return result;
}
/**
* Returns a resized dimension (like a width or height)
*
* @param size, the unit of measurement (px, mm, pt, etc.) does not matter
* @param convertToPx if true, convert the given size from mm to pixels
* @return
*/
public static double getResized(double size, boolean convertToPx) {
if (!convertToPx) {
return getResized(size);
} else {
return getResized(Display.getInstance().convertToPixels((float) size));
}
}
/**
* Returns true if the app is running in the CN1 Simulator
*
* @return
*/
public static boolean isSimulator() {
return Display.getInstance().isSimulator();
}
/**
* Returns true if the app is running as native Android app
*
* @return
*/
public static boolean isAndroidNative() {
return !isSimulator() && "and".equals(CN.getPlatformName());
}
/**
* Returns true if the app is running as native iOS app
*
* @return
*/
public static boolean isiOSNative() {
return !isSimulator() && "ios".equals(CN.getPlatformName());
}
/**
* Returns true if the app is running as Javascript port
*
* @return
*/
public static boolean isJavascript() {
return !isSimulator() && "HTML5".equals(CN.getPlatformName());
}
}
然后,在您的主类中,注释 theme = UIManager.initFirstTheme("/theme"); 行,将其替换为:
// theme = UIManager.initFirstTheme("/theme");
// We assume that CSS support is enabled
CSSUtilities.loadMultipleCSSes("theme");
就是这样。这是一个使用示例:
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("(Recognized) screen width: " + (hi.getWidth() / CN.convertToPixels(1)) + " mm"));
hi.add(new SpanLabel("This text enters a line on a 70mm screen. Do tests."));
hi.add(FontImage.createMaterial(FontImage.MATERIAL_LOCAL_RESTAURANT, "Label", CSSUtilities.getResized(10.0f)));
hi.show();
请注意,识别的宽度不是实际宽度,可能会有所不同:但是,我的代码确保即使在 Codename One 无法正确检测宽度的情况下,文本也会按照您的要求进行调整。
一些注意事项:
此代码有限制,需要垂直锁定方向,仅适用于智能手机屏幕(无平板电脑);
记住Android和iOS的原生字体是不一样的;
此代码会自动调整您在 css 中指定的尺寸,涉及文本、边距和填充(使用 mm 或 pt,1pt 约为 0.35mm);
调整大小不是自动的,在示例代码中我向您展示了如何自动调整图像;
代码被限制为最多减少30%的文本,在我的测试中这很好,前提是默认大小是70mm;
代码永远不会增加文本的大小:同样,我根据我的测试决定了这种行为,你可以随心所欲。
更准确地说,这段代码对我有帮助,尤其是在那些没有正确报告其屏幕密度并因此“愚弄”代号一的设备上。
我希望这对你有用。它在真实设备上比在模拟器上更有用。