为什么要进行屏幕适配 ?先说说原理,在说怎么适配
支持Android设备
由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,于是导致:
Android系统碎片化:小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等
当然都是基于Google原生系统定制的
Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920
据友盟指数显示,统计至2016年12月,支持Android的设备共有27796种
屏幕尺寸
含义:手机对角线的物理尺寸
单位:英寸(inch),1英寸=2.54cm
屏幕像素密度
含义:每英寸的像素点数
单位:dpi(dots per ich)
Nexul5 445
10980*1080+1920*1920 开根号 /4.95
1 实际密度与系统密度概念,为什么会有实际密度和系统密度的概念
Nexul5 445dpi
轻金属 轻金属的共同特点是比重小于5,(又有一说是密度小于4 .5克/立方匣米),如铝的比重是2 .7,镁的比重是1 .7倍,而钾的比重只有0.87,钠只有0.97
重金属 重金属指比重大于5的金属,(一般指密度大于4.5克每立方厘米的金属) 铜、铅、锌、铁、钴、镍、锰、镉、汞、钨、钼、金、银等
低密度(mdpi) 中密度(hdpi) 高密度(xhdpi) 超高密度(xxhdpi) 超超高密度(xxxhdpi)
160dpi 1dp=1px
445dpi 1dp=2.78px 1dp=2px;
displaymetrics.density字段指定比例因子必须使用转换DP单位像素,
根据当前屏幕的密度。在中等密度屏幕,displaymetrics.density等于1;在高密度的屏幕
,它等于1.5;在超高密度的屏幕,它等于2;在低密度的屏幕,它等于0.75。这个数字的因素,
你应该乘DP单位为当前屏幕获得实际的像素数。(然后添加0.5f绕图到最接近的整数,当转换成一个整数。)
但是,现在很多Android厂商不一定会选择这些值作为系统密度,
而是选择实际的dpi作为系统密度,这就导致了很多手机的dpi也不是在这些值内。
例如小米Note这样的xxhdpi的设备他的系统密度并不是480,而是它的实际密度440。
public static int dip2px(float dipValue) {
float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
2 dp和px 如何互转
3 为什么会有 drawable-mdpi、drawable-hdpi、drawable-xhdpi drawable-xxhdpi 之类的文件 这些文件是起什么作用的
下面我讲适配,我们适配其实就是那么几种
1 .写多套布局layout
2.写多套value
3.放多套图片
4.用.9图片 左上可以拉伸,右下不可以拉伸区域。
5 .自定义布局
这是我今天讲的重点自定义 布局
我们一把都用俩个布局俩个布局大家都清楚一个线性布局,一个相对布局,那我们为啥不自定义这俩个布局呢,我以前想过,但考虑性能等等没有弄
但是我看到一篇不错的文章,我觉的可以写,现在我也在用,怕自己忘记了发一份放网上
public class PrecentRelative extends RelativeLayout { public PrecentRelative(Context context) { super(context); } public PrecentRelative(Context context, AttributeSet attrs) { super(context, attrs); } public PrecentRelative(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public PrecentRelative(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * 测量主见 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int with= View.MeasureSpec.getSize(widthMeasureSpec); int height=View.MeasureSpec.getSize(heightMeasureSpec); int childCount=this.getChildCount(); for (int i = 0; i <childCount ; i++) { View child=this.getChildAt(i);//获得到子控件 ViewGroup.LayoutParams layoutParams=child.getLayoutParams();//获得到子控件布局参数 float withParams=0; float heightParams=0; if (layoutParams instanceof PrecentRelative.LayoutParams){//确定是我自己设置了 withParams=((LayoutParam)layoutParams).getWithlayout(); heightParams=((LayoutParam)layoutParams).getHeightlayout(); } if (withParams>0){ layoutParams.width= (int) (with*withParams); } if (heightParams>0){ layoutParams.height= (int) (height*heightParams); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 把布局设置上去 * @param attrs * @return */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParam(getContext(),attrs); } public static class LayoutParam extends LayoutParams{ private float withlayout; private float heightlayout; public float getHeightlayout() { return heightlayout; } public void setHeightlayout(float heightlayout) { this.heightlayout = heightlayout; } public float getWithlayout() { return withlayout; } public void setWithlayout(float withlayout) { this.withlayout = withlayout; } /** * 只要修改这块就行 * @param c * @param attrs */ public LayoutParam(Context c, AttributeSet attrs) { super(c, attrs); TypedArray typedArray=c.obtainStyledAttributes(attrs,R.styleable.PrecentRelative); withlayout=typedArray.getFloat(R.styleable.PrecentRelative_layout_withPrecent,this.getWithlayout()); heightlayout=typedArray.getFloat(R.styleable.PrecentRelative_layout_heightPrecent,this.getHeightlayout()); } public LayoutParam(ViewGroup.LayoutParams source) { super(source); } public LayoutParam(LayoutParams source) { super(source); } public LayoutParam(MarginLayoutParams source) { super(source); } public LayoutParam(int w, int h) { super(w, h); } } }
旧这么一个类,这个相对布局的,其他布局也可以仿照来写
共同学习,写下你的评论
评论加载中...
作者其他优质文章