1.屏幕尺寸信息

屏幕大小:屏幕对角线长度,单位“寸”;
分辨率:手机屏幕像素点个数,例如720x1280分辨率;
PPI(Pixels Per Inch):即DPI(Dots Per Inch),它是对角线的像素点数除以屏幕大小得到的;
系统屏幕密度:android系统定义了几个标准的DPI值作为手机的固定DPI。(注,最后一个有笔误,正确的是1080x1920)

独立像素密度(DP):android系统使用mdpi屏幕作为标准,在这个屏幕上1dp=1px,其他屏幕可以通过比例进行换算。在hdpi中,1dp=1.5px。在xhdpi中,1dp=2px。在xxhdpi中,1dp=3px。
单位转换:常用的单位转换的辅助类DisplayUtil

/**
* 常用单位转换的辅助类
*/
public class DisplayUtil { /**
* dp转px
*/
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
} /**
* sp转px
*/
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
} /**
* px转dp
*/
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
} /**
* px转sp
*/
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}

2.2D绘图基础
(1)Canvas对象
drawPointdrawLinedrawRectdrawRoundRectdrawCircledrawArcdrawOvaldrawTextdrawPosText(在指定位置绘制文本),drawPath(绘制路径)

(2)Paint对象
setAntiAlias:设置画笔的锯齿效果
setColor:设置画笔的颜色
setARGB:设置画笔的A、R、G、B值
setAlpha:设置画笔的透明度值
setTextSize:设置字体大小
setStyle:设置画笔的效果(空心STROKE或者实心FILL)
setStrokeWidth:设置空心边框的宽度

3.Android XML绘图
(1)Bitmap
在XML中定义Bitmap的语法

<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@[package:]drawable/drawable_resource"
android:antialias=["true" | "false"]
android:dither=["true" | "false"]
android:filter=["true" | "false"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />

(2)Shape
在XML中定义Shape的语法

<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners //当shape为rectangle时使用
android:radius="integer" //半径值会被后面的单个半径属性覆盖,默认为1dp
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient //渐变
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
android:type=["linear" | "radial" | "sweep"]
android:useLevel=["true" | "false"] />
<padding //内边距
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<size //指定大小,一般用在imageview配合scaleType属性使用
android:width="integer"
android:height="integer" />
<solid //填充颜色
android:color="color" />
<stroke //边框
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>

(3)Layer
在XML中定义Layer的语法,layer类似PS中图层的概念,语法如下

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@[package:]drawable/drawable_resource" />
<item android:drawable="@[package:]drawable/drawable_resource" />
......
</layer-list>

(4)Selector
selector的用法很多,一般是定义控件在不同状态下的显示形态,可以是图片drawable,也可以是形状shape,还可以只是颜色color!

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 默认时的背景图片-->
<item android:drawable="@drawable/pic1"/>
<!-- 没有焦点时的背景图片 -->
<item android:drawable="@drawable/pic1" android:state_window_focused="false"/>
<!-- 非触摸模式下获得焦点并单击时的背景图片 -->
<item android:drawable="@drawable/pic2" android:state_focused="true" android:state_pressed="true"/>
<!-- 触摸模式下单击时的背景图片-->
<item android:drawable="@drawable/pic3" android:state_focused="false" android:state_pressed="true"/>
<!--选中时的图片背景-->
<item android:drawable="@drawable/pic4" android:state_selected="true"/>
<!--获得焦点时的图片背景-->
<item android:drawable="@drawable/pic5" android:state_focused="true"/>
</selector>

selector与shape结合的例子

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义当button处于pressed状态时的状态-->
<item android:state_pressed="true">
<shape>
<gradient android:startColor="#8600ff"/>
<stroke android:width="2dp" android:color="#000000"/>
<corners android:radius="5dp"/>
<padding android:bottom="10dp" android:left="10dp"
android:right="10dp" android:top="10dp"/>
</shape>
</item>
<!-- 定义当button获得焦点时的状态-->
<item android:state_focused="true">
<shape>
<gradient android:startColor="#eac100"/>
<stroke android:width="2dp" android:color="#333333"/>
<corners android:radius="8dp"/>
<padding android:bottom="10dp" android:left="10dp"
android:right="10dp" android:top="10dp"/>
</shape>
</item>
</selector>

selector可以用来指定不同状态下文本的颜色,例如按钮上的文本的颜色

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#999" android:state_selected="true"/>
<item android:color="#666" android:state_focused="true"/>
<item android:color="#333" android:state_pressed="true"/>
<item android:color="#000"/>
</selector>

结合这篇博文Android开发:shape和selector和layer-list以及博主的实现的圆角镂空按钮例子(综合使用了Shape、Layer和Selector实现了圆角镂空按钮)一起看还是挺不错的。

4.Android绘图技巧
(1)Canvas 画布
四个主要方法:
save:保存画布,将之前绘制的内容保存起来;
restore:合并画布,将save方法之后绘制的内容与之前绘制的内容合并起来;
translate:移动画布,其实是画布所在的坐标系的移动;
rotate:旋转画布,其实是画布所在的坐标系的旋转。
后面两个方法主要是用来方便在某些特殊情况下的绘制,例如书中介绍的仪表盘的绘制

@Override
protected void onDraw(Canvas canvas) {
// 获取宽高参数
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
// 画外圆
Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setAntiAlias(true);
paintCircle.setStrokeWidth(5);
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);
// 画刻度
Paint painDegree = new Paint();
paintCircle.setStrokeWidth(3);
for (int i = 0; i < 24; i++) {
// 区分整点与非整点
if (i == 0 || i == 6 || i == 12 || i == 18) {
painDegree.setStrokeWidth(5);
painDegree.setTextSize(30);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 60,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 90,
painDegree);
} else {
painDegree.setStrokeWidth(3);
painDegree.setTextSize(15);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 30,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 60,
painDegree);
}
// 通过旋转画布简化坐标运算
canvas.rotate(15, mWidth / 2, mHeight / 2);
}
// 画圆心
Paint paintPointer = new Paint();
paintPointer.setStrokeWidth(30);
canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer);
// 画指针
Paint paintHour = new Paint();
paintHour.setStrokeWidth(20);
Paint paintMinute = new Paint();
paintMinute.setStrokeWidth(10);
canvas.save();
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.restore();
}

