diff --git a/internal/widget/scroller.go b/internal/widget/scroller.go
index 76c6321192..1a7554251f 100644
--- a/internal/widget/scroller.go
+++ b/internal/widget/scroller.go
@@ -222,7 +222,7 @@ func (a *scrollBarArea) CreateRenderer() fyne.WidgetRenderer {
 
 func (a *scrollBarArea) MouseIn(*desktop.MouseEvent) {
 	a.isMouseIn = true
-	a.scroll.Refresh()
+	a.scroll.refreshBars()
 }
 
 func (a *scrollBarArea) MouseMoved(*desktop.MouseEvent) {
@@ -234,7 +234,7 @@ func (a *scrollBarArea) MouseOut() {
 		return
 	}
 
-	a.scroll.Refresh()
+	a.scroll.refreshBars()
 }
 
 func (a *scrollBarArea) moveBar(offset float32, barSize fyne.Size) {
@@ -432,12 +432,13 @@ func (s *Scroll) CreateRenderer() fyne.WidgetRenderer {
 // ScrollToBottom will scroll content to container bottom - to show latest info which end user just added
 func (s *Scroll) ScrollToBottom() {
 	s.scrollBy(0, -1*(s.Content.MinSize().Height-s.Size().Height-s.Offset.Y))
-	s.Refresh()
+	s.refreshBars()
 }
 
 // ScrollToTop will scroll content to container top
 func (s *Scroll) ScrollToTop() {
 	s.scrollBy(0, -s.Offset.Y)
+	s.refreshBars()
 }
 
 // DragEnd will stop scrolling on mobile has stopped
@@ -478,8 +479,11 @@ func (s *Scroll) SetMinSize(size fyne.Size) {
 
 // Refresh causes this widget to be redrawn in it's current state
 func (s *Scroll) Refresh() {
-	s.updateOffset(0, 0)
-	s.refreshWithoutOffsetUpdate()
+	s.refreshBars()
+
+	if s.Content != nil {
+		s.Content.Refresh()
+	}
 }
 
 // Resize is called when this scroller should change size. We refresh to ensure the scroll bars are updated.
@@ -492,6 +496,18 @@ func (s *Scroll) Resize(sz fyne.Size) {
 	s.Refresh()
 }
 
+// SetOffset will update the location of the content of this scroll container.
+//
+// Since: 2.6
+func (s *Scroll) SetOffset(p fyne.Position) {
+	if s.Offset.Subtract(p).IsZero() {
+		return
+	}
+
+	s.Offset = p
+	s.refreshBars()
+}
+
 func (s *Scroll) refreshWithoutOffsetUpdate() {
 	s.Base.Refresh()
 }
@@ -503,6 +519,11 @@ func (s *Scroll) Scrolled(ev *fyne.ScrollEvent) {
 	}
 }
 
+func (s *Scroll) refreshBars() {
+	s.updateOffset(0, 0)
+	s.refreshWithoutOffsetUpdate()
+}
+
 func (s *Scroll) scrollBy(dx, dy float32) {
 	min := s.Content.MinSize()
 	size := s.Size()
@@ -530,10 +551,12 @@ func (s *Scroll) updateOffset(deltaX, deltaY float32) bool {
 	min := s.Content.MinSize()
 	s.Offset.X = computeOffset(s.Offset.X, -deltaX, size.Width, min.Width)
 	s.Offset.Y = computeOffset(s.Offset.Y, -deltaY, size.Height, min.Height)
-	if f := s.OnScrolled; f != nil && (s.Offset.X != oldX || s.Offset.Y != oldY) {
+
+	moved := s.Offset.X != oldX || s.Offset.Y != oldY
+	if f := s.OnScrolled; f != nil && moved {
 		f(s.Offset)
 	}
-	return true
+	return moved
 }
 
 func computeOffset(start, delta, outerWidth, innerWidth float32) float32 {
diff --git a/widget/testdata/entry/wrap_multi_line_truncate.xml b/widget/testdata/entry/wrap_multi_line_truncate.xml
index 6c1447c3da..2b99875431 100644
--- a/widget/testdata/entry/wrap_multi_line_truncate.xml
+++ b/widget/testdata/entry/wrap_multi_line_truncate.xml
@@ -4,20 +4,12 @@
 			<rectangle fillColor="inputBackground" pos="2,2" radius="4" size="116x96"/>
 			<rectangle pos="1,1" radius="4" size="117x97" strokeColor="primary" strokeWidth="2"/>
 			<widget pos="0,2" size="120x96" type="*widget.Scroll">
-				<widget size="292x96" type="*widget.entryContent">
-					<widget size="292x96" type="*widget.RichText">
+				<widget size="120x96" type="*widget.entryContent">
+					<widget size="120x96" type="*widget.RichText">
 						<text pos="8,6" size="276x19">A long text on short words w/o NLs or LFs.</text>
 					</widget>
 					<rectangle fillColor="primary" pos="7,6" size="2x19"/>
 				</widget>
-				<widget pos="120,0" size="0x96" type="*widget.Shadow">
-					<linearGradient angle="270" endColor="shadow" pos="-8,0" size="8x96"/>
-				</widget>
-				<widget pos="0,90" size="120x6" type="*widget.scrollBarArea">
-					<widget pos="0,3" size="49x3" type="*widget.scrollBar">
-						<rectangle fillColor="scrollbar" radius="3" size="49x3"/>
-					</widget>
-				</widget>
 			</widget>
 		</widget>
 	</content>
diff --git a/widget/testdata/entry/wrap_single_line_truncate.xml b/widget/testdata/entry/wrap_single_line_truncate.xml
index c3c7f10909..8122f6f653 100644
--- a/widget/testdata/entry/wrap_single_line_truncate.xml
+++ b/widget/testdata/entry/wrap_single_line_truncate.xml
@@ -10,14 +10,6 @@
 					</widget>
 					<rectangle fillColor="primary" pos="7,6" size="2x19"/>
 				</widget>
-				<widget pos="120,0" size="0x31" type="*widget.Shadow">
-					<linearGradient angle="270" endColor="shadow" pos="-8,0" size="8x31"/>
-				</widget>
-				<widget pos="0,25" size="120x6" type="*widget.scrollBarArea">
-					<widget pos="0,3" size="109x3" type="*widget.scrollBar">
-						<rectangle fillColor="scrollbar" radius="3" size="109x3"/>
-					</widget>
-				</widget>
 			</widget>
 		</widget>
 	</content>