Android setText 出现文本重叠的问题

本文讲述了作者在Android系统级应用中遇到的TextView重叠问题,通过自定义View和onDraw方法、清空画布以及设置WindowManager背景透明,最终解决了在无Activity容器的Service中添加导航栏时的文本重叠问题。
一、今天在做NavigatorBar(导航栏,系统级应用)时,遇到一个问题,在调用TextView.setText方法后,会出现文本重叠的问题,如下图所示:

在这里插入图片描述


二、我的实现场景比较特殊,我的导航栏是无Activity做为容器的,在Service中,直接通过WindowManager.addView()添加NavigatorBar,而NavigatorBar本身是一个自定义View,直接继承自FrameLayout实现的。所以,我的NavigatorBar的getParent()返回的是ViewRootImpl,而不是传统的DecorView。

我的整体排查思路如下:

  1. TextView的实例是否有过变化?,经log查看,确实是同个实例。
  2. 是否有2个TextView存在,导致重叠? 经log查看,只有一个TextView。
  3. 在setText之后,打印text,看看打出来的text是不是最新的?经log查看,是最新的text,出现重叠是旧的text没被清除而留下来的残影。
  4. 调用invalidate()方法,有效? 不起作用。
  5. 尝试调用WindowManager的updateViewLayout,不起作用。(除非修改长宽,但这个会导致闪烁,用户体验不佳)
  6. 改成动态添加TextView,每次设置文本,都先remove现有的,再创建个新的。结果,仍然不起作用。
  7. 在网上搜索相同问题,查出来的文章,有的说,给根布局设置背景,比如,这篇:Android 绘制产生重影(重叠)。后面,经实验,设置个非透明的颜色,比如黑色,白色,都可以,但透明、半透明、不设置,都不行。如果可以给根布局设置纯色背景,那问题到此可以解决。
  8. 但像我这种业务场景的话就不行,原因是一旦某个app设置了跟我背景色不一致的颜色,就会出现颜色相左的问题 【详见图1】 ,如图所示,一条黑条横在页面中间。既然不行,那就继续排查。

在这里插入图片描述


  1. 重新屡了一下思路: 首先,Navigator是自定义View。自定义View就会走onDraw(),那么,我是不是可以考虑在onDraw里面做什么清除操作,或者自已绘制文本,不用TextView,就没这问题了?然后,我就重写Navigator(FrameLayout的子类)的onDraw()方法,并加log。但发现,onDraw方法,并没有被触发。后面,想起来,以前做继承自ViewGroup的自定义View时,也遇到过onDraw没被调用过,原因是ViewGroup默认是不触发draw的,源码如下所示:
 // 摘自 ViewGroup。
 private void initViewGroup() {
   
   
        // ViewGroup doesn't draw by default
        if (!isShowingLayoutBounds()) {
   
   
            setFlags(WILL_NOT_DRAW, DRAW_MASK);
        }
        .... 省略其它
 }

  1. FrameLayout直接继承自ViewGroup,默认也是没有调onDraw方法。问题搞清楚了,我们现在只需要加这行代码,就可以触发ViewGroup/FrameLayout/NavigatorBar的onDraw()方法:
   // 摘自 NavigatorBar
   init {
   
   
        setWillNotDraw(false)
   }

  1. 现在,NavigatorBar的onDraw方法有触发了,但重叠问题仍然存在。此时,我第一个猜想是,这个重叠,既然是个残影,即上个绘制没有被清空导致的。那我加上清空画布的代码,是不是就OK了?然后,我就在onDraw方法里面加上清空画布的代码,如下所示:
  // 摘自 NavigatorBar
  override fun onDraw(canvas: Canvas) 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值