使用R.drawablw.xxx来引用即可
bitmap转drawable:使用new BitmapDrawable(bitmap); drawable转bitmap:使用drawable.getBitmap();
BitmapFactory的方法: 1. decodeByteArray(byte[] data,int offset,int length); 2. decodeFile(String pathName); 3. decodeFileDescriptor(FileDescriptor fd); 4. decodeSource(Resource res, int id); 5. decodeStream(inputStream is);
问题:大量使用封装该图片的Drawable对象,可能由于前面创建的Bitmap所占用的内存还没有回收,导致程序出现OutOfMemory的错误。 解决办法:Android为Bitmap提供两种判读Bitmap是否已回收的方法,以及强制Bitmap回收自己。 1. boolean isRecycled():返回该Bitmap对象是否已被回收。 2. void recycle():强制一个Bitmap对象立即回收自己。 方法为:if(!bitmapDrawable.getBitmap().isRecycled()){bitmapDrawable.getBitmap().recycle()};
如果Android应用需要访问其他路径(SD卡),需要借助BitmapFactory来解析、创建对象。
丰富的Android界面离不开绘图罗,废话不多说,入正题。
Andriod绘图过程:
Canvas的方法: 1. drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint);画弧 2. drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint);制定图片挖取一块 3. drawBitmap(Bitmap bitmap,float left ,float top,Paint paint);指定点画位图 4. drawCircle(float cx,float cy,float radius,Paint paint);画圆 5. drwaLine(float startX,float startY,float stopX,float stopY,Paint paint); 6. drawLines(float[] pts,int offset ,int counts,Paint paint); 7. drawOval(RectF oval,Paint paint); 8. drawPath(Path path,Paint paint);沿指定的Path绘制任意形状 9. drawPoint(float x,float y,Paint paint); 10. drawPoints(float[] pts,int offset,int count,Paint paint); 11. drawRect(float left,float top,float right,float bottom,Paint paint); 12. drawRoundRect(RectF rect,float rx,float ry,Paint paint);圆角矩形 13. drawText(String text,int start,int end,Paint paint); 14. drawTextOnPath(String text,Path path,float hOffset,float vOffset,Paint paint); 15. clipRect(float left,float top,float right,float bottom); 16. clipRegion(Region region);裁剪指定区域 17. drawBitmapMesh(Bitmap bitmap,int meshWidth,int meshHeight,float[] verts,int vertOffset,int[] colors,int colorOffset,Paint paint);对Bitmap进行扭曲 除此之外,Canvas还提供如下方法进行坐标变换: 1. rotate(float degress,float px,float py) 2. scale(float sx,float sy,float px,float py) 3. skew(float sx,float sy)倾斜变换 4. translate(float dx,float dy)
说完Canvas,来来来,皮皮虾,我们去看看Paint: 如果说Canvas是画布的话,那么Paint就是画笔罗。包括绘画风格,粗细,填充。 Paint的方法: 1. setARGB(int a,int r,int g, int b); 2. setAlpha(int a); 3. setAntiAlias(boolean aa);是否抗锯齿 4. setColor(int color); 5. setPathEffect(PathEffect effect);设置绘制路径的路径效果 6. setShader(Shader shader):设置画笔的填充效果 7. setShadowLayer(float radius,float dx,float dy,int color);设置阴影 8. setStrokeWidth(float width);设置画笔的笔触宽度 9. setStrokeJoin(Paint.Join join):设置画笔转弯处的连笔风格 10. setStyle(Paint.Style style):设置Paint的填充风格 11. setTextAlign(Paint.Align align):设置绘制文本的对齐方式 12. setTextSize(float textSize):设置绘制文本的文字大小
//为Paint设置渐变器 Shader mShader = new LinearGradient(0,0,40,60,new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},null,Shader.TileMode.REPEAT); paint.setShader(mShader); paint.setShadowLayer(25,20,20,Color.GRAY);Path的子类,每一种子类代表一种效果: 1. CompostPathEffect 2. CornerPathEffect 3. DashPathEffect 4. DiscretePathEffect 5. PathDashPathEffect 6. SumPathEffect
Path常用方法:(自结) 1. moveTo() 2. quadTo() 3. lineTo()
path.moveTo(0,0); //生成20个点,随机生成它们的Y坐标,并练成线 for(int i = 1; i <= 20;i++){ paths.lineTo(i*30,(float)Math.random()*30); }通知View重绘界面可以用invalidate(UI线程)或psotInvalidate(非UI线程)
技术点: 1. 双缓冲技术
高级绚丽的UI界面设计
使用Matrix控制图形或组件变换的步骤: 1. 获取Matrix对象,可创建也可直接获取其他对象内部封装的Matrix 2. 调用Matrix的方法进行平移,旋转,缩放,倾斜 3. 将程序对Matrix所做的变换指定给图形或者组件
Matrix提供如下方法: 1. setTranslate(float dx,float dy); 2. setSkew(float kx ,float ky,float px,flpat py); 3. setSkew(float kx,float ky) 4. setRotate(float degress); 5. setRotate(float degree,float px,float py); 6. setScale(float sx,float sy) 7. setScale(float sx,float sy,float px,float py); 8. preTranslate(float x,float y);当matrix进行变换的时候,将整个图片向上移动x个单位。将旋转中心点位于图片中间。 9. postTranslate(float x,float y);当旋转之后再将图片向下移动x个单位。
关于8,9两个方法可以参考对Matrix中preTranslate()和postTranslate()的理解
实例:做一个雷电游戏
drawBitmapMesh(Bitmap bitmap,int meshWidth,int meshHeight,float[] verts,int vertOffset,int[] colors,int colorOffset,Paint paint);参数分析 1. bitmap:需要扭曲的源 2. meshWidth:控制横向上把该源图划分多少格 3. meshHeight:同上 4. verts:长度为(meshWidth+1)*(meshHeight+1)X2的数组,记录了扭曲的各顶点位置 5. verOffset:控制从第几个数组开始扭曲
Shader作为一个抽象类,提供如下实现类: 1. BitmapShader:使用位图平铺的渲染效果 2. LinearGradien:使用线性渐变来填充图形 3. RadialGradient:使用圆形渐变来填充图形 4. SweepGradient:使用角度渐变来填充图形 5. CompostShader:使用组合渲染效果来填充图形
原理和放电影的原理是一样的
XML中实现方法:在
只需要设置开始动画和结束动画的关键帧,其他中间部分的帧由系统计算补齐
Animation有下面几个子类: 1. AlphaAimation:动画透明度的修改 2. ScaleAnimation:缩放修改 3. TranslateAnimation:平移动画 4. RotateAnimation:旋转动画
当动画执行期间需要动态插入多少帧,在哪个时刻插入,就需要用到intepolator.
interpolator:就是根据算法计算处整个动画所需要动态插入帧的密度和位置。 Android为interpolator提供如下几个实现类: 1. LinearInterpolator:匀速 2. AccelerateInterpolator:加速 3. AccelerateDecelerateInterpolator:在动画开始、结束的地方地方速度较慢,在中间加速 4. CycleInterpolator:动画循环播放特定的次数,变化速度按正弦曲线改变 5. DecelerateInterpolator:减速 6. AnticipateInterpolator:中间慢,两头快 7. AnticipateOvershootInterpolator:慢快慢快 8. BounceInterpolator: 9. OvershootInterpolator:变速慢,比DecelerateInterpolator中间的速度变化快一点。
如果需要在
如何让图片在三维空间中进行旋转缩放。这里就需要使用到自定义补间动画了,自定义补间动画并不难。需要继承Animation,继承Animation时关键需要重写该抽象类的基类applyTransformation(float interpolatedTime,Transformation t)方法,该方法有两个参数说明: 1. interpolatedTime:代表动画进行的时间比。总是从0变化到1. 2. Transformation:代表不同时刻的变化程度。
Camera提供如下常用方法: 1. getMatrix(Matrix matrix);将Camera所做的变换应用到指定的matrix上。 2. rotateX(float deg):使目标沿X轴旋转 3. rotateY(float deg):同上 4. rotateZ(float deg):同上 5. translate(float x,float y,float z);三维空间位移变换 6. applyToCanvas(Canvas canvas):把所有的变换应用到Canvas上
问题:startAnimation()和setAnimation()的区别。
简单来说属性动画从某种角度来说就是增强的补间动画。 属性动画的强大主要体现在如下两个方面: 1. 补间动画只能定义两个帧透明度,旋转,位移,缩放4个面的变化,但属性动画可以定义任何属性的变化 2. 补间动画只能对UI组件执行动画 类似之处: 1. 动画持续方式:默认300ms 2. 动画插值方式 3. 重复次数 4. 重复行为 5. 动画集 6. 刷新新频率,默认10ms
步骤: 1. 调用ValueAnimator的ofInt(),ofFloat()或ofObject()静态方法创建ValueAnimator实例 2. 调用ValueAnimator的setXXX()方法来设置动画持续时间,插值方式,重复次数等 3. 调用ValueAnimator的start()方法来启动动画 4. 为ValueAnimator注册AnimatorUpdateLister监听器,在该监听器中可以监听ValueAnimator计算出来的值改变,并将这些值应用到指定对象上。
ObjectAnimator继承字ValueAnimator,因此可以直接将ValueAnimator在动画过程中计算的值应用到指定对象的指定属性上,所以它不需要AnimatorUpdateListener监听器。
与ValueAnimator不同的是,使用ObjectAnimator有如下几个注意点: 1. 要为对象对应的属性提供setter方法。 2. 如果ObjectAnimator的ofInt(),ofFloat()或者ofObject()工厂方法时,如果values参数只提供一个值,那么默认为结束值。该对象提供一个getter方法,该getter方法返回值将作为开始值 3. 如果动画的对象时view,为了能显示动画效果,可能需要onAnimationUpdate()事件监听中调用View.invalidate()方法来刷新屏幕的显示。但view定义了setter方法,如setAlpha()和setTranslationX()等方法,将会自动调用invalidate()方法。因此不需要额外调用invalidate()方法。
定义属性动画有两种方式: 1. 使用ValueAnimator或ObjectAnimator的静态工厂的方法来创建动画 2. 使用资源文件来定义动画
创建属性动画的步骤: 1. 创建ValueAnimator或ObjectAnimator对象——即可从XML资源文件加载该动画资源,也可直接调用ValueAnimator或ObjectAnimator的静态工厂的方法来创建动画 2. 根据需要为Animator对象设置属性 3. 如果需要监听Animator的开始,结束,重复,动画值改变事件,应该设置事件监听器 4. 如果有多个需要按次序或者组合使用,需要使用AnimatorSet组合动画 5. 调用start()启动动画
View的绘图存在如下缺陷: 1. View缺乏双缓冲机制 2. 当程序需要更新View上的图片时,程序必须重绘View上显示的整张图片。 3. 新线程无法直接更新View组件
由于上述原因,所以在自定义绘图中,我们多数采用SurfaceView来实现。
SurfaceView一般会与SurfaceHolder结合使用,SurfaceHolder用于向与之相关联的SurfaceView上绘图,调用SurfaceView的个体Holder()即可获得与之相关联的surfaceHolder. SurfaceHolder提供如下方法来获取Canvas对象: 1. Canvas lockCanvas():锁定整个SurfaceView对象,获取该SurfaceView上的Canvas. 2. Canvas lockCanvas(Rect dirty):锁定SurfaceView上Rect划分的区域,获取SurfaceView上的Canvas.
当对同一个SurfaceView进行上面两个方法时,获取是同一个Canvas对象,但是当使用第二种方法时,SurfaceView获取的Canvas时只对Rect范围内的区域进行更新。 获取Canvas后通过如下方法来释放,提交绘图。 unlockCanvasAndPost(canvas) 当调用SurfaceHolder的unlockCanvasAndPost()方法之后,该方法之前所绘制的图形还处于缓冲区中,下一次lockCanvas()方法锁定的区域可能会遮挡它。
Android动画这一块可深可浅,可能你了解一点,刚入门,缩放,平移旋转都不是事,就觉得动画很简单,没什么技术含量.但当有一天你真正的深入到这个领域去,做一些市面上不存在的动画效果的时候,到时候再回过头来看,将会发现android动画包涵了一些很了不起的 算法和实现思路.