(2)Layer 图层
在Android中图层是基于栈的结构来管理的,通过调用saveLayersaveLayerAlpha方法来创建图层,使用restorerestoreToCount方法将一个图层入栈。入栈的时候,后面所有的操作都发生在这个图层上,而出栈的时候则会把图像绘制在上层Canvas上。

@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
mPaint.setColor(Color.BLUE);
canvas.drawCircle(150, 150, 100, mPaint); canvas.saveLayerAlpha(0, 0, 400, 400, 127, LAYER_FLAGS);
mPaint.setColor(Color.RED);
canvas.drawCircle(200, 200, 100, mPaint);
canvas.restore();
}

仪表盘和Layer图层效果如下:
    

5.Android图像处理 [TODO:该部分略过了,自己暂时用的比较少,等需要用的时候学习下再补充]
色彩特效处理、图形特效处理、画笔特效处理

6.SurfaceView
SurfaceView与View的区别
(1)View主要适用于主动更新的情况下,而SurfaceView主要适用于被动更新,例如频繁地刷新;
(2)View在主线程中对画面进行刷新,而SurfaceView通常会通过一个子线程来进行页面刷新;
(3)View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中就已经实现了双缓冲机制。

SurfaceView的使用
(1)创建SurfaceView,一般继承自SurfaceView,并实现接口SurfaceHolderCallback。
SurfaceHolderCallback接口的三个回调方法

@Override
public void surfaceCreated(SurfaceHolder holder) {
//做一些初始化操作,例如开启子线程通过循环来实现不停地绘制
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
} @Override
public void surfaceDestroyed(SurfaceHolder holder) {
}

(2)初始化SurfaceView
初始化SurfaceHolder对象,并设置Callback

private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
......
}

(3)使用SurfaceView
通过lockCanvas方法获取Canvas对象进行绘制,并通过unlockCanvasAndPost方法对画布内容进行提交
需要注意的是每次调用lockCanvas拿到的Canvas都是同一个Canvas对象,所以之前的操作都会保留,如果需要擦除,可以在绘制之前调用drawColor方法来进行清屏。

private void draw() {
try {
mCanvas = mHolder.lockCanvas();
//mCanvas draw something
} catch (Exception e) {
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);
}
}

书中使用SurfaceView实现了简易画板

