Android smoothScrollToPosition在RecyclerView上闪烁
我有一个recyclerView,其中列出了在特定事件发生时要滚动到的项目。我使用的是Android smoothScrollToPosition在RecyclerView上闪烁,android,android-recyclerview,Android,Android Recyclerview,我有一个recyclerView,其中列出了在特定事件发生时要滚动到的项目。我使用的是smoothScrollToPosition,但令我惊讶的是,它不仅一点也不平滑,而且我还得到了闪烁效果,就像它必须在实际滚动之前恢复基本位置一样。从这里可以看到效果: 这是正常的行为吗 适配器代码: @ActivityScope class HighlightListAdapter @Inject constructor() : RecyclerView.Adapter<HighlightListAd
smoothScrollToPosition
,但令我惊讶的是,它不仅一点也不平滑,而且我还得到了闪烁效果,就像它必须在实际滚动之前恢复基本位置一样。从这里可以看到效果:
这是正常的行为吗
适配器代码:
@ActivityScope
class HighlightListAdapter @Inject constructor() : RecyclerView.Adapter<HighlightListAdapter.ViewHolder>() {
private var highlights: List<Highlight> = emptyList()
private var itemClick: ((Highlight, Int) -> Unit)? = null
private var selectedRow: MutableList<Int> = mutableListOf()
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = holder.binding
val highlight = highlights[position]
var viewModel = binding.viewModel
viewModel?.unbind()
viewModel = HighlightViewModel(highlight)
binding.viewModel = viewModel
viewModel.bind()
if(selectedRow.contains(position)) {
binding.rootItemView.alpha = 1.0f
}
else {
binding.rootItemView.alpha = 0.5f
}
holder.setClickListener(itemClick)
}
override fun getItemCount(): Int = highlights.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = DataBindingUtil.inflate<ItemHighlightListBinding>(
LayoutInflater.from(parent.context),
R.layout.item_highlight_list,
parent,
false
)
return ViewHolder(binding)
}
fun updateEvents(highlights: List<Highlight>) {
this.highlights = highlights
notifyDataSetChanged()
}
fun setClickListener(itemClick: ((Highlight, Int) -> Unit)?) {
this.itemClick = itemClick
}
fun enableRow(index: Int) {
//Clear previous selection (only if we want single selection)
selectedRow.clear()
//Select specified row
selectedRow.add(index)
//Let the adapter redraw
notifyDataSetChanged()
}
class ViewHolder(val binding: ItemHighlightListBinding) : RecyclerView.ViewHolder(binding.root) {
fun setClickListener(callback: ((Highlight, Int) -> Unit)?) {
binding.viewModel.clicks().subscribe {
callback?.invoke(binding.viewModel.highlight, adapterPosition)
}
}
}
fun getSelected() = selectedRow
}
@ActivityScope
类HighlightListAdapter@Inject构造函数():RecyclerView.Adapter(){
private var highlights:List=emptyList()
私有变量项单击:((高亮显示,Int)->单位)?=null
私有变量selectedRow:MutableList=mutableListOf()
覆盖BindViewHolder(holder:ViewHolder,位置:Int){
val binding=holder.binding
val highlight=突出显示[位置]
var viewModel=binding.viewModel
viewModel?.unbind()
viewModel=高亮显示viewModel(高亮显示)
binding.viewModel=viewModel
viewModel.bind()
if(selectedRow.contains(位置)){
binding.rootItemView.alpha=1.0f
}
否则{
binding.rootItemView.alpha=0.5f
}
holder.setClickListener(itemClick)
}
重写getItemCount():Int=highlights.size
override onCreateViewHolder(父级:ViewGroup,viewType:Int):ViewHolder{
val binding=DataBindingUtil.inflate(
LayoutFlater.from(父上下文),
R.layout.项目突出显示列表,
父母亲
假的
)
返回视图保持器(绑定)
}
趣味更新事件(亮点:列表){
this.highlights=高光
notifyDataSetChanged()
}
趣味设置ClickListener(项单击:((突出显示,Int)->单位)?){
this.itemClick=itemClick
}
趣味使能行(索引:Int){
//清除以前的选择(仅当需要单个选择时)
selectedRow.clear()
//选择指定的行
selectedRow.add(索引)
//让适配器重新绘制
notifyDataSetChanged()
}
类ViewHolder(val绑定:ItemHighlightListBinding):RecyclerView.ViewHolder(binding.root){
有趣的设置ClickListener(回调:((突出显示,Int)->单位)?){
binding.viewModel.clicks().subscribe{
回调?.invoke(binding.viewModel.highlight,adapterPosition)
}
}
}
fun getSelected()=selectedRow
}
布局文件:
我认为问题在于启用行notifyDataSetChanged()。它会刷新整个数据集,从而导致列表的翻转。请尝试此操作
fun enableRow(index: Int) {
//Clear previous selection (only if we want single selection)
selectedRow.clear()
//Select specified row
selectedRow.add(index)
//Let the adapter redraw
notifyItemRangeChanged(index,highlights.size())
}
我认为问题出在enable row notifyDataSetChanged()中。它刷新整个数据集,从而导致列表的翻转。请尝试此操作
fun enableRow(index: Int) {
//Clear previous selection (only if we want single selection)
selectedRow.clear()
//Select specified row
selectedRow.add(index)
//Let the adapter redraw
notifyItemRangeChanged(index,highlights.size())
}
发布一些代码。发布你的适配器代码完成,不确定是否有帮助。发布一些代码。发布你的适配器代码完成,不确定是否有帮助。好吧,这似乎以某种方式解决了问题,但问题是我确实需要更新所有行,因为我只想选择一行(选择意味着用户界面与所选行不同),我无法清楚地理解,但是,如果您觉得这有助于您对答案进行投票,请再次投票。notifyDataSetChanged()和notifyItemRangeChanged()非常相似,这会刷新数据列表。我的意思是,列表中选定的项目会以不同的颜色显示。因此,每次选择(并滚动到)新事件时,其他项目都需要刷新,以便显示为未选择。如果我照你说的做,我只会刷新从所选项目开始的一系列项目,从而使以前选择的项目保持选中状态。你听说过稀疏布尔数组吗?维护布尔数组。每当你单击某个位置时,在布尔数组中将该位置存储为true,然后用数组中的位置检查绑定持有者的位置。没关系,让它工作起来了,谢谢@Anonymous找到问题。这似乎以某种方式解决了问题,但问题是我确实需要更新所有行,因为我只想选择一行(选择意味着所选行的UI不同),我无法清楚地告诉你,但是,如果您觉得这有助于您对答案进行投票,请再次投票。notifyDataSetChanged()和notifyItemRangeChanged()非常相似,这会刷新数据列表。我的意思是,列表中选定的项目会以不同的颜色显示。因此,每次选择(并滚动到)新事件时,其他项目都需要刷新,以便显示为未选择。如果我照你说的做,我只会刷新从所选项目开始的一系列项目,从而使以前选择的项目保持选中状态。你听说过稀疏布尔数组吗?维护布尔数组。每当你单击某个位置时,在布尔数组中将该位置存储为true,然后用数组中的位置检查绑定持有者的位置。没关系,让它工作起来了,谢谢@Anonymous找到问题