You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Android中Invalidate()未触发OnDraw()问题求助

解决触摸按下时重绘不立即触发的问题

看起来你遇到的问题是触摸事件处理中,Invalidate()的重绘请求被延迟到触摸抬起后才执行,导致按下状态的图片始终看不到。这是因为Android的UI线程消息循环机制:触摸事件的处理是在UI线程执行的,直接调用Invalidate()只是标记视图需要重绘,实际的OnDraw()会等待当前触摸事件处理完成后才会执行。如果抬起事件紧接着触发并也调用了重绘,就会覆盖按下状态的绘制请求。

下面是具体的解决方案和优化代码:

1. 核心修复:确保按下事件的重绘优先执行

修改你的触摸事件处理逻辑,用Post()将重绘请求加入UI消息队列,让它在当前触摸事件处理过程中就被调度执行,同时要正确标记事件已处理:

private void MyView_Touch(object sender, TouchEventArgs e)
{
    var myView = sender as View;
    if (myView == null) return;

    switch (e.Event.Action)
    {
        case MotionEventActions.Down:
            // 设置按下状态的图片
            SetSelectedPart(Resource.Drawable.Green);
            // 使用Post将重绘请求放到消息队列,确保当前事件流程中触发OnDraw
            myView.Post(() => myView.Invalidate());
            // 返回true,告知系统当前View要处理后续触摸事件
            e.Handled = true;
            break;
        case MotionEventActions.Up:
            // 设置抬起状态的图片
            SetSelectedPart(Resource.Drawable.YourDefaultDrawable);
            myView.Invalidate();
            e.Handled = true;
            break;
        case MotionEventActions.Cancel:
            // 触摸被中断时也要恢复默认状态
            SetSelectedPart(Resource.Drawable.YourDefaultDrawable);
            myView.Invalidate();
            e.Handled = true;
            break;
        default:
            e.Handled = false;
            break;
    }
}

2. 确保SetSelectedPart和OnDraw逻辑正确

检查你的SetSelectedPart方法是否正确初始化了Drawable,并且OnDraw中正确绘制它:

private Drawable _currentDrawable;

private void SetSelectedPart(int drawableResId)
{
    // 获取Drawable并设置正确的绘制边界
    _currentDrawable = Resources.GetDrawable(drawableResId);
    _currentDrawable.SetBounds(0, 0, Width, Height);
}

protected override void OnDraw(Canvas canvas)
{
    base.OnDraw(canvas);
    // 确保Drawable不为空时才绘制
    if (_currentDrawable != null)
    {
        _currentDrawable.Draw(canvas);
    }
}

为什么这样有效?

  • myView.Post(() => myView.Invalidate()):将重绘请求异步投递到UI线程的消息队列,这样它会在当前触摸事件处理的间隙被执行,而不是等到整个触摸事件序列(Down→Up)处理完。
  • e.Handled = true:在Down事件中返回true,确保当前View能接收后续的Up/Cancel事件,避免系统将触摸事件传递给父容器,保证状态切换的完整性。
  • 处理MotionEventActions.Cancel:当触摸被系统中断(比如滑动到其他控件)时,也能恢复默认状态,避免图片停留在按下状态。

内容的提问来源于stack exchange,提问作者Praddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:32:55