如何解析维度字符串并将其转换为维度值

Arn*_*ter 19 android android-layout

我正在寻找一种方法来动态地将String转换为"30dp"类似于像素数量的int.这意味着StaticClass.theMethodImSearchingFor("16px")会回来16.
我的应用程序将动态获取这些字符串,我需要一种方法将其存储为像素值,以便以后使用.
我已经看过了Android源代码,主要是类Resources,TypedArrayTypedValue,但我找不到任何有用的东西.

Cat*_*ata 55

如果您需要android资源维度作为int,您可以在您的代码中执行此操作:

context.getResources().getDimensionPixelSize(R.dimen.your_dimen_res);
Run Code Online (Sandbox Code Playgroud)


min*_*iot 15

我自己需要这个,所以我写了一个类来处理它.本答案中的所有代码均在Apache License 2.0下获得许可.请享用.

有两种静态方法可以模仿两种TypedValue方法.DimensionConverter.stringToDimension()模仿TypedValue.complexToDimension.DimensionConverter.stringToDimensionPixelSize()模仿TypedValue.complexToDimensionPixelSize.

支持所有当前单位.将接受像"33sp","44 dp"这样的维度字符串,并为不良格式抛出异常.

使用简单:

String dimension = "38dp";
Log.i(TAG, "Testing: " + dimension);
try {
    Log.i(TAG, "Converts to: " + DimensionConverter.stringToDimension(dimension, resources.getDisplayMetrics()));
} catch (NumberFormatException exception) {
    Log.i(TAG, "Unable to convert.");
}
Run Code Online (Sandbox Code Playgroud)

这里的课程:

public class DimensionConverter {

    // -- Initialize dimension string to constant lookup.
    public static final Map<String, Integer> dimensionConstantLookup = initDimensionConstantLookup();
    private static Map<String, Integer> initDimensionConstantLookup() {
        Map<String, Integer> m = new HashMap<String, Integer>();  
        m.put("px", TypedValue.COMPLEX_UNIT_PX);
        m.put("dip", TypedValue.COMPLEX_UNIT_DIP);
        m.put("dp", TypedValue.COMPLEX_UNIT_DIP);
        m.put("sp", TypedValue.COMPLEX_UNIT_SP);
        m.put("pt", TypedValue.COMPLEX_UNIT_PT);
        m.put("in", TypedValue.COMPLEX_UNIT_IN);
        m.put("mm", TypedValue.COMPLEX_UNIT_MM);
        return Collections.unmodifiableMap(m);  
    }
    // -- Initialize pattern for dimension string.
    private static final Pattern DIMENSION_PATTERN = Pattern.compile("^\\s*(\\d+(\\.\\d+)*)\\s*([a-zA-Z]+)\\s*$");

    public static int stringToDimensionPixelSize(String dimension, DisplayMetrics metrics) {
        // -- Mimics TypedValue.complexToDimensionPixelSize(int data, DisplayMetrics metrics).
        InternalDimension internalDimension = stringToInternalDimension(dimension);
        final float value = internalDimension.value;
        final float f = TypedValue.applyDimension(internalDimension.unit, value, metrics);
        final int res = (int)(f+0.5f);
        if (res != 0) return res;
        if (value == 0) return 0;
        if (value > 0) return 1;
        return -1;
    }

    public static float stringToDimension(String dimension, DisplayMetrics metrics) {
        // -- Mimics TypedValue.complexToDimension(int data, DisplayMetrics metrics).
        InternalDimension internalDimension = stringToInternalDimension(dimension);
        return TypedValue.applyDimension(internalDimension.unit, internalDimension.value, metrics);
    }

    private static InternalDimension stringToInternalDimension(String dimension) {
        // -- Match target against pattern.
        Matcher matcher = DIMENSION_PATTERN.matcher(dimension);
        if (matcher.matches()) {
            // -- Match found.
            // -- Extract value.
            float value = Float.valueOf(matcher.group(1)).floatValue();
            // -- Extract dimension units.
            String unit = matcher.group(3).toLowerCase();
            // -- Get Android dimension constant.
            Integer dimensionUnit = dimensionConstantLookup.get(unit);
            if (dimensionUnit == null) {
                // -- Invalid format.
                throw new NumberFormatException();
            } else {
                // -- Return valid dimension.
                return new InternalDimension(value, dimensionUnit);
            }
        } else {
            // -- Invalid format.
            throw new NumberFormatException();
        }        
    }

    private static class InternalDimension {
        float value;
        int unit;

        public InternalDimension(float value, int unit) {
            this.value = value;
            this.unit = unit;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信String unit = matcher.group(2).toLowerCase(); 应更改为String unit = matcher.group(3).toLowerCase(); (2认同)

Phi*_*hil 0

链接可能会帮助您计算出转换结果,但是由于像素和与密度无关的像素不是 1:1 的匹配,因此预计会出现一些(轻微的)扭曲。

这些单位 (dp) 是相对于 160 dpi 屏幕而言的,因此 1 dp 是 160 dpi 屏幕上的一个像素。dp与像素的比例会随着屏幕密度的变化而变化,但不一定成正比。