https://developer.android.com/guide/topics/graphics
Drawables
-
从资源文件中获取Drawable
val image:Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.my_image, null)
-
从xml文件中获取Drawable
val transition = ResourcesCompat.getDrawable(context.resources, R.drawable.transition, null) as TransitionDrawable
-
ShapeDrawable:适用于动态绘制不同形状边长的图形
class CustomDrawableView(context: Context) : View(context) { private val drawable: ShapeDrawable = run { val x = 10 val y = 10 val width = 300 val height = 50 contentDescription = context.resources.getString(R.string.my_view_desc) ShapeDrawable(OvalShape()).apply { // If the color isn't set, the shape uses black as the default. paint.color = 0xff74AC23.toInt() // If the bounds aren't set, the shape can't be drawn. setBounds(x, y, x + width, y + height) } } override fun onDraw(canvas: Canvas) { drawable.draw(canvas) } }
NinePatchDrawable:左、上是拉伸区域,右、下是内容显示区域
-
自定义drawables:重写draw(Canvas)
class MyDrawable : Drawable() { private val redPaint: Paint = Paint().apply { setARGB(255, 255, 0, 0) } override fun draw(canvas: Canvas) { // Get the drawable's bounds val width: Int = bounds.width() val height: Int = bounds.height() val radius: Float = Math.min(width, height).toFloat() / 2f // Draw a red circle in the center canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, redPaint) } override fun setAlpha(alpha: Int) { // This method is required } override fun setColorFilter(colorFilter: ColorFilter?) { // This method is required } override fun getOpacity(): Int = // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE PixelFormat.OPAQUE }
给drawables添加tint:着色
从image中抽取颜色:Palette类
Vector drawables
- VectorDrawable
- AnimatedVectorDrawable
Handling bitmaps
推荐Glide
Selecting Colors with the Palette API
依赖:implementation 'com.android.support:palette-v7:28.0.0'
-
创建Palette对象
// Generate palette synchronously and return it fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate() // Generate palette asynchronously and use it on a different // thread using onGenerated() fun createPaletteAsync(bitmap: Bitmap) { Palette.from(bitmap).generate { palette -> // Use generated instance } }
-
定制Palette对象
- addFilter()
- maximumColorCount()
- setRegion()
- addTarget()
-
抽取颜色:getXXXColor()
- Light Vibrant
- Vibrant
- Dart Vibrant
- Light Muted
- Muted
- Dark Muted
-
通过色块Palette.Swatch创建颜色: getXXXSwatch()
// Set the background and text colors of a toolbar given a // bitmap image to match fun setToolbarColor(bitmap: Bitmap) { // Generate the palette and get the vibrant swatch val vibrantSwatch = createPaletteSync(bitmap).vibrantSwatch // Set the toolbar background and text colors. // Fall back to default colors if the vibrant swatch is not available. with(findViewById<Toolbar>(R.id.toolbar)) { setBackgroundColor(vibrantSwatch?.rgb ?: ContextCompat.getColor(context, R.color.default_title_background)) setTitleTextColor(vibrantSwatch?.titleTextColor ?: ContextCompat.getColor(context, R.color.default_title_color)) } }
Reducing image download sizes
WebP优先;背景透明的用PNG;图片复杂用JPG、简单用PNG
AS中右键PNG文件,即可选择转换WebP
Hardware acceleration
可在Application、Activity、Window、View级别分别控制
确定是否开启:Canvas.isHardwareAccelerated()
-
Android绘制模型(难懂哦)
-
基于软件的绘制模型
- 对层次结构进行无效化处理(invalidate)
- 绘制层次结构
当需要更新界面一部分时,会对所有发生更改的所有视图调用invalidate()。无效化消息一直传播到视图树上层,以计算需要重新绘制的“脏区域”,然后系统会绘制视图树中与脏区域交互的所有视图。
缺点:每次绘制都需要执行大量代码;每次修改都要调用invalidate()
-
硬件加速绘制模型
- 对层次结构进行无效化处理
- 记录并更新显示列表
- 绘制显示列表
Android 系统不会立即执行绘制命令,而是将这些命令记录在显示列表中,这些列表中包含视图树绘制代码的输出。另一项优化是,Android 系统只需要记录和更新被
invalidate()
调用标记为脏视图的视图的显示列表。只需重新发出之前记录的显示列表,即可重新绘制未经过无效化处理的视图。
-
-
视图层
在所有 Android 版本中,视图能够通过以下两种方式渲染到屏幕外缓冲区:使用视图的绘制缓存或使用
Canvas.saveLayer()
。从 Android 3.0(API 级别 11)开始可以通过View.setLayerType()
方法更好地控制如何及何时使用层。- LAYER_TYPE_NONE
- LAYER_TYPE_HARDWARE
- LAYER_TYPE_SOFTWARE
view.setLayerType(View.LAYER_TYPE_HARDWARE, null) ObjectAnimator.ofFloat(view, "rotationY", 180f).apply { addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { view.setLayerType(View.LAYER_TYPE_NONE, null) } }) start() }
-
其他技巧
减少应用中的视图数量
避免过度绘制
请勿在绘制方法中创建渲染对象
请勿过于频繁地修改形状
请勿过于频繁地修改位图
-
谨慎使用 Alpha
当您使用
setAlpha()
、AlphaAnimation
或ObjectAnimator
将视图设置为半透明时,该视图会在屏幕外缓冲区渲染,导致所需的填充率翻倍。在超大视图上应用 Alpha 时,请考虑将视图的层类型设置为LAYER_TYPE_HARDWARE
。
OpenGL ES
-
基础
-
GLSurfaceView
绘制和操作Api的类,功能类似于SurfaceView,需要给一个Renderer对象
-
GLSurfaceView.Renderer
- onSurfaceCreated()
- onDrawFrame()
- onSurfaceChanged()
-
-
声明
<!-- Tell the system this app requires OpenGL ES 2.0. --> <uses-feature android:glEsVersion="0x00020000" android:required="true" />
-
坐标
OpenGL使用了一个正方形、有别于Android的坐标系统,因此不受硬件屏幕的尺寸和形状影响。
......