public class SimpleDraw extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
private Path mPath;
private Paint mPaint; public SimpleDraw(Context context) {
super(context);
initView();
} public SimpleDraw(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
} public SimpleDraw(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
initView();
} private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPath = new Path();
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(40);
} @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() {
long start = System.currentTimeMillis();
while (mIsDrawing) {
draw();
}
long end = System.currentTimeMillis();
// 50 - 100ms,经验值
if (end - start < 100) {
try {
Thread.sleep(100 - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} private void draw() {
try {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath, mPaint);
} catch (Exception e) {
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);
}
} @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;
}
}

Android动画机制与使用技巧

1.View动画 (视图动画)
视图动画(Animation)框架定义了透明度(AlphaAnimation)、旋转(RotateAnimation)、缩放(ScaleAnimation)和位移(TranslateAnimation)几种常见的动画,控制的是整个View,所以视图动画的缺陷就在于当某个元素发生视图动画后,其响应事件的位置还依然停留在原来的地方!
实现原理是每次绘制视图时View所在的ViewGroup中的drawChild方法获取该View的Animation的Transformation值,然后调用canvas.concat(transformationToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用invalidate方法,启动下次绘制来驱动动画,从而完成整个动画的绘制。
动画集合(AnimationSet):将多个视图动画组合起来
动画监听器(AnimationListener):提供动画的监听回调方法

2.属性动画
Android 3.0之后添加了属性动画(Animator)框架,其中核心类ObjectAnimator能够自动驱动,在不影响动画效果的情况下减少CPU资源消耗。

ObjectAnimator
创建ObjectAnimator只需通过它的静态工厂方法直接返回一个ObjectAnimator对象,参数包括view对象,以及view的属性名字,这个属性必须要有get/set方法,因为ObjectAnimator内部会通过反射机制来修改属性值。常用的可以直接使用属性动画的属性包括:
(1)translationXtranslationY:控制view从它布局容器左上角坐标偏移的位置;
(2)rotationrotationXrotationY:控制view围绕支点进行2D和3D旋转;
(3)scaleXscaleY:控制view围绕着它的支点进行2D缩放;
(4)pivotXpivotY:控制支点位置,围绕这个支点进行旋转和缩放处理。默认情况下,支点是view的中心点;
(5)xy:控制view在它的容器中的最终位置,它是最初的左上角坐标和translationX、translationY的累计和;
(6)alpha:控制透明度,默认是1(不透明)。

ObjectAnimator的常见使用方式如下:

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 300);
animator.setDuration(1000);
animator.start();

属性动画集合AnimatorSet:控制多个动画的协同工作方式,常用方法animatorSet.play().with().before().after()playTogetherplaySequentially等方法来精确控制动画播放顺序。使用PropertyValueHolder也可以实现简单的动画集合效果。

动画监听器:监听动画事件可以使用AnimatorListener或者简易的适配器AnimatorListenerAdapter

如果一个属性没有get/set方法怎么办?
(1)自定义包装类,间接地给属性提供get/set方法,下面就是一个包装类的例子,为width属性提供了get/set方法

public class WrapperView {

    private View mView;

    public WrapperView(View mView){
this.mView = mView;
} public int getWidth(){
return mView.getLayoutParams().width;
} public void setWidth(int width){
mView.getLayoutParams().width = width;
mView.requestLayout();
}
}

(2)使用ValueAnimator
ObjectAnimator就是继承自ValueAnimator的,它是属性动画的核心,ValueAnimator不提供任何动画效果,它就是一个数值产生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程,控制的方式是使用AnimatorUpdateListener来监听数值的变换。

ValueAnimator animator = ValueAnimator.ofFloat(0,100);
animator.setTarget(view);
animator.setDuration(1000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
//do the animation!
}
});

在XML中使用属性动画
下面是一个简单例子:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />

在代码中使用方式如下: [注:测试该代码的时候,上面的xml定义应该放在res的animator目录下,放在anim目录下不行]

Animator animator = AnimatorInflater.loadAnimator(this, R.animator.animator_rotation);
animator.setTarget(view);
animator.start();

View的animate方法
Android 3.0之后View新增了animate方法直接驱动属性动画,它其实是属性动画的一种简写方式

