Open RobMeyer opened 5 years ago
Thanks for writing this up @RobMeyer !
One thing occurs off the top of my head - DropShadowPanel
is a Windows Community toolkit control. Is the best approach here to wrap a high policy control or should we go directly to Windows.UI.Composition.DropShadow and implement a layer around that in RNW instead?
Let's discuss in an upcoming review.
I think DropShadowPanel's approach is the only way that works because of some unfortunate restrictions of ElementCompositionPreview and DropShadow.
Only SpriteVisual and LayerVisual have a .Shadow property used to attach a shadow to an existing visual. Visual, which is what is exposed by ElementCompositionPreview, doesn't have a Shadow property.
It's still possible to create a new SpriteVisual and attach a DropShadow initialized using Mask (acquired from TextBlock.GetAlphaMask, Image.GetAlphaMask, or Shape.GetAlphaMask), but the SpriteVisual needs to be inserted in the XAML tree somewhere. Two ways to do this:
For your information, in iOS, children will not get the shadow property if a background color is set on the view ;)
Any chance of moving forward with this? I believe that the fact that shadow properties are still missing might come as a surprise for anyone coming to RNW development 🥸
can any one helps in creating shadow properties that has to be work on react native windows application using react native components or using svg components
for now i was using imagebackground that has image shadow and on top of that i was showing view data to overcome this any help from react native community
Proposal: Drop Shadow support for View, Text, Image, and more
Implement support for ViewStyle.shadow and TextStyle.textShadow for View, Text, and Image.
Summary
Tasks
DropShadowPanel
, to be calledShadowedContentControl
will be used for shadows cast from all XAML-based components.ShadowedContentControl
for reuse by third partiesMotivation
React Native supports shadows for View, Text, and Image using the ViewStyle.shadow and TextStyle.textShadow props. Android and iOS both support these properties (though with some notable differences), but support hasn’t been implemented in react-native-windows vNext yet. The WPF RN project has support but a straight port to UWP isn’t possible due to differences in shadow APIs available between WPF and UWP + XAML + Composition.
Shadows will improve application visuals and usability. In addition to aiding visualization of the application's information hierarchy and drawing attention to UX of interest, drop shadows can also be used to enhance readability of text against low-contrast or "busy" background content such as a photograph. A shadow without vertical or horizontal offsets can also be used to create a "glow" effect, used for similar design and usability goals.
Basic example
Open Questions
View shadows, iOS, Android, and staging work
iOS and Android's support for shadows on elements differs in one important way: on iOS all the children of the view also get the same drop shadow visuals applied to them. On android, the view's shadow only affects the view's border and background visuals, not all the children too. This can be seen in the screenshot above.
Android's model seems ideal because it allows for the most flexibility. On iOS, if you want a View's border to have shadow visuals, but you don't want the children to, then you have to put the children in another superimposed view. On Android, you simply set the shadow props on all the elements you want to have shadows. Similarly, in the event where child and a parent should both have shadows, on Android you're able to use the specialized textShadow props on the Text, which visually look better than iOS's inherited ViewStyle.shadow* visuals (see first two Text shadows in screenshot above).
However, I can guess how iOS' behavior came about. If we were to implement ShadowedContentControl using the "SoftwareBitmap -> CompositionBrush -> AlphaMask" technique, the shadow visuals would apply not only to the View itself, but also all children.
With that background information out of the way, we can discuss work staging. Rewriting ViewViewManager to use Composition border rendering instead of a XAML control would be a substantial task. The fastest path to supporting View shadows is to use the "SoftwareBitmap -> CompositionBrush -> AlphaMask" technique. However, this would mean children inherit shadows, like iOS. It also would be inferior performance-wise. Luckily, shadows are opt-in so it's pay-for-play.
Long-term there seems to be agreement on adopting Composition for a plethora of benefits (smaller XAML tree, improved performance, support for ViewStyle.borderStyle "dotted" and "dashed", etc.), but ShadowedContentControl + SoftwareBitmap -> CompositionBrush -> AlphaMask could help us get to basic drop shadow support faster. The short-term work also wouldn't go wasted, because it accrues towards making ShadowedContentControl work with arbitrary XAML types, useful for third parties wanting shadows for their own custom NativeComponents written wrapping XAML components.
RN Glyph / NativeComponent "PLYIcon"
IconViewManager is currently implemented using Glyph, not a XAML. We would like shadow support for these elements too, but I'm not sure which implementation would be preferred. Some possibilities:
a. If ShadowedContentContainer has support for arbitrary XAML content via the SoftwareBitmap -> CompositionBrush -> AlphaMask approach, Glyph could be wrapped in a ShadowedContentContainer.
b. IconViewManager could be rewritten to use instead of Glyph. The TextBlock could then be wrapped using ShadowedContentContainer.
c. IconViewMangager could be rewritten to be drawn using Composition with DropShadow.
d. Alternatively, our client could migrate from Glyph-based icons to using or components.
Popup/Flyout and Context Menu
Shadows are also of interest for these components but I haven't investigated enough to include anything along with this proposal.
Further reading, dev plan notes
2020/10/28: Attaching investigation notes I put together back in July 2019 when I was formulating a plan of attack. These notes were only intended for personal purposes and haven't been cleaned up for broad publication, so grant me a little leeway regarding rough edges. I hope it helps anyone that might pick up this task in the future. Drop Shadows in react-native-windows.pdf