Skip to content

Releases

SkiaUi.Maui 1.11.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 19:42

New features

  • .NET 11 and MAUI 11: SkiaUi.Maui, SkiaUi.Maui.CommunityToolkit, SkiaUi.Maui.Markdown and SkiaUi.Maui.Markdown.Math target net11.0-* with MAUI 11.0.10 (Community Toolkit 17.0.0) next to net10.0-* with MAUI 10, so .NET 10 apps keep restoring the net10 assets and never see MAUI 11. The net11 assets need Android 7.0 (API 24) and build with .NET SDK 11.0.100 and Xcode 27.2; the other minimum OS versions are unchanged. Details and the behaviour differences between the lines: ImplementationPlan-1.11.md.

Breaking changes

  • The net10 assets need MAUI 10.0.130: all four packages' net10.0-* assets now reference MAUI 10.0.130 (was 10.0.120). A .NET 10 app with its own Microsoft.Maui.Controls reference below 10.0.130 must raise it, or restore fails with NU1605 (package downgrade). MAUI 10.0.130 leaves room for a shape's stroke only when it has one (dotnet/maui#37319): a drawn shape without Stroke (both layers) now fills its bounds and measures without StrokeThickness, as MAUI's shapes do, and a stroke appearing or going measures it again.

Other

  • Demo Release builds measure without MAUI's visual tree diagnostics: the demo's profiling default sets a diagnostic endpoint, which also turned on MAUI's visual tree diagnostics; those look up each new child's index among its siblings, so building a layout of N children cost O(N²) (a 1,000-button grid built 4× slower on .NET 11 iOS). Non-Debug builds with profiling on now set EnableMauiDiagnostics=false and keep the endpoint; Testing.md explains how to do the same in an app.
  • Headless test suite flake: SamplesTests.EveryExamplePageIsOneDrawnSurfaceThatLaysOutAndDraws failed about one run in three with Collection was modified while disposing a surface. The Markdown example's background build handed its result to SkUiTestHelpers.UseTestDispatcher(), whose Dispatch ran it inline on the calling pool thread, so the document's Core tree changed while the test tore it down. The package is unchanged (with a real dispatcher the result goes on the UI thread); the test now uses the new SkUiTestHelpers.UseUiThreadDispatcher(), which queues work dispatched from other threads until TestDispatcherProvider.RunDispatched(), plus a TestUiContext for the examples' own async continuations, and ABackgroundMarkdownBuildChangesTheTreeOnlyOnTheUiThread checks the hand-over.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.10.3

Choose a tag to compare

@github-actions github-actions released this 12 Nov 15:58

Fixes

  • Simulated taps whose handler ends the press (#95): SkUiDiagnostics.SimulateTap(element, releaseOnlyIfTap) and SimulateTapAt reported Winner: null and IsTap: false for a tap that ran when its own handler ended the press while it ran: it opened a popup or navigated (cancelling the surface's pointers), disabled its control, or removed it from the tree. They now report the recognizer that took the tap. The gesture arena ends once per pointer and keeps the release's winner when the release's handlers take it out; a recognizer that gives up the release itself (a scroller after a press that did not move) still leaves Winner empty, and so does a control disabled before the release.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.10.2

Choose a tag to compare

@github-actions github-actions released this 11 Nov 16:36

New features

  • Simulated taps report what took them (#93): SkUiDiagnostics.SimulateTapAt(root, rootPoint, releaseOnlyIfTap = true) and SkUiDiagnostics.SimulateTap(element, releaseOnlyIfTap) return an SkUiSimulatedTap, so automation can report a tap truthfully instead of "succeeding" on a label inside a scroller, a disabled control or a control without a tap.
    • Hit (the element hit, as before), Winner (the recognizer that won the press), IsTap (the winner completes on release: taps, a control's own tap, slider / stepper taps, text fields), PassedToNative (a real touch would reach native views around the surface: a parent's tap recognizer, or a hosted native view, which is not pressed; per platform, as each surface hands touches on) and Released.
    • releaseOnlyIfTap: a press that a release without movement would not turn into a tap is cancelled instead of released, so a failed tap has no side effects (no fling, no pressed state left behind).
    • SimulateTap(element, releaseOnlyIfTap) also cancels a press another element's recognizer would take (drawn over the element, or at its center while it is scrolled out of view), even without releaseOnlyIfTap; Winner names it.
    • SimulateTap(element) is unchanged (returns the hit, always releases), except that a native view hosted on the surface (SkUiMauiContentView) is no longer pressed through to the drawn content under it.
  • DevFlow extension for apps: the dev.skiaui DevFlow agent extension the demo uses (a tree of drawn elements with window bounds, taps, hit-testing) is now ready to copy into any app that uses SkiaUi. The new docs/DevFlow.md covers setup, and the new skiaui-devflow agent skill (/plugin install skiaui-devflow@skiaui) does it for you. It isn't a NuGet package because the DevFlow agent is still in preview.
    • Taps report whether a drawn tap recognizer took them (taken, winner, passedToNative, released). A press that isn't a tap is cancelled unless force is set, and a press another element would take (the target is covered or scrolled out of view) is cancelled and reported as coveredBy.
    • A new tapAt tool taps the drawn content at a window point.

Fixes

  • Toggles: one-way bindings on CheckState, IsChecked or IsToggled stop updating after their first change (#92): the control wrote the state back to its own bindable property with a plain SetValue, whose specificity outranks a binding's, so later values from the binding were stored below it and never applied (a three-state "select all" box bound one-way stayed on the dash). Check boxes, radio buttons and switches now skip writing a value the property already holds and write derived values (taps, the other view of the state) as handler values, as MAUI's own controls do: two-way bindings still get them, and the next value from a one-way binding, a style or the app replaces them.
  • Input controls: one-way bindings stop updating after the first user change (the rest of #92's bug class): controls wrote user changes and derived values back to their own bindable properties with a plain SetValue (or the CLR setter), whose specificity outranks a binding's, so later values from a one-way binding were stored below it and never applied. They are now written as handler values (SetValueFromRenderer, as MAUI's own controls do) and skipped when the property already holds them: two-way bindings still get them, and the next value from a one-way binding, a style or the app replaces them.
    • SkUiSlider.Value (drag, tap, screen reader, range clamp); SkUiStepper.Value and SkUiStepper<T>.Value (buttons, keys, screen reader, range changes).
    • SkUiEntry / SkUiEditor / SkUiSearchBar Text (typing, MaxLength cuts, TextTransform, formatters), CursorPosition and SelectionLength (the user's selection), SkUiEntry.IsPasswordRevealed (the reveal button); SkUiNumericEntry<T>.Value and the text it shows.
    • SkUiPicker.SelectedIndex / SelectedItem, SkUiPickerColumn.SelectedIndex / SelectedItem, SkUiDatePicker.Date, SkUiTimePicker.Time, SkUiDateTimePicker.Date (popup choices, clearing, range clamps) and every picker's IsOpen (taps, closing). SkUiPickerColumn now derives from Element (was BindableObject) to write handler values; its API is otherwise unchanged.
    • SkUiCollectionView.SelectedItem (taps, keys, the selection mode, removed items), IsLoadMoreActive and IsRefreshing; SkUiCarouselView.Position / CurrentItem (swipes, ScrollTo, the linked indicator); SkUiIndicatorView.Position (taps, keys, screen reader, the linked carousel, a count clamp); SkUiExpander.IsExpanded (header taps); SkUiRefreshView.IsRefreshing (pulls, automatic completion, disabling).
    • The group layout's RadioButtonGroup.SelectedValue (a radio button checked), and the uniform CornerRadius that follows CornerRadii on labels, image buttons, entries and pickers.

Other

  • Built with Xcode 27.2: CI and the packages build with workload set 10.0.404 (iOS / Mac Catalyst 27.2 SDKs, Xcode 27.2 on the xcode-27 image) instead of 10.0.402.1 (Xcode 27.1); the Xcode 26.6 build (10.0.401) stays. The library still compiles against the iOS / Mac Catalyst 26.0 SDK, so apps keep building with Xcode 26.6, 27.1 or 27.2.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.10.1

Choose a tag to compare

@github-actions github-actions released this 11 Nov 11:53

Fixes

  • Check box and radio button: a look can set the unchecked colors (#90): an unchecked check box's outline and fill and an unselected radio button's ring were hard-coded (the color scheme's Muted, white), so matching a design system meant re-implementing DrawCheckBoxCore. They now come from the look's virtual SkUiLook.CheckBoxBorderColor, CheckBoxBackgroundColor and RadioButtonRingColor, whose defaults are the old colors; both layers, still at half alpha while disabled.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.10.0

Choose a tag to compare

@github-actions github-actions released this 11 Nov 07:15

New features

  • Community Toolkit layouts: SkUiDockLayout and SkUiUniformItemsLayout in SkiaUi.Maui.CommunityToolkit (namespace MauiSkiaUi.CommunityToolkit), drawn counterparts of the toolkit's DockLayout and UniformItemsLayout laid out by the toolkit's own layout managers, so toolkit pages port by changing the prefix: SkUiDockLayout.md, SkUiUniformItemsLayout.md.
    • SkUiDockLayout: ShouldExpandLastChild, HorizontalSpacing, VerticalSpacing, Add(view, position); children keep the toolkit's attached DockLayout.DockPosition, and changing it re-lays the dock out.
    • SkUiUniformItemsLayout: MaxRows, MaxColumns. Unlike the toolkit's layout, cells follow the first child when it changes size, and children past MaxRows × MaxColumns are hidden instead of keeping an old frame.
    • The migration checker suggests them for the toolkit's layouts in drawn trees; the gallery shows each beside the toolkit's own.
  • Keyboard navigation in collection views: an interactive SkUiCollectionView is one tab stop with a current item, as native lists are: Keyboard.
    • Arrow keys move it (in grids also across, keeping the column; mirrored right to left), Home / End to the ends, Page Up / Page Down by the part of the viewport sticky parts leave uncovered; each move scrolls it into view.
    • Space / Enter select and tap it as a tap would (SelectionChanging, ItemTapped, ItemTappedCommand); with AllowGroupExpandCollapse, group headers are stops that the arrows and Enter expand and collapse.
    • The focus ring is drawn on the current item while focus came from the keyboard; the item is kept across collection changes and recycling, and passes to its neighbor when removed.
  • Extended selection in collection views: IsExtendedSelectionEnabled with SelectionMode="Multiple" selects as desktop lists: a click selects only its item, Ctrl+click (Command+click on Apple) toggles one, Shift+click selects the range from the anchor; modifier clicks select without raising ItemTapped. The keyboard never drops the selection by moving: the arrow keys move only the current item, Space toggles it, Insert toggles it and moves on, Shift+arrows toggle the items they move onto (selected ones are deselected; the item the range starts on keeps its state, so a click then Shift+Down selects both), Enter taps (opens) without selecting, Ctrl / Command+A selects all. Touch keeps the toggling tap. Each gesture is one cancelable change (Keyboard).
  • Selected item template in collection views: SelectedItemTemplate (a template or selector) makes a selected item's row, for selected rows that show more or differ in size. A selection change swaps the row's view (recycled per template) and measures it again with what shows kept in place, in lists and grids; nothing changes while it is unset. Leak scenario CollectionViewSelectedTemplate.
  • Animated item changes in collection views: AnimatesItemChanges="True" (or a look's CollectionViewAnimatesItemChanges) animates inserts, removes and moves as native lists do: moved items and grid cells glide to their new places, inserted ones fade in, removed ones fade out where they were; expanding and collapsing groups too (Animated changes).
    • Off by default in 1.x. The changes of a frame animate together; everything runs on the render thread, the views keep their final layout and taps hit it.
    • With a SelectedItemTemplate of another size, the rows after a selected row glide to make room.
    • The look's new transitions ItemInsert, ItemRemove, ItemMove (per platform). Leak scenario CollectionViewItemsAnimated, bench scenarios collection-changes and collection-changes-animated.
  • Modifier keys on pointer samples: SkUiTouchEvent.Modifiers and SkUiPointer.Modifiers (SkUiKeyModifiers, now public) report Shift, Control, Alt and Command held during a press, move or release, from Android (GPU surfaces), UIKit (iOS 13.4+, Mac Catalyst) and Windows (EventMechanism.md).
  • Layouts of your own on other layout managers: SkUiLayout.AffectsChildLayout (a child's attached property that re-lays the layout out) and OnChildrenChanged are now protected virtuals, so a layout outside SkiaUi can run another library's ILayoutManager (SkUiLayout.md).

Breaking changes

  • Collection view items clip to their bounds (ClipItemsToBounds, default true): an item's or grid cell's content wider or taller than its slot (a row of buttons in a narrow grid column) spilled over the neighboring items, which are drawn after it, and covered them in part. Item and group header containers now clip what they show, native views hosted in them included, as Android's lists do. A template that draws past its row on purpose (a shadow into the item spacing, a part overlapping the next row, content scaled up on press) is cut at the edge: set ClipItemsToBounds="False", or give the template's root a margin that leaves the shadow room.

Fixes

  • No stuck Selected look under the pointer: a collection item deselected while the pointer was over it (on a desktop, or selecting with the keyboard) kept its Selected visual state when its template defined no PointerOver state, until the pointer left it, as MAUI's visual state manager leaves a group in its state when the next one is missing. Drawn views now go to Normal when they have no PointerOver state.

Other

  • Control / Command with a letter now reaches drawn key handlers on Apple and Windows too (as on Android), as SkUiKey.Character with the lowercase letter; pickers' type-ahead ignores it.
  • Gallery pages for the collection view's keyboard and extended selection and its animated changes (next to MAUI's CollectionView), and its selected item template.
  • Collection view items are no longer tab stops one by one: the list is one stop and the arrow keys move between its items (above). Buttons inside items stay tab stops.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.9.0

Choose a tag to compare

@github-actions github-actions released this 10 Nov 12:52

New features

  • Tile layout: SkUiTileLayout and SkUiCoreTileLayout lay out equal tiles for galleries and attachment strips: as many columns of at most TileSize as the width takes, stretched to fill the row but never past it, a column dropped below MinimumTileSize, TileAspectRatio, ColumnSpacing / RowSpacing: SkUiTileLayout.md.
    • MaximumRows cuts the rows: the children past it are neither measured nor drawn, and an OverflowTemplate (bound to SkUiTileOverflow.HiddenCount: "+5") shows over the last tile, with OverflowTapped / OverflowCommand (and OverflowCommandParameter, by default Overflow).
    • Replaces a Grid rebuilt in SizeChanged (Migration.md); the gallery's tile layout pages, on both layers.
  • Core state container: SkUiCoreStateContainer, the Core twin of the attached SkUiStateContainer: its content, or the node of the state CurrentState names, from keyed States (a node, or a factory run when the state is first named). CanStateChange, ChangeStateWithAnimation and the before / after state change animations on the render thread work as on the SkUi* layer; a SkUiCoreShimmer makes a skeleton loading state (SkUiStateContainer.md).
  • Core expander: SkUiCoreExpander, the Core twin of SkUiExpander: Header, Content, IsExpanded, Direction, Command, ExpandedChanged, LazyContentExpansion, AnimationLength / AnimationEasing, the content growing from the header while the height follows. Each animation frame re-records only the nodes whose size changed (SkUiExpander.md).
  • Core nodes scale each axis: ScaleX, ScaleY (multiplied by Scale, as in MAUI), AnchorX and AnchorY on every Core node, composite-time and animatable on the render thread (AnimateAsync, SkUiViewAnimation), with transform-aware hit testing.
  • Password reveal: IsPasswordRevealed (two-way), ShowsPasswordRevealButton and HidesPasswordOnUnfocus (default true) on SkUiEntry and SkUiCoreEntry (and the numeric entries): a password field draws its text instead of the bullets, with an optional reveal button (an eye) at its end that toggles without focusing the field, or with PasswordRevealMode="WhilePressed" shows the text only while held (SkUiEntry.md).
    • The field stays a password field for the platform while revealed (the keyboard, autofill and password managers see one) and copying stays off; the caret and selection stay put, and the text is masked again when the field loses focus.
    • Screen readers read the text only while it shows, and the button as "Show password" / "Hide password" (SkUiStrings.ShowPasswordText / HidePasswordText, automation id {AutomationId}_Reveal).
    • The look sizes and draws the button: TextFieldPasswordRevealButtonWidth, DrawTextFieldPasswordRevealButton (DrawTextFieldPasswordRevealButtonCore, DrawPasswordRevealGlyph, TextFieldPasswordRevealButtonPainter) with SkUiPasswordRevealButtonPaint.
  • Reorder from a drag handle: the attached SkUiCollectionView.IsReorderHandle marks a view in the item template (a ⋮⋮ or ≡ glyph) as the item's drag handle. With CanReorderItems, a press on it lifts the item at once, with any pointer, and drags it; the rest of the item no longer lifts it, so the row's own taps and long presses (LongPressedCommand: entering a select mode) work, and a drag there scrolls the list. Items with no handle lift with a long press anywhere, as before; a hidden handle stops reordering its item with any pointer; the screen-reader moves stay on the item (SkUiCollectionView.md).

Breaking changes

  • Animating one scale axis of a Core node scales that axis only: an SkUiViewAnimation (or a Core shimmer's state change animation) of ScaleX or ScaleY on a Core node used to scale both axes, or was rejected; it now scales its own axis, as on SkUi* views and in MAUI. Animate Scale to scale both (Migration.md).

Fixes

  • An empty SkUiCollectionView without an empty view no longer pushes the footer down: with no EmptyView (or an EmptyViewTemplate that makes no view), the empty state took the height the list had left, so the Footer sat at the bottom of the list instead of after the header. Nothing shows for it now, and the footer follows the header as it follows the last item.
  • VoiceOver finds buttons inside drawn controls by touch: explore by touch (and Accessibility Inspector's pointer) on iOS and Mac Catalyst picks the front-most, innermost drawn element, as TalkBack and Narrator do; UIKit picked the top-left of overlapping elements, so a text field's clear and password reveal buttons and actions inside a described group were reached only by swiping.
  • A drawn root sized by its content grows with it again: a surface root in a MAUI layout (a drawn stack in a VerticalStackLayout in a ScrollView) kept its old height when a nested BindableLayout list gained items while the page was shown, cutting off what was below the list until the page laid out again. A native layout pass that arranged the root after the change and before its next frame measured it at its old bounds, capping its height, so its relayout found no change to report. It is now measured with the constraint the native layout gave it, which is asked again when the root's size changed.

Other

  • Shaped borders' first frame: borders with the same outline (equal ticket-shaped cards in a list) share its content clip and shadow silhouette, which took a path operation per border: 400 such cards record their first frame in 25 ms instead of 590 ms on a desktop CPU (SkUi*; Core 8 ms instead of 570 ms), and reach it in 0.6 s instead of 1.9 s on a Galaxy S9 and 0.17 s instead of 1.0 s on an iPhone 8 (Performance.md). It also works when each card makes its own stroke shape.
  • Core layout changes re-record less: a Core node whose measure changes (a label's new text, a box's new size) re-records itself and the containers whose size changes, no longer every container up to the host, as SkUi* views since 1.0. SkUiCoreTable still re-records when a cell's measure changes, since its track fills and separators follow the cells.
  • Device tests: a password reveal check with the platform's real text input (the keyboard is not restarted, the field stays a password field, screen readers follow), passed on a Galaxy S9 and an iPhone 8; scripts/device_tests.sh --xcode launches on iOS 16 devices with an older Xcode, whose developer image Xcode 27 no longer mounts.
  • Gallery: Core state container and Core expander pages; drag handles on the collection view reordering page.
  • Demo: two-way property editors: a component page's editors follow their property when it changes on a preview: the password reveal button toggles the IsPasswordRevealed switch, typing in either preview updates the Text editor (and the other preview), dragging a slider or swiping a carousel moves its editor. IsEnabled stays one-way (MAUI reports the effective value, false while a command cannot execute).

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.8.0

Choose a tag to compare

@github-actions github-actions released this 06 Nov 15:00

New features

  • Markdown: a drawn Markdown view on both layers (SkUiMarkdownView, SkUiCoreMarkdown), in a new package, SkiaUi.Maui.Markdown, on Markdig. SkiaUi.Maui gets no new dependency.
    • Headings, emphasis of every kind, inline code, quotes, alerts, containers, code blocks with a copy button, rules, nested and task lists, pipe and grid tables, links, emoji, footnotes, definition lists and images.
    • Nothing a document says happens by itself: links and images raise events, remote images load only with AllowRemoteImages, and a document cannot read a local file (ImageResolver replaces the rule).
    • Bad input never throws: a document past a limit, or one that cannot be built, shows as plain text with a Warning.
    • Parsing and creating nodes run on a background thread, with the latest text winning; only putting them on screen runs on the UI thread.
    • A growing text only builds its tail, so a streamed answer stays cheap.
    • The gallery's Markdown page, the samples app's "A Markdown document", and SkUiMarkdownView.md.
  • Formulas in Markdown: block and inline math in a second package, SkiaUi.Maui.Markdown.Math, on CSharpMath (UseSkiaUiMarkdownMath(), UseMath()). A deep formula could end the process with a stack overflow, so every formula is checked before the engine sees it; one past the limits shows its source.
  • Zoom: SkUiZoomView and SkUiCoreZoomView, with pinch, pan, double tap and wheel at composite time, so nothing re-records: SkUiZoomView.md. IsWheelZoomEnabled turns the wheel off for a view in a scroll view. AllowImageZoom on the Markdown view opens a picture in one through the app's popup presenter.
  • Inline objects in text: a span can draw something in the line instead of its text, on both layers (SkUiCoreSpan.InlineObject, SkUiSpan.InlineObject on MAUI's Span, SkUiInlineObject). It wraps, aligns and takes taps as a word, and follows the bidi order: SkUiLabel.md.
  • Baseline shift on spans: SkUiCoreSpan.BaselineShift and SkUiSpan.BaselineShift, for real superscripts and subscripts.
  • SkUiPopups.ShowContentAsync: a popup of any drawn view through the app's presenter, on the same contract as a picker's list.

Fixes

  • A pinch beats a pan on the same element: with two fingers down, one finger moving first no longer starts the element's PanUpdated and ends the pinch.
  • <sub> and <sup> in HTML text sit below and above the baseline; before, they were only smaller.
  • A scroll that waits for the layout (a keyboard inset, say) ends in the frame that ends it; before, its task ended through a pool thread, which a busy pool could delay past the frames that needed it.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.7.0

Choose a tag to compare

@github-actions github-actions released this 05 Nov 19:22

New features

  • Vector icons: an .svg file, MauiAsset, download or stream now draws at runtime on both layers (Source="check.svg"), through a small SVG reader in SkiaUi.Maui with no new dependency. It is drawn again at the size its view shows it in exact pixels, larger or smaller, on SkUiImage, SkUiImageButton and their Core twins; explicit decode bounds win. A MauiImage of the same name still wins. A file with something the reader knows it cannot draw (a gradient, <use>, an embedded image) fails with a LoadError naming it, and a file cannot make requests or hold a thread for long.
    • SkUiVectorImageSource, a MAUI ImageSource shaped like FontImageSource, works in every image property of the SkUi* controls: Source, Color (the starting value of currentColor; colors written in the file stay) and Size (the longest edge in DIPs). Color takes AppThemeBinding, DynamicResource and bindings, and a new color keeps the icon shown until it is drawn.
    • Core: SkUiImageSource.FromVector(source, color, size) and FromVectorText(svg, color, size).
    • Once loaded, an icon costs what a PNG of its size does: Performance.md.
    • The samples app's "Icons from SVG files" example and the gallery's "SVG icons at runtime" page; how to use them: SkUiImage.md, and moving icons over: Migration.md.

Fixes

  • No backdrop flashing through resized GPU surfaces on Windows: a hardware-accelerated surface being resized (a splitter drag, a window resize, anything that changes its layout) showed strips of the window's backdrop at its edges and, for a frame, stretched content. WinUI does not synchronize a swap chain's presents with its own layout, so a swap chain resized with its slot could be shorter than what XAML showed. The swap chain panel is now longer than its slot and clipped to it, and changes only when the slack runs out, so most resizes do not touch the swap chain. A surface starts with 192 epx of slack per direction; one that outgrows it takes 384, and keeps up to 768. Still open: a resize of more than 96 epx in one layout pass can show a gap for a frame, and each change of the panel can flash the whole surface for a frame; a drag back and forth now changes it once instead of twice per sweep.
  • No exception when a touch closes its own surface: a release can disconnect the surface's handler while the touch is still being handled (such as the pick that closes a picker's popup); code reading the handler's view afterwards (the demo's input trace on Windows, a frame already queued) threw InvalidOperationException: VirtualView cannot be null here.
  • SkUiAvatarView follows edits of its image source: changing a property of a live source (a FontImageSource's Color, a UriImageSource's Uri) reloaded the old values.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.6.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 18:22

New features

  • Viewport insets: ViewportInsets (Thickness, default none) on SkUiScrollView (and so SkUiVirtualScrollView), SkUiCoreScrollView (SetViewportInsets) and SkUiCollectionView says which parts of the viewport are covered by views drawn over the scroller, so an edge-to-edge page scrolls its content under translucent bars with nothing covered at the ends of the range. Padding keeps its meaning.
    • The band left uncovered is what the scroll bars' track, SnapPointsAlignment, ScrollToAsync(element / node, position), ScrollToIndex / ScrollTo, KeepSelectionVisible, keyboard and screen-reader reveal, keyboard paging, load-more triggers, RemainingItemsThreshold and reordering's auto-scroll use. ScrollToAsync(x, y) stays raw offsets.
    • Insets across the scroll axis pad the content and keep the scroll bar out of them (a landscape notch). The keyboard and the end inset count as the larger of the two.
    • Changing the insets while scrolled keeps what shows in place; at the start of the range the scroller stays there.
    • The collection view's sticky header, footer and group headers are drawn inside the insets; the refresh indicator of the collection view and of SkUiRefreshView comes down from the start inset (the refresh view reads it from its content's first vertical scroller).
    • A bare SkUiVirtualVerticalStackLayout follows the insets of the SkUiScrollView around it.
    • Native views hosted in the content (SkUiMauiContentView) are clipped to the band, as they show above the drawn surface: they are cut off at a bar and do not take its touches. This also keeps them out of a list's sticky header and footer, which they used to cover.
    • All of them implement ISkUiViewportInsets, for app helpers that pass bars' sizes and the safe area on to whichever scroller or list a page shows.
  • SafeAreaInsets on the surface root: read-only and bindable, how far the window's bars, notch and home indicator reach into the root, whatever its SafeAreaEdges say; it follows rotation and window resizes, and zero inside a surface. An app binds its bars' padding and ViewportInsets to it. Nothing asks the platform until it is first read.
  • Demo and samples: the gallery's "Edge-to-edge scrolling" page; the samples app's "Order list" example opens a full edge-to-edge page that follows the insets through a rotation.

Fixes

  • Layout changes made while a surface root is arranged are no longer lost: a SizeChanged handler that changed a view's layout during the root's first arrange (a bar setting a list's insets) asked the native layout, which was in its own pass and did not come back, so the tree stayed as it was until something else laid it out. The root now lays out again before its next frame.
  • Hosted native views follow a smaller clip: a SkUiMauiContentView kept its old clip when an SkUiScrollView above it, or an ancestor with ClipToBounds, changed size without moving it (a sheet giving a list less height when the keyboard opens), and showed over what lies below until the next scroll. The clip is now placed again whenever that rectangle changes.

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md

SkiaUi.Maui 1.5.1

Choose a tag to compare

@github-actions github-actions released this 03 Nov 13:24

Fixes

  • Android: check boxes, radio buttons, switches and selected chips no longer crash accessibility with Xamarin.AndroidX.Core 1.19: an app that resolves 1.19 (through Google Play Services, Xamarin.AndroidX.CustomView 1.2.0.4 and others) threw MissingMethodException: AccessibilityNodeInfoCompat.set_Checked(bool) as soon as TalkBack or a UI-test driver (UiAutomator, Maestro) read a drawn view with a check state, since that binding turned Checked into the tri-state int. The checked state is now set on the platform node, which works with every AndroidX version; on Android 16+ all three states go through CheckedState (a mixed check box is partially checked, as before). CI also builds the Android TFM against the newest Xamarin.AndroidX.Core, so a binding change like this one fails the build (issue #78).

Other

  • Bugfix releases from devel: the publish workflow's bump patch on devel now makes a stable release (1.5.0 → 1.5.1) and moves master to it, as bump release does; before, it started a 1.5.1-Prerelease01 line. Prerelease lines start with minor or major (auto still starts one with minor). A patch from devel in a prerelease line is refused: the fix goes to master as a hotfix (docs/Releasing.md).

Full changelog: https://github.com/rafalka/MauiSkiaUi/blob/master/CHANGELOG.md