1.首先抛出一个问题:
自定义中getWidth()、getHeight()、canvas.drawCircle()
等方法获取的值和设置的值是dp
值还是px
值
我百度了一下得到的答案是px
值
2.验证:
我自定义一个view,在ondraw()中绘制一个圆
package com.example;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @Author: david.lvfujiang
* @Date: 2020/1/16
* @Describe:
*/
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
Log.e("TAG",canvas.getWidth()+","+ Resources.getSystem().getDisplayMetrics());
canvas.drawCircle(200,200,200,paint);
}
}
设备1:1440 x 2560 像素密度:560 density:3.5
设备2:1080 x 1920 像素密度:420 density:2.6
我们知道我们的圆占400像素
在1080 x 1920
的设备上显得比较大,宽度占比:400:1080 = 37%
在1440 x 2560
的设备上则显得比较小,宽度占比:400:1080 = 27%
因此我们运行出来的效果在不同的手机屏幕可能有的大有的小,我们适配的最终希望是:我的圆无论在什么手机上显示的占比度都是一样的。
3根据density计算我们的view高宽度
package com.example;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import androidx.annotation.Nullable;
/**
* @Author: david.lvfujiang
* @Date: 2020/1/16
* @Describe:
*/
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
Log.e("TAG",canvas.getWidth()+","+ Resources.getSystem().getDisplayMetrics());
canvas.drawCircle(dp2pix(100),dp2pix(100),dp2pix(100),paint);
}
private int dp2pix(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
}
}
在view中添加dp2pix()
方法根据系统density
计算圆的高宽
(设备1:1440 x 2560
像素密度:560
density:3.5
) 计算得到的圆:直径*density = 700px
占屏幕宽度:48%
.
(设备2:1080 x 1920
像素密度:420
density:2.6
)计算得到的圆:直径*density = 520px
占屏幕宽度:48%
我们知道我们计算px
值的时候是需要density
配合:
(设备1:1440 x 2560
像素密度:560
density:3.5
) 计算得到的圆:700px
占屏幕宽度:48%
(设备2:1080 x 1920
像素密度:420
density:2.6
)计算得到的圆:520px
占屏幕宽度:48%
设备1的density
值比较大,所以我们计算得到圆的像素比较大,设备2的density
值比较小,我们计算得到圆的像素比较小,而像素又是相对单位,因此在设备1和设备2上显示的大小正好一样。当然这是density
值和设备宽度分辨率成正比的情况下,density是由系统决定不是由屏幕的分辨率决定。如果说设备1和设备2的像素密度正好反过来:
(设备1:1440 x 2560
像素密度:420
density:2.6
)
(设备2:1080 x 1920
像素密度:560
density:3.5
)
那我计算圆的时候会得到:
(设备1:1440 x 2560
像素密度:420
density:2.6
) 计算得到的圆:520px
占屏幕宽度:36%
(设备2:1080 x 1920
像素密度:560
density:3.5
)计算得到的圆:700px
占屏幕宽度:64%
4.解决density带来的问题
为了解决该问题我们需要引入今日头条适配方案:
Android 屏幕适配之框架(AndroidAutoSize)(今日头条)适配
android开发:今日头条屏幕适配方案
AndroidAutoSize的核心是动态的修改系统的density值
假设我们把所有的屏幕宽度都看成360dp
(总设计图纸的dp),通过dp
和px
的转换率我们可以知道,设备1的density = 3
,设备2的density = 4
。那我们的圆在设备1上的尺寸则是600px
,占屏幕宽度的55%,
在设备2上尺寸是800px
,占屏幕宽度的55%
。使用AndroidAutoSize动态的修改density ,保证了我们的density 是和屏幕宽度是成正比的。