RecyclerView局部刷新视图导致闪烁
问题:RecyclerView 调用notifyItemChanged()方法更新单个Item时,此Item有闪烁 因为RecyclerView 默认实现了一个DefaultItemAnimator,如果RecyclerView 的item布局过于复杂且包含 重新测量等复杂步骤的时候,就会产生闪烁。所以最好的解决办法就是不产生动画效果。 看到网上有很多的设置方法。最常见的是关闭,是这么写的。
recyclerView.getItemAnimator().setAddDuration(0);
recyclerView.getItemAnimator().setChangeDuration(0);
recyclerView.getItemAnimator().setMoveDuration(0);
recyclerView.getItemAnimator().setRemoveDuration(0);
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
解决:以上方法,不知道大家是否可以,但是我测下来还是有点问题,虽然动画间隔设置为了0,但是还是有执行动画的操作,所以简单粗暴的设置方法,直接设置animator为null。简单有效
recyclerView.setItemAnimator(null);
TextView设置多行后ellipsize失效的问题
问题:我这里要求是设置textview最多展示两行,然后多出来的中间显示省略号,xml布局设置了maxlines = 2,ellipsize="middle"但是没有效果。。。。。 没办法只能自己实现了。最终决定借助ViewTreeObserver来实现这个效果 当监听到布局完成之后,获取到textView当前的总行数。判断如果大于需要限定的行数,就开始处理。首先使用getLineEnd获取指定行最后一个字符后的文本偏移量(文字数量)。根据获取到的文字数量截取字符串,然后重新设置textview就可以了。 解决:具体代码如下所示:
open fun dealMiddleNoEffect(tv: TextView, lines: Int = 2) {
val viewTreeObserver = tv.viewTreeObserver
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (viewTreeObserver.isAlive) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
}
if (viewTreeObserver.isAlive && tv.lineCount > lines) {
val lineEnd = tv.layout.getLineEnd(lines)
val allText = tv.text
val text = lineEnd.let {
val i = (it - 3) / 2
"${allText.substring(0, i)}...${allText.substring(allText.length - i + 3, allText.length)}"
}
tv.text = text
}
}
})
}
扩展一下:在onCreate中获取view的宽高? 方法一:使用MeasureSpec进行测量,如下所示:
fun calculateViewWidthAndHeight(view: View): Pair<Int, Int> {
val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
view.measure(measureSpec, measureSpec)
return view.measuredWidth to view.measuredHeight
}
方法二:使用ViewTreeObserver 来获得宽高,当获得正确的宽高后,移除观察者,否则会调会多次执行
val observer = view.viewTreeObserver
observer.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (observer.isAlive) {
observer.removeOnGlobalLayoutListener(this)
val viewWidth = view.measuredWidth
val viewHeight = view.measuredHeight
}
}
})
val observer = view.viewTreeObserver
observer.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (observer.isAlive) {
observer.removeOnPreDrawListener(this)
}
val viewWidth = view.measuredWidth
val viewHeight = view.measuredHeight
return true
}
})
|