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 是和屏幕寬度是成正比的。