我正在寻找一种方法,将"30dp"
之类的字符串动态转换为类似于像素数量的int。这意味着StaticClass.theMethodImSearchingFor("16px")
将返回16
我的应用程序将动态获取这些字符串,我需要一种方法将其存储为像素值,以便以后使用
我已经查看了Android Source code,主要是类Resources
,TypedArray
和TypedValue
,但我找不到任何有用的内容。
答案 0 :(得分:54)
如果您需要android资源维度作为int,您可以在代码中执行此操作:
context.getResources().getDimensionPixelSize(R.dimen.your_dimen_res);
答案 1 :(得分:13)
我自己需要这个,所以我写了一个类来处理它。此答案中的所有代码均在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.");
}
这里的课程:
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;
}
}
}
答案 2 :(得分:1)
感谢mindriot,工作得很好并且是救星。
这是在C#
注意:如果出于某种原因你不能使用Integer类型(vs int)(它将是Mono中的Java Integers),我在所有关联的注释中都留下了使用C#int的代码。只需在您看到的地方交换未注释的Integer代码的注释int代码。
必须使用Integer,以便在检查后缀的Dictionary / Map(TryGetValue)时可以确定是否没有匹配(在这种情况下它将为null;如果使用int,则out param将是0,它对应于地图的第一个条目,显然不起作用。太糟糕了,TryGetValue在没有匹配时没有返回一个negeative值!?)。
public class DimensionConverter
{
// -- Initialize dimension string to constant lookup.
//public static readonly Dictionary<string, int> dimensionConstantLookup = initDimensionConstantLookup();
public static readonly Dictionary<string, Integer> dimensionConstantLookup = initDimensionConstantLookup();
//private static Dictionary<string, int> initDimensionConstantLookup()
private static Dictionary<string, Integer> initDimensionConstantLookup()
{
//Dictionary<string, int> m = new Dictionary<string, int>();
Dictionary<string, Integer> m = new Dictionary<string, Integer>();
m.Add("px", (Integer)((int)ComplexUnitType.Px));
m.Add("dip", (Integer)((int)ComplexUnitType.Dip));
m.Add("dp", (Integer)((int)ComplexUnitType.Dip));
m.Add("sp", (Integer)((int)ComplexUnitType.Sp));
m.Add("pt", (Integer)((int)ComplexUnitType.Pt));
m.Add("in", (Integer)((int)ComplexUnitType.In));
m.Add("mm", (Integer)((int)ComplexUnitType.Mm));
/*m.Add("px", (int)ComplexUnitType.Px);
m.Add("dip", (int)ComplexUnitType.Dip);
m.Add("dp", (int)ComplexUnitType.Dip);
m.Add("sp", (int)ComplexUnitType.Sp);
m.Add("pt", (int)ComplexUnitType.Pt);
m.Add("in", (int)ComplexUnitType.In);
m.Add("mm", (int)ComplexUnitType.Mm);*/
return m;
}
// -- Initialize pattern for dimension string.
private static Regex DIMENSION_PATTERN = new Regex("^\\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);
float value = internalDimension.value;
//float f = TypedValue.ApplyDimension((ComplexUnitType)internalDimension.unit, value, metrics);
float f = TypedValue.ApplyDimension((ComplexUnitType)(int)internalDimension.unit, value, metrics);
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((ComplexUnitType)internalDimension.unit, internalDimension.value, metrics);
return TypedValue.ApplyDimension((ComplexUnitType)(int)internalDimension.unit, internalDimension.value, metrics);
}
private static InternalDimension stringToInternalDimension(String dimension)
{
// -- Match target against pattern.
MatchCollection matches = DIMENSION_PATTERN.Matches(dimension);
if (matches.Count > 0)
{
Match matcher = matches[0];
// -- Match found.
// -- Extract value.
float value = Float.ValueOf(matcher.Groups[1].Value).FloatValue();
// -- Extract dimension units.
string unit = matcher.Groups[3].ToString().ToLower();
// -- Get Android dimension constant.
//int dimensionUnit;
Integer dimensionUnit;
dimensionConstantLookup.TryGetValue(unit, out dimensionUnit);
//if (dimensionUnit == ????)
if (dimensionUnit == null)
{
// -- Invalid format.
throw new NumberFormatException();
}
else
{
// -- Return valid dimension.
return new InternalDimension(value, dimensionUnit);
}
}
else
{
// -- Invalid format.
throw new NumberFormatException();
}
}
private class InternalDimension
{
public float value;
//public int unit;
public Integer unit;
//public InternalDimension(float value, int unit)
public InternalDimension(float value, Integer unit)
{
this.value = value;
this.unit = unit;
}
}
}
答案 3 :(得分:0)
此link可能会帮助您找出转换效果,但由于像素和与密度无关的像素不是1:1的匹配,因此会出现一些(次要的)失真。
这些单位(dp)相对于160 dpi的屏幕,因此一个dp是一个 160 dpi屏幕上的像素。 dp与像素的比率将随之变化 屏幕密度,但不一定是正比例。