android中invalidate()的使用小结

本文详细解析了invalidate()方法的作用及其在不同场景下的应用,包括单线程刷新、多线程结合双缓冲机制下的屏幕刷新策略。通过具体示例介绍了如何在Android中有效地触发UI重绘。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。 
对于屏幕刷新有以下集中情况可以考虑: 
1.不使用多线程和双缓冲 
     这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。 
/**
         * 刷新波形的线程
         * */
		private class TimerProcess implements Runnable {
			public void run() {
				if (isDrawing) {
					ctrlWave.invalidate();//
					mHandler.postDelayed(this, 50);
				}
				
			}
		}


@Override
protected void onDraw(Canvas canvas) {
	 super.onDraw(canvas);

 //drawTable(canvas);
 drawcanvas(canvas);
 preLine();
 while(FLAG){
	 try {
			preSettings();
		    FLAG=false;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 }	
}


2.使用多线程和不使用双缓冲 

     这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views. 

     这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量, 你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后在主线程中捕获、处理该消息。 


3.使用多线程和双缓冲 

    Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示)。


一般引起invalidate()操作的函数如下:

                1、直接调用invalidate()方法,请求重新draw(),但只会绘制调用者本身。

                2、setSelection()方法 :请求重新draw(),但只会绘制调用者本身。

                3、setVisibility()方法 : 当View可视状态在INVISIBLE转换VISIBLE时,会间接调用invalidate()方法,继而绘制该View。

                4 、setEnabled()方法 : 请求重新draw(),但不会重新绘制任何视图包括该调用者本身。 


Android 平台上实现心形图片动画并绘制一个同心结效果,可以通过结合 `Canvas`、`Path` 和自定义 `View` 来完成。以下是一种可行的实现思路和技术路径。 ### 心形图像的绘制 首先需要定义一个心形的 `Path`,用于作为图像裁剪或绘制的基础。可以通过数学公式或手动构造路径来创建心形形状: ```java private Path createHeartPath(float width, float height) { Path path = new Path(); path.moveTo(width / 2, height); path.cubicTo( width / 4, height / 4, width * 3 / 4, -height / 4, width / 2, height ); path.close(); return path; } ``` ### 动画实现 使用 `ValueAnimator` 实现心形图像的缩放和旋转动画,以增强视觉效果: ```java ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f); animator.setDuration(1000); animator.setRepeatCount(ValueAnimator.INFINITE); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(animation -> { float scale = (float) animation.getAnimatedValue(); invalidate(); // 触发重绘 }); animator.start(); ``` 在 `onDraw(Canvas canvas)` 中应用动画效果: ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.save(); canvas.translate(getWidth() / 2, getHeight() / 2); canvas.scale(scaleFactor, scaleFactor); // 应用缩放 canvas.rotate(rotationAngle); // 应用旋转 // 使用之前定义的心形路径进行裁剪或绘制 Path heartPath = createHeartPath(200, 200); canvas.clipPath(heartPath); // 绘制图像 canvas.drawBitmap(heartBitmap, -100, -100, null); // 假设 bitmap 大小为 200x200 canvas.restore(); } ``` ### 同心结效果的实现 同心结效果通常由多个交叠的心形组成,并通过透明度、缩放等变化形成层次感。可以使用 `Canvas.saveLayer()` 方法保存当前图层状态,在绘制不同心形独立操作其变换[^4]。 示例代码如下: ```java canvas.saveLayer(null, null); // 保存当前画布状态 for (int i = 0; i < 5; i++) { canvas.save(); canvas.translate(i * 10, i * 10); // 每个心形稍微偏移 canvas.scale(1 - i * 0.1f, 1 - i * 0.1f); // 缩放递减 canvas.setAlpha((int) (255 * (1 - i * 0.2f))); // 透明度递减 canvas.drawPath(heartPath, paint); // 绘制心形路径 canvas.restore(); } canvas.restore(); // 恢复到之前保存的状态 ``` ### 图像资源与性能优化 - **图像资源**:确保使用高质量的 PNG 或矢量图(VectorDrawable)作为心形图标。 - **性能优化**:避免频繁调用 `invalidate()`,可以在动画更新控制刷新频率;同建议使用硬件加速提升绘制效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值