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

使用Fyne List组件时显示异常,我哪里操作有误?

问题原因与解决方案

为什么会出现显示错乱?

这不是List或滚动组件的Bug,是canvas.Text组件的使用场景不匹配导致的:

  • canvas.Text是纯绘图类组件,不属于标准Widget范畴,它没有实现Widget接口里的自动刷新触发逻辑。List滚动时会复用已创建的列表项组件,当你更新Text内容后,组件不会主动通知系统重绘,只有鼠标移到组件上触发交互时,才会触发重绘显示正确内容。
  • 另外,canvas.Text没有默认的最小尺寸,List无法正确计算每个列表项的高度,也会加剧复用和布局时的异常。

修复方案(两种可选)

方案1:给canvas.Text手动添加刷新触发

在List的UpdateItem回调里,设置完Text后调用组件的Refresh()方法强制触发重绘,同时给canvas.Text指定固定高度,让List能正确计算项高:

package main

import (
	"fmt"
	"image/color"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/widget"
)

func main() {
	App    := app.New()
	Window := App.NewWindow("List Widget")
	data   := []string{}
	Window.Resize(fyne.NewSize(150, 200))

	// 定义列表项的固定高度
	itemHeight := float32(20)

	list := widget.NewList(
		func() int { return len(data) },
		func() fyne.CanvasObject {
			text := canvas.NewText("", color.Black)
			// 设置最小尺寸,让List能正确计算项高
			text.SetMinSize(fyne.NewSize(0, itemHeight))
			return text
		},
		func(id widget.ListItemID, obj fyne.CanvasObject) {
			text := obj.(*canvas.Text)
			text.Text = data[id]
			// 手动触发刷新,强制重绘
			text.Refresh()
		},
	)

	for i := 0; i <= 100; i++ {
		data = append(data, fmt.Sprintf("Number %3d", i))
	}
	list.Refresh()

	Window.SetContent(list)
	Window.Show()
	App.Run()
}

方案2:自定义轻量Widget替代Label

如果觉得Label高度太大,可以自定义一个轻量的文本Widget,基于canvas.Text实现必要的Widget方法,既能保持紧凑高度,又能兼容List的复用逻辑:

import (
	"image/color"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/widget"
)

type CompactText struct {
	widget.BaseWidget
	Text     string
	Color    color.Color
	TextSize float32
}

func NewCompactText(text string, color color.Color) *CompactText {
	t := &CompactText{Text: text, Color: color, TextSize: 14}
	t.ExtendBaseWidget(t)
	return t
}

func (t *CompactText) CreateRenderer() fyne.WidgetRenderer {
	text := canvas.NewText(t.Text, t.Color)
	text.TextSize = t.TextSize
	return widget.NewSimpleRenderer(text)
}

func (t *CompactText) SetText(text string) {
	t.Text = text
	t.Refresh()
}

然后在List里使用这个自定义组件:

list := widget.NewList(
	func() int { return len(data) },
	func() fyne.CanvasObject { return NewCompactText("", color.Black) },
	func(id widget.ListItemID, obj fyne.CanvasObject) {
		obj.(*CompactText).SetText(data[id])
	},
)

关于数据绑定的问题

如果用数据绑定后无法清空切片,建议直接操作绑定的数据源(比如binding.StringList),调用Set([]string{})来清空,而不是直接修改切片。例如:

data := binding.NewStringList()
// 清空时
data.Set([]string{})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:42:34