imageView.animate().alpha(0).y(100).setDuration(1000)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
} @Override
public void onAnimationEnd(Animator animation) {
} @Override
public void onAnimationCancel(Animator animation) {
} @Override
public void onAnimationRepeat(Animator animation) {
}
});

3.布局动画
布局动画是作用在ViewGroup上的,给ViewGroup添加view时添加动画过渡效果。
(1)简易方式(但是没有什么效果):在xml中添加如下属性 android:animateLayoutChanges="true
(2)通过LayoutAnimationController来自定义子view的过渡效果,下面是一个常见的使用例子:

LinearLayout linearLayout = (LinearLayout) findViewById(R.id.ll);
ScaleAnimation scaleAnimation = new ScaleAnimation(0,1,0,1);
scaleAnimation.setDuration(2000);
LayoutAnimationController controller = new LayoutAnimationController(scaleAnimation, 0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);//NORMAL 顺序 RANDOM 随机 REVERSE 反序
linearLayout.setLayoutAnimation(controller);

4.自定义动画
创建自定义动画就是要实现它的applyTransformation的逻辑,不过通常还需要覆盖父类的initialize方法来实现初始化工作。
下面是一个模拟电视机关闭的动画,

public class CustomTV extends Animation {

    private int mCenterWidth;
private int mCenterHeight; @Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(1000);// 设置默认时长
setFillAfter(true);// 动画结束后保留状态
setInterpolator(new AccelerateInterpolator());// 设置默认插值器
mCenterWidth = width / 2;
mCenterHeight = height / 2;
} @Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final Matrix matrix = t.getMatrix();
matrix.preScale(1, 1 - interpolatedTime, mCenterWidth, mCenterHeight);
}
}

applyTransformation方法的第一个参数interpolatedTime是插值器的时间因子,取值在0到1之间;第二个参数Transformation是矩阵的封装类,一般使用它来获得当前的矩阵Matrix对象,然后对矩阵进行操作,就可以实现动画效果了。

如何实现3D动画效果呢?
使用android.graphics.Camera中的Camera类,它封装了OpenGL的3D动画。可以把Camera想象成一个真实的摄像机,当物体固定在某处时,只要移动摄像机就能拍摄到具有立体感的图像,因此通过它可以实现各种3D效果。
下面是一个3D动画效果的例子

public class CustomAnim extends Animation {

    private int mCenterWidth;
private int mCenterHeight;
private Camera mCamera = new Camera();
private float mRotateY = 0.0f; @Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(2000);// 设置默认时长
setFillAfter(true);// 动画结束后保留状态
setInterpolator(new BounceInterpolator());// 设置默认插值器
mCenterWidth = width / 2;
mCenterHeight = height / 2;
} // 暴露接口-设置旋转角度
public void setRotateY(float rotateY) {
mRotateY = rotateY;
} @Override
protected void applyTransformation( float interpolatedTime, Transformation t) {
final Matrix matrix = t.getMatrix();
mCamera.save();
mCamera.rotateY(mRotateY * interpolatedTime);// 使用Camera设置旋转的角度
mCamera.getMatrix(matrix);// 将旋转变换作用到matrix上
mCamera.restore();
// 通过pre方法设置矩阵作用前的偏移量来改变旋转中心
matrix.preTranslate(mCenterWidth, mCenterHeight);
matrix.postTranslate(-mCenterWidth, -mCenterHeight);
}
}

5.Android 5.X SVG矢量动画机制 [TODO:该部分略过了,自己暂时用的比较少,等需要用的时候学习下再补充]
本章最后还有几个很常用的动画实例,感兴趣可以看下。

第三章 Android绘图机制与处理技巧的更多相关文章

  1. Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧

    第六章 Android绘图机制与处理技巧 1.屏幕尺寸信息屏幕大小:屏幕对角线长度,单位“寸”:分辨率:手机屏幕像素点个数,例如720x1280分辨率:PPI(Pixels Per Inch):即DP ...

  2. Android群英传笔记——第六章:Android绘图机制与处理技巧

    Android群英传笔记--第六章:Android绘图机制与处理技巧 一直在情调,时间都是可以自己调节的,不然世界上哪有这么多牛X的人 今天就开始读第六章了,算日子也刚好一个月了,一个月就读一半,这效 ...

  3. Android绘图机制和处理技巧

    色彩特效处理 在色彩处理中,使用以下三个角度来描述一个图像. 色调: 物体传播的颜色 饱和度: 颜色的纯度, 从0(灰)到100%(饱和)来进行描述 亮度: 颜色的相对明暗程度 在Android中, ...

  4. Android绘图机制(三)——自定义View的实现方式以及半弧圆新控件

    Android绘图机制(三)--自定义View的三种实现方式以及实战项目操作 在Android绘图机制(一)--自定义View的基础属性和方法 里说过,实现自定义View有三种方式,分别是 1.对现有 ...

  5. Android群英传笔记——第七章:Android动画机制和使用技巧

    Android群英传笔记--第七章:Android动画机制和使用技巧 想来,最 近忙的不可开交,都把看书给冷落了,还有好几本没有看完呢,速度得加快了 今天看了第七章,Android动画效果一直是人家中 ...

  6. Android绘图机制(四)——使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美

    Android绘图机制(四)--使用HelloCharts开源框架搭建一系列炫酷图表,柱形图,折线图,饼状图和动画特效,抽丝剥茧带你认识图表之美 这里为什么不继续把自定义View写下去呢,因为最近项目 ...

  7. Android绘图机制(二)——自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解

    Android绘图机制(二)--自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解 我们要想画好一些炫酷的View,首先我们得知道怎么去画一些基础的图案,比如矩形,圆 ...

  8. Android绘图机制(一)——自定义View的基础属性和方法

    Android绘图机制(一)--自定义View的基础属性和方法 自定义View看起来,确实看起来高深莫测,很多Android开发都不是特别在行这一块,这里面的逻辑以及一些绘画都是有一点难的,说一下我目 ...

  9. 第三章Android移植平台工具介绍

    第三章Android移植平台工具介绍 进行 Android 移植的学习并不一定需要一款 Android 手机,但必须要有一款主流的开发板,开发板是用来进行嵌入式系统开发的电路板,包括中央处理器.存储器 ...

随机推荐

  1. SQL Server 2005、SQL Server 2008版本比较

    SQL Server 2005的版本有SQL Server 2005企业版(Enterprise).SQL Server 2005标准版(Standard) 和SQL Server 2005工作组版( ...

  2. 手写总结:synchronized 和 lock 区别

    1.  synchronized 是jvm 层次的(可以会造成死锁), lock 可以写代码控制,一般在异常时在 finally 里可以 unlock 释放锁 2. lock 细度更细,synchro ...

  3. 学OpenGL的一些好的网站

    好的资源太多,自己懂的太少,而今迈步从头越!!fighting...... 一些OpenGL资源链接 这是前几天自己简单整理的几个链接,希望对大家有用 顺便问一下http://www.spacesim ...

  4. DIY一款C/C++编译器

    一. 原理 1.1 记事本编程 我们用记事本新建一个文件,文件后缀改成.c,例如文件名叫做"1.c",在文件里写上最简单的C或者C++代码, #include<stdio.h ...

  5. 删除所有ecshop版权和logo

    前面我们已经讲过如何删除ecshop的版权,但是还有很多人不会,今天就详细的讲下如何删除所有ecshop版权和logo 前台部分: 1:去掉头部TITLE部分的ECSHOP演示站 Powered by ...

  6. CentOS 7 之几个新特性(转)

    上篇我们讲到默认没有ifconfig是centos7的新特性,所以我特意上网搜索了一下其新特性,找到一篇文章,现转过来. centos最小好化安装没有ifconfig命令 刚安装了centos7.0, ...

  7. 一个读取C#特性Description方法

    class Program { static void Main(string[] args) { string str= DB.write.ToDescription(); Console.Writ ...

  8. 静态编译Qt5.4.1和Qt WebKit

    图灵社区文章地址:http://www.ituring.com.cn/article/195148WebKit是个好东西,做爬虫.显示网页还是想用HTML来做桌面应用的界面都可以用他,不过一直以来都觉 ...

  9. java基本类型作为成员变量时的初始值

    package primitivetypedefaultvalue; public class ListDefaultValue { public static void main(String[] ...

  10. TCP 协议

    == 已经了解了以太网和IP了,下面我们进入传输层,开始讲解TCP协议. == 仍然先把TCP报文段的格式放在这里,然后我们看图说话: TCP报文段也分为首部和数据两部分,首部默认情况下一般是20字节 ...