屏幕的尺寸信息
px:像素
dp:獨立密度像素
PPI:每英寸包含的像素個數
具體解釋如下鏈接,這哥們寫的特別好
可以做一個工具類,
public class DisplayUtil {
/**
* 將px值轉換爲dip或者dp值,保證尺寸大小不變
* @param context
* @param pxValue px的值
* @return
*/
public static int px2dip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue/scale+0.5f);
}
/**
* 將dip或者dp轉換爲px值,保證尺寸大小不變
* @param context
* @param dipValue
* @return
*/
public static int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue*scale + 0.5f);
}
/**
* 將px值轉換爲sp值,保證文字大小不變
* @param context
* @param pxValue
* @return
*/
public static int px2sp(Context context, float pxValue){
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue/fontScale+0.5f);
}
/**
* 將sp值轉換爲px值,保證文字大小不變
* @param context
* @param spValue
* @return
*/
public static int sp2px(Context context, float spValue){
final float scale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue*scale+0.5f);
}
}
paint 的常用方法
paint.setAntiAlias(true);//設置畫筆的鋸齒效果
paint.setColor(Color.RED);
paint.setARGB(100, 100, 100, 100);//設置畫筆的A、R、G、B值
paint.setAlpha(9); //取值範圍爲0~255,數值越小越透明
paint.setTextSize(30); //設置字體的大小
paint.setStyle(Paint.Style.STROKE); //設置畫筆的風格(空心或實心) 例:可以畫出空心的矩形
paint.setStrokeWidth(20);//設置空心邊框的寬度
Canvas ##
Canvas.save(): 作用是將之前的已經繪製的圖像保存起來,讓後續的操作就好像在一個新的圖層上操作一樣。
Canvas.restore(): 作用是將我們在save()之後繪製的圖像與save之前的圖像進行合併。
實現一個錶盤:
public class MyView extends View {
private Paint paint;
private Paint paintCircle;
private Paint paintHour;
private Paint paintMinute;
private int mWidth;
private int mHeight;
private boolean isInitDialPlate = true;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData(context);
}
private void initData(Context context) {
paint = new Paint();
// paint.setAntiAlias(true);//設置畫筆的鋸齒效果
//paint.setColor(Color.RED);
paint.setStrokeWidth(3);
// paint.setARGB(100, 100, 100, 100);//設置畫筆的A、R、G、B值
// paint.setAlpha(9); //取值範圍爲0~255,數值越小越透明
// paint.setTextSize(30); //設置字體的大小
// paint.setStyle(Paint.Style.STROKE); //設置畫筆的風格(空心或實心) 例:可以畫出空心的矩形
// paint.setStrokeWidth(20);//設置空心邊框的寬度
paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setAntiAlias(true);
paintCircle.setStrokeWidth(5);
paintHour = new Paint();
paintHour.setStrokeWidth(20);
paintMinute = new Paint();
paintMinute.setStrokeWidth(10);
Resources resources = this.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
float density = dm.density;
mWidth = dm.widthPixels;
mHeight = dm.heightPixels;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInitDialPlate){
initDialPlate(canvas);
}
canvas.translate(mWidth/2,mHeight/2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.rotate(15, mWidth/2, mHeight/2);
canvas.restore();
}
private void initDialPlate(Canvas canvas) {
canvas.drawCircle(mWidth/2, mHeight/2, mWidth/2-50, paintCircle);
for (int i=0; i<24; i++){
if (i==0||i==6||i==12||i==18){
paint.setStrokeWidth(5);
paint.setTextSize(30);
canvas.drawLine(mWidth/2, mHeight/2-mWidth/2+50, mWidth/2, mHeight/2-mWidth/2+60+50,paint);
String degree = String.valueOf(i);
canvas.drawText(degree, mWidth/2-paint.measureText(degree)/2, mHeight/2-mWidth/2+90+50, paint);
}else {
paint.setStrokeWidth(3);
paint.setTextSize(15);
canvas.drawLine(mWidth/2, mHeight/2-mWidth/2+50, mWidth/2, mHeight/2-mWidth/2+30+50, paint);
String degree = String.valueOf(i);
canvas.drawText(degree, mWidth/2-paint.measureText(degree)/2, mHeight/2-mWidth/2+60+50, paint);
}
canvas.rotate(15, mWidth/2, mHeight/2);
}
canvas.save();
}
}
surfaceView
View通過刷新來重繪視圖,Android系統通過發出VSYNC信號來進行屏幕的重繪,刷新的時間間隔是16ms,如果在16ms內View完成了你需要執行的所有操作,那麼用戶在視覺上就不會有卡頓現象,如果執行的邏輯太多,特別是需要頻繁刷新的界面,例如遊戲界面,那麼就會不斷阻塞主線程,從而導致畫面卡頓。
SurfaceView的使用雖然比View複雜,但是SurfaceView在使用的時候有一套使用的模板代碼,大部分的SurfaceView繪圖操作就會套用這樣的模板來進行編寫。
SurfaceView的使用案例之一:繪畫板
public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback,Runnable {
private SurfaceHolder mHolder;
/**
* 用於繪圖的Canvas
*/
private Canvas mCanvas;
/**
* 子線程標誌位
*/
private boolean mIsDrawing;
private Path mPath;
private Paint paint;
public SurfaceViewTemplate(Context context) {
this(context, null);
}
public SurfaceViewTemplate(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
/**
* 獲得焦點
*/
setFocusable(true);
/**
* 設置可以獲得焦點,但是不一定獲得
*/
setFocusableInTouchMode(true);
/**
* 設置屏幕一直亮
*/
this.setKeepScreenOn(true);
mPath = new Path();
paint = new Paint();
paint.setStrokeWidth(20);
paint.setTextSize(60);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDrawing = false;
}
@Override
public void run() {
while (mIsDrawing){
draw();
}
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();
/**
* draw something
*/
drawSomething();
}catch (Exception e){
}finally {
if (mCanvas!=null){
/**
* 對畫布內容進行提交,放在finally中保證每次都能將內容提交
*/
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
/**
* 在這裏畫
*/
private void drawSomething() {
mCanvas.drawColor(Color.YELLOW);//畫布的背景
mCanvas.drawPath(mPath, paint);
}
}