titanium-sdk icon indicating copy to clipboard operation
titanium-sdk copied to clipboard

iOS: ListView header flickers when being updated

Open jonasfunk opened this issue 2 years ago • 5 comments

I have searched and made sure there are no existing issues for the issue I am filing

  • [X] I have searched the existing issues

Description

Updating the header view of listview will cause it to flicker.

https://user-images.githubusercontent.com/1299558/212501809-11880a41-faa4-42b3-86be-ee636dc9f9c0.mov

Expected Behavior

The header view should not flicker

Actual behavior

The header view flickers

Reproducible sample

const win = Ti.UI.createWindow();

const headerView = Ti.UI.createView({ height: 200, backgroundColor: 'red' });

const listView = Ti.UI.createListView({ 
	headerView,
	sections: [ Ti.UI.createListSection({ items: [ {properties: { title: 'Apple'}},{properties: { title: 'Banana'}} ] }) ]
 });

setInterval(() => {
	headerView.height++;
}, 1000);
	

win.add(listView);

win.open();

Steps to reproduce

Install the code on a device (does not happen in simulator) and run it. The issue should be apparent. We've seen this on iPhone 13, but not on earlier versions.

Platform

No response

SDK version you are using

12.0.0.GA.

Alloy version you are using

2.0.1

jonasfunk avatar Jan 14 '23 23:01 jonasfunk

@prashantsaini1 Can you please reproduce this? Trying to get this fixed next week.

hansemannn avatar Apr 24 '25 06:04 hansemannn

@hansemannn @jonasfunk

Findings:

  • This bug is reproducible on simulator as well. Reducing the setInterval duration to 500ms or lower causes faster flickering.

Issue Cause:

  • When the headerView is part of the ListView, there are lots of UI updates happen internally on the entire view hierarchy, even reloading the entire data inside frameSizeChanged in TiUIListView.m class.
  • I tried at 2s interval and the flickering didn't occur. Only noticed it on 1s or lower when updating the UI repeatedly.
  • So the flickering only happens when we do UI updates too often.

Solution:

  • I am not sure what would be the case to do such frequent UI updates. But here's an existing solution already:
  • The replaceSectionAt does not trigger any view updates or data reloads.
  • Moving headerView inside the first ListSection and then updating it using replaceSectionAt makes the flickering gone.

Code without flickering:

const win = Ti.UI.createWindow();

const headerView = Ti.UI.createView({ height: 200, backgroundColor: 'red', top: 0 });
const listView = Ti.UI.createListView({
  style: Ti.UI.iOS.ListViewStyle.GROUPED, // make the headerView non-sticky while scrolling
  sections: [
      Ti.UI.createListSection({
          headerView,
          items: [ {properties: { title: 'Apple'}},{properties: { title: 'Banana'}} ]
      })
  ],
});

setInterval(() => {
  headerView.height += 2;
    
  // this is important to reflect the updated height of the headerView
  listView.replaceSectionAt(0, listView.sections[0]);
}, 100);

win.add(listView);	
win.open();
headerView inside ListView - 100ms headerView inside ListSection - 50ms

prashantsaini1 avatar Apr 25 '25 20:04 prashantsaini1

That makes a lot of sense, thank you! @jonasfunk Can you try one of the two suggestions? We usually use the section based header view solution very successfully.

hansemannn avatar Apr 25 '25 21:04 hansemannn

Thanks for the feedback. I’ve tried to follow the suggestion of using the section header instead. It’s a bigger task since we have quite a few controllers that make up the individual header views. Some of these controllers may trigger frame change events.

The good thing about this approach is that you get animation of height changes.

However, I’m occasionally experiencing that the header height updates correctly, but the content doesn’t follow along — so it gets clipped at its previous height. The image below shows an example of this. The red border defines the headerview, that has gotten the correct height, while the content, defined by the blue border, remains at its height. The layout in the header is vertical - I'm guessing it has something to do with that.

Image

jonasfunk avatar May 01 '25 07:05 jonasfunk

@jonasfunk Can you share a video and some code snippet (exclude private code pieces) of what you're actually trying to achieve?

prashantsaini1 avatar May 01 '25 07:05 prashantsaini1