Skip to content

Conversation

@johnzhou721
Copy link
Contributor

@johnzhou721 johnzhou721 commented Jun 23, 2025

Fixes #3580.

Will replace screenshot with version that the Screenshot example app generates.

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

@johnzhou721
Copy link
Contributor Author

I have no idea why but it seems like the widths are a huge mess.

@freakboy3742 Any ideas on how to solve this? It looks like the dateInput width returned is messy...

Screen.Recording.2025-06-22.at.9.12.49.PM.mov

And they have weird formatting as well...

@freakboy3742
Copy link
Member

The date is always the right width; but that width is not being propagated into a new layout. I'd bet that if you resize the window after each change, the text will move to a consistent location.

That suggests the problem is that refresh() isn't being invoked as a result of a value change. This won't be an issue on Winforms, because the widget has a fixed size; it's only an issue on iOS because a change in date changes the rendering size.

@johnzhou721
Copy link
Contributor Author

Hmm… might try layoutSubviews method tonight.

@johnzhou721
Copy link
Contributor Author

@freakboy3742 FYI: You should go ahead and investigate this when you have time. I think if this doesn't work we can make a note about its width.

@johnzhou721
Copy link
Contributor Author

After much playing around, I decided to ask the Apple Engineers to see what they say about this.

Refs https://developer.apple.com/forums/thread/790220

@johnzhou721
Copy link
Contributor Author

FYI: Gotten no satisfactory responses yet...

Alternative plan would be to:

  • Align the DateInput/TimeInput to the right when layout out right-to-left so they expand to the left, and inform users to not put things to the right of the inputs in LTR and not to the left in RTL.

However I'd rather not do that since I could think of some usecases for having text to the right (for example, a history app that quizzes you important dates using DateInput as cloze)

@freakboy3742
Copy link
Member

Yeah - trying to work around this with alignment strikes me as the wrong approach. There's a low level widget sizing issue that we need to sort out; any fix will be in that area.

(Side note - I'm on leave until July 8, so I won't be as responsive as normal for the next week or so)

Copy link
Contributor Author

@johnzhou721 johnzhou721 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this?

@johnzhou721
Copy link
Contributor Author

johnzhou721 commented Jun 29, 2025

@freakboy3742 with some further experimentation, it seems that with the latest code every time it's returning the correct width, but sometimes the behavior is still weird. I've clicked different sequences of buttons, and sometimes it collapses into mm/dd/yyyy and sometimes it doesn't, all with the same returned fitting width EDIT for each date.

---EDIT: edited onto wrong thread the last time.---

@johnzhou721
Copy link
Contributor Author

@freakboy3742 In case it's not clear from my comment(s) 5 hours ago: I think I've found a fix to this problem but the API it uses (setting width directly rather than a hint) is definitely not acceptable -- and I need to work out why setting it through the size hint does not work.

@johnzhou721 johnzhou721 marked this pull request as ready for review September 6, 2025 03:15
@johnzhou721
Copy link
Contributor Author

Apparently I'm stupid. Never occured to me to call refresh on interface which works. Ready for review now, sorry for wasting time.

def set_value(self, value):
self.native.date = native_date(value)
self.interface.on_change()
self.native.sendActionsForControlEvents(UIControlEventValueChanged)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this because the logic is now sort of complex... call on_change, invalidate existing fitting width, and calling a refresh when there's a change. Duplicating in TimeInput, DateInput, and TogaDatePicker will make maintenance more complex, and we also get more semantic here by saying "do whatever is done when the value changed" instead of "invoke the on change handler, invalidate width, and refresh".

Copy link
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So - it's very difficult to review this because it's not at all clear what it's doing, and why.

  1. There's a setNeedsLayout() and layoutIfNeeded() call whenever the value changes
  2. The layout has been changed to use fitting size exclusively, rather than MIN_SIZE.
  3. Widget alignment has been changed to centered

I think (1) makes conceptual sense, but the code could do with comments explaining why this is needed, and the sequence of things that will happen as a result of those calls (if I'm understanding correctly - value change means the widget could be bigger; setNeedsLayout marks the widget as dirty; layoutIfNeeded forces a recompute of the layout geometry at the iOS level; refresh forces new layout hints at the Toga level, and the new size then takes effect).

(2) also makes sense - but the MIN SIZE should still be there - If the fitting size is less than MIN_SIZE, we should be setting to MIN_SIZE.

I have no idea why (3) is required. It seems like something that (a) shouldn't affect the size of the widget, but it would affect the display of the widget, in a way that is inconsistent with all other platforms. If it's a required part of the process, that should definitely be documented inline; and if it won't affect display, that should also be documented.

Copy link
Contributor Author

@johnzhou721 johnzhou721 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my own benefit.

@johnzhou721
Copy link
Contributor Author

johnzhou721 commented Sep 8, 2025

  • There's a setNeedsLayout() and layoutIfNeeded() call whenever the value changes

Resolved.

  • The layout has been changed to use fitting size exclusively, rather than MIN_SIZE.

Not sure about this one, as the iOS picker widgets have a fixed amount of gray area depending on the date regardless of what width you set it to. So like if we force a MIN_SIZE (which is greater than ANY fitting width the picker can take on) that means there will always be extra white area to the right of the Date / Time Picker. If that's what you want, tell me and I will proceed with the changes (but since the native fitting size is always smaller than our imposed MIN_SIZE it means that this PR will just have no effect at all.)

  • Widget alignment has been changed to centered

Resolved..

Thank you for your assitance on this patch.

EDIT -- appears that we're having another GitHub snow day...

@freakboy3742
Copy link
Member

  • The layout has been changed to use fitting size exclusively, rather than MIN_SIZE.

Not sure about this one, as the iOS picker widgets have a fixed amount of gray area depending on the date regardless of what width you set it to. So like if we force a MIN_SIZE (which is greater than ANY fitting width the picker can take on) that means there will always be extra white area to the right of the Date / Time Picker. If that's what you want, tell me and I will proceed with the changes (but since the native fitting size is always smaller than our imposed MIN_SIZE it means that this PR will just have no effect at all.)

Hrm; I guess if the minimum size is guaranteed to be a "reasonable minimum", then the MIN_SIZE constraint won't be needed . I agree that given the what iOS renders dates/times, the extra padding could be confusing.

EDIT -- appears that we're having another GitHub snow day...

I've restarted the failed tests.

Copy link
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - I'm happy with this now. Thanks for the investigation work and PR.

@freakboy3742 freakboy3742 merged commit 61b381d into beeware:main Sep 9, 2025
49 checks passed
@johnzhou721
Copy link
Contributor Author

You're welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow iOS DateInput and TimeInput widgets to fit snugly

2 participants