自定义控件invalidate()方法未成功调用onDraw()

在Android自定义控件开发中,通常使用invalidate()方法请求重绘并调用onDraw()。然而,当作者尝试实现一个在事件触发后能展开或缩回的控件时,发现展开时onDraw()并未被调用。问题在于控件大小在onDraw()内改变,导致系统认为控件不需要重绘,因为其大小始终为0。解决办法是将大小修改操作移到invalidate()之前,确保控件大小不为0且可见,从而正确触发onDraw()。

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

写过自定义控件的大家都知道invalidate方法是Android请求重绘的方法。所以会调用到我们自己重写的onDraw方法。

但是在我最近写的一个控件时却没有调用他的onDraw方法。我所重写的控件需求是在触发事件后控件可以展开或是缩回

准确的说 是在我展开他的时候没有触发他的onDraw方法。


测试时的效果是我在点击展开时,没有反应。再次点击触发缩回 却会开到控件直接变为最大 之后再次收回。

public Handler updateHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        switch (slideFlag){
            case HORIZONTAL_SLIDE:
                AutoMoveX();
                if(xcloseTask)
                    closeTask();
                break;
            case VERTICAL_SLIDE:
                AutoMoveY();
                if(ycloseTask)
                    closeTask();
                break;
            case ALL_SLIDE:
                AutoMoveX();
                AutoMoveY();
                if(xcloseTask || ycloseTask){
                    if(ViewShowFlag){
                        nowViewHeight = maxViewHeight;
                        nowViewWidth  = maxViewWidth;
                    }else{
                        nowViewHeight = minViewHeight;
                        nowViewWidth  = minViewWidth;
                    }
                    closeTask();
                }
                break;
        }
        invalidate();
    }

};

@Override
protected void onDraw(Canvas canvas) {
    	super.onDraw(canvas);
	switch (slideFlag){
    	case HORIZONTAL_SLIDE:
       	    this.setLayoutParams(new LayoutParams(nowViewWidth, maxViewHeight));
    	    break;
    	case VERTICAL_SLIDE:
    	    this.setLayoutParams(new LayoutParams(maxViewWidth, nowViewHeight));
    	    break;
    	case ALL_SLIDE:
            this.setLayoutParams(new LayoutParams(nowViewWidth, nowViewHeight));
            break;
    	default:
	    this.setLayoutParams(new LayoutParams(maxViewWidth, maxViewHeight));
	}
}


其中我在log,debug中都没有发现其中的问题。过程中我所设置的控价大小,标示等都符合我所希望的情况。


之后为了 更好的了解到发生了什么,我吧每次调用重绘的时间间隔加长,吧展开与缩回的控制分离。再次测试后发现

如果我连续触发两次张开的事件就可以正常打开。现在的问题就是为什么只有在打开控件的时候不能触发


这个时候我注意到这个情况是控件从0开始一步一步到完全打开。这就是问题所在:

Android的机制中在绘制前会判断控件是否需要重新绘制的。条件是不透明且大小不为0。

而在我的程序中控件大小改变(告知给系统)是在onDraw方法内。这就导致了控件一直是0的大小不会触发onDraw方法

知道原因后处理就简单了,我们只需要把大小的修改完成在invalidate之前就可以避免了。

switch (slideFlag){
    	case HORIZONTAL_SLIDE:
       	    this.setLayoutParams(new LayoutParams(nowViewWidth, maxViewHeight));
    	    break;
    	case VERTICAL_SLIDE:
    	    this.setLayoutParams(new LayoutParams(maxViewWidth, nowViewHeight));
    	    break;
    	case ALL_SLIDE:
            this.setLayoutParams(new LayoutParams(nowViewWidth, nowViewHeight));
            break;
    	default:
	    this.setLayoutParams(new LayoutParams(maxViewWidth, maxViewHeight));
	}

        invalidate();
修改后控件就可以正常运行了。


吧大小修改写在onDraw中没有任何问题 但是要保证控件当前的大小不是0并且你没有隐藏他

        invalidate();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值