1,px,dp的转换
ldpi:mdpi:hdpi:xhdpi=120:160:240:320=3:4:6:8
在mdpi下,1dp=1px
UI切图按照hdpi设计,设计图上标注px,要先除以1.5换算成dp,存放在dimens.xml里 <dimen name="width">18dip</dimen>
然后getResourses().getDimensionPixelSize(R,dimens.width)会通过方法TypedValue.complexToDimensionPixelSize(int data,DisplayMetrics metrics)调用
TypedValue.applyDimension(int unit, float value,DisplayMetrics metrics)方法将dimens里的数据根据设备的dpi转换成px
public static int complexToDimensionPixelSize(int data, DisplayMetrics metrics) { final float value = complexToFloat(data); final float f = applyDimension( (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 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 applyDimension(int unit, float value, DisplayMetrics metrics) { switch (unit) { case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }
DisplayMetrics.density屏幕密度值为ldpi:0.75 mdpi:1 hdpi:1.5 xhdpi=2,它是将dp换算成px的比例
applyDimension转换将dp转成的px要加上0.5f来修正,因为float强制转换成int是舍去小数部分来取整,而我们需要四舍五入,因此getDimensionPixelSize里要加上0.5f
也可以不用系统给的方法来转换dp和px
public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); }
2,setTextSize
不指定参数类型的方法 public void setTextSize(float size) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}默认的单位是sp,但是我们通过getDimensionPixelSize将dimens里的数据转成了px,因此我们需要这个方法setTextSize(TypedValue.COMPLEX_UNIT_PX,
getDimensionPixelSize(R.dimens.textSize)
另外,getTextSize返回的是px
3,wrapContent
一个长的RelativeLayout的最右侧有一个RelativeLayout控件,这个控件里有一个ImageView和一个TextView,它们在控件里是水平居中,TextView位于控件底部,ImageView位于TextView之上,并且距控件右边的距离是固定的margin_right。RelativeLayout控件和ImageView、TextView宽度都是WrapContent
我原本想的是,通过设置ImageView的layout_marginright来设置图片距右边缘距离,但是实际上RelativeLayout控件的宽度被先放置的TextView的宽度限定了,结果TextView占满宽度靠上了边缘,而ImageView的margin_right起不到撑大整个控件的效果,反而有可能为了达到这个margin_right而把图片缩小
解决方法:我根据设计图上的图片宽度和margin_right设计值计算出整个控件应该有的宽度,直接设置了控件宽度值。
4,动态添加布局时,如果是RelativeLayout,要记得给其中的View设置ID,因为RelativeLayout.LayoutParams.addRule(RelativeLayout.ABOVE,xxxView.getId())方法用来设置相对位置时,需要相对的view的ID