屏幕的尺寸信息
px:像素
dp:独立密度像素
PPI:每英寸包含的像素个数
具体解释如下链接,这哥们写的特别好
http://blog.youkuaiyun.com/u010074743/article/details/51603736
可以做一个工具类,
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);
}
}