win10 app - Rounded corner images keeping aspect ratio - win-universal-app

Simple app that just displays a list of images. The list of images must keep there aspect ratio, but be full window width + a bit of margin. The hard part is making the images additionally have rounded corners.
Ideas?
Only success I have had is with ImageBrush, but any control using that doesn't keep the aspect ratio. For example, here you must set the height and width.
<Rectangle RadiusX="10" RadiusY="10" Stretch="Fill" Width="100" Height="100" >
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding}"></ImageBrush>
</Rectangle.Fill>
</Rectangle>
full source here: http://1drv.ms/1HlZHVe

I got nicely rounded corners on my images (in my UWP app) by using an ImageBrush, however be careful if you do this programmatically - the first time I did I managed to use my memory rather poorly and consumed too much (poor coding).
I was using the ImageBrush much as you seem to be, but I wasn't getting any distortion of the aspect ratio; make sure you're setting properties like Stretch appropriately - e.g. Stretch.UniformToFill.
<Rectangle x:Name="rctCardFace" Margin="0" RadiusX="20" RadiusY="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle.Fill>
<ImageBrush Stretch="UniformToFill"/>
</Rectangle.Fill>
</Rectangle>
Or in C#
Uri path = new Uri(_ActiveStyle.BackgroundImagePath, UriKind.Absolute);
BitmapImage bitmapImage = new BitmapImage(path);
if (_AppReference.CardManager.TempImgBrush == null)
{
_AppReference.CardManager.TempImgBrush = new ImageBrush();
}
_AppReference.CardManager.TempImgBrush.ImageSource = bitmapImage;
_AppReference.CardManager.TempImgBrush.Stretch = _ActiveStyle.BackgroundImageStretch;
_AppReference.CardManager.TempImgBrush.AlignmentX = _ActiveStyle.BackgroundImageAlignX;
_AppReference.CardManager.TempImgBrush.AlignmentY = _ActiveStyle.BackgroundImageAlignY;
cfPreview.ImgB = _AppReference.CardManager.TempImgBrush;

Hi you can use the following code to create a rounded corner image in UWP:
<Ellipse Width="250" Height="250">
<Ellipse.Fill>
<ImageBrush ImageSource="ms-appx:///highfive.jpg" />
</Ellipse.Fill>
</Ellipse>

Related

Xamarin.Forms: how to center an Image in TitleView when ToolbarItems are displayed?

I'm working on a Xamarin.Forms.Shell app containing 4 tabs. I would like to display a common Title containing a centered SVG logo on all these pages.
For this, I can use a TitleView like this:
<Shell.TitleView>
<ffimageloadingsvg:SvgCachedImage Source="resource://ShellAppSample.Resources.logoTitle.svg"
DownsampleHeight="6"
HeightRequest="45"/>
</Shell.TitleView>
This works and the logo is well centered in the NavigationBar. However, if the page contains ToolbarItems, the logo is no longer centered.
For example, on a page I've a ToolBarItem like this:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Refresh"
Order="Primary"
Priority="0"
Command="{Binding RefreshCommand}"
CommandParameter="{x:Reference webView}">
<ToolbarItem.IconImageSource>
<FontImageSource Glyph="{StaticResource FalIconRefresh}"
FontFamily="FontAwesomeLight"
Size="Medium"/>
</ToolbarItem.IconImageSource>
</ToolbarItem>
</ContentPage.ToolbarItems>
Is there another way to display a centered Image from a SVG as Title, by using CustomRenderer or calculating the size of the ToolbarItems?
I've seen that a similar question has already been posted 1 year ago, but without any solution...
I've already tried to redraw the ToolbarItem in the TitleView like this:
<Shell.TitleView>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
BackgroundColor="Transparent">
<ffimageloadingsvg:SvgCachedImage Source="resource://ShellAppSample.Resources.blackLogoTitle.svg"
DownsampleHeight="6"
HorizontalOptions="CenterAndExpand"
HeightRequest="45"
BackgroundColor="Transparent"/>
<Image HorizontalOptions="End" VerticalOptions="CenterAndExpand"
BackgroundColor="Transparent">
<Image.Source>
<FontImageSource Glyph="{StaticResource FalIconRefresh}"
FontFamily="FontAwesomeLight"
Size="Medium"/>
</Image.Source>
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding RefreshCommand}" CommandParameter="{x:Reference webView}"/>
</Image.GestureRecognizers>
</Image>
</Grid>
</Shell.TitleView>
On iOS it's correct, but I can see that:
the logo is not exactly centered like on the pages that don't contain any ToolBarItem, as there is a small gap when I switch between the pages
the icon is not positioned like when I use a ToolBarItem
On Android, the result it's not correct: the logo hasn't the same height, and the icon is out of the TitleView.
Finally I've managed my TitleViews like this:
For the Image:
<Shell.TitleView >
<Image Source="resource://ShellAppSample.Resources.logo.jpg"
VerticalOptions="CenterAndExpand" HorizontalOptions="Center"
Margin="{OnPlatform Android='0,0,16,0', Default=0}"/>
</Shell.TitleView>
For the Label:
<Shell.TitleView>
<Label Text="{Binding Title}"
VerticalOptions="CenterAndExpand" HorizontalOptions="Center"
Margin="{OnPlatform Android='0,0,16,0', Default=0}"/>
</Shell.TitleView>
And for Label with one "medium" size ToolBarItem:
<Shell.TitleView>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Title}"
Grid.Column="1"
VerticalOptions="CenterAndExpand" HorizontalOptions="Center"
Margin="{OnPlatform Android='0,0,16,0', Default=0}"/>
</Grid>
</Shell.TitleView>
<ContentPage.ToolbarItems>
<ToolbarItem Text="Refresh"
Order="Primary"
Priority="1"
Command="{Binding RefreshCommand}">
<ToolbarItem.IconImageSource>
<FontImageSource Glyph="{StaticResource FalIconRefresh}"
FontFamily="FontAwesomeLight"
Size="Medium"/>
</ToolbarItem.IconImageSource>
</ToolbarItem>
</ContentPage.ToolbarItems>
I've checked the alignment through the DebugRainbows package and it looked fine on iOS/Android, on small/large devices.
It's not perfect, and I need to update rules if I add other ToolBarItems but it worked like this.

Windows Phone Runtime pathicon runtime vs designtime

I’m working on a WP8.1 runtime app (using the universal app template).
I’ve created an appbar with a togglebutton. The button icon is a PathIcon.
in designtime (both Blend and VS2013) the button looks exactly what I expect it to look like but at runtime the path stretches out so it fills the circle of the button.
is this difference between designtime and runtime a known issue and is there a workaround so that my button looks how it’s supposed to look at runtime?
It looks good on every resolution in Blend so it's not a scaling issue
designtime:
runtime:
the XAML for the button:
<Page.BottomAppBar>
<CommandBar>
<AppBarToggleButton Label="HQ">
<AppBarToggleButton.Icon>
<PathIcon HorizontalAlignment="Left"
VerticalAlignment="Top"
Data="M21.0007,6.25 C6.3752,1.125 5.25043,16.6091 5.62518,19.5 C5.9215,21.7858 6.25018,10.75 16.0005,12.875 C19.8337,13.7104 24.1247,19.3755 20.3747,23.0006 C20.1689,23.1995 18.7133,17.0212 13.6254,19.5002 C8.75026,21.8755 13.0958,28.4331 12.8234,28.4006 C5.88184,27.5722 0.5,21.6646 0.5,14.5 C0.5,6.76801 6.76801,0.5 14.5,0.5 C19.153,0.5 23.0847,2.9988 25.2497,6.50016 C25.7361,7.28663 25.9271,7.98672 26.2501,8.87522 C26.75,10.2503 22.9202,6.92261 21.0007,6.25 z" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
</CommandBar>
I did not test with a PathIcon, but you can just a Path just fine:
<CommandBar>
<AppBarToggleButton Label="HQ">
<Path VerticalAlignment="Center" HorizontalAlignment="Center"
Fill="White" Stroke="White"
Data="M21.0007,6.25 C6.3752,1.125 5.25043,16.6091 5.62518,19.5 C5.9215,21.7858 6.25018,10.75 16.0005,12.875 C19.8337,13.7104 24.1247,19.3755 20.3747,23.0006 C20.1689,23.1995 18.7133,17.0212 13.6254,19.5002 C8.75026,21.8755 13.0958,28.4331 12.8234,28.4006 C5.88184,27.5722 0.5,21.6646 0.5,14.5 C0.5,6.76801 6.76801,0.5 14.5,0.5 C19.153,0.5 23.0847,2.9988 25.2497,6.50016 C25.7361,7.28663 25.9271,7.98672 26.2501,8.87522 C26.75,10.2503 22.9202,6.92261 21.0007,6.25 z" />
</AppBarToggleButton>
</CommandBar>

Half filled circle with d3.js

I am trying to create a half filled circle with d3.js to be like this.
I didn't find any example of how to do it.
How can this be done with d3.js?
Yes, you can do that with an SVG gradient. All you have to do is define it and then use it as fill for the circle.
var grad = svg.append("defs").append("linearGradient").attr("id", "grad")
.attr("x1", "0%").attr("x2", "0%").attr("y1", "100%").attr("y2", "0%");
grad.append("stop").attr("offset", "50%").style("stop-color", "lightblue");
grad.append("stop").attr("offset", "50%").style("stop-color", "white");
svg.append("circle")
.attr("fill", "url(#grad)");
JSfiddle here.
You may not even require d3 for this simple task. You may use this simple technique, Using Clippath on a circle, I have written it in details in my blog http://anilmaharjan.com.np/blog/2013/11/create-filled-circle-to-visualize-data-using-svg
Use Two circles one above another in a tag.
Fill one with the color you wish and another with white or may be your background color just to make it look like its empty in there.
Then clip the later one using with rectangle in it, assign radius few pixel less than the earlier circle.
Place clip path at the top left .. assign width equal to the diameter of the circle and height will be defined by your data.
The data will act reversible to the filling so you may subtract the actual data from your max. EG: if data is 20/100 do 100-20 so u ll get 80 in this way the empty part will be 80 and filled will be 20.
You may switch between height or width to switch between vertical or horizontal filling axis.
The HTML should look like this.
<svg height="200"> <a transform="translate(100,100)">
<g>
<circle fill="#f60" r="50"></circle>
</g>
<g>
<clippath id="g-clip">
<rect height="50" id="g-clip-rect" width="100" x="-50" y="-50">
</rect>
</clippath>
<circle clip-path="url(#g-clip)" fill="#fff" r="47"></circle>
</g>
</a>
</svg>
I have created a jsfiddle to illustrate this at: http://jsfiddle.net/neqeT/2/
create a div having id name id_cirlce and paste this code inside script tag
<div id="id_circle"></div>
<script>
var svg = d3.select("#id_circle")
.append("svg")
.attr("width",250)
.attr("height",250);
var grad = svg.append("defs")
.append("linearGradient").attr("id", "grad")
.attr("x1", "0%").attr("x2", "0%").attr("y1", "100%").attr("y2", "0%");
grad.append("stop").attr("offset", "50%").style("stop-color", "lightblue");
grad.append("stop").attr("offset", "50%").style("stop-color", "white");
svg.append("circle")
.attr("r",50)
.attr("cx",60)
.attr("cy",60)
.style("stroke","black")
.style("fill","url(#grad)");
</script>

How do specify a width percentage in JavaFX 2 using FXML?

I am looking for a way to say set a maxWidth size to 80% in FXML.
Much like in web development.
<VBox fx:id="testVB" prefWidth="600">
But this does not:
<VBox fx:id="testVB" prefWidth="80%">
I know that in Straight JavaFX2 non-fxml you can create insets? What is the best way to do this outside of code in FMXL?
Thanks!
Riley
I'm not sure you can. You need to use the GridPane layout component. In this component, you can specify rows and columns constraints, and in these constraints you can specify a width as a percentage. For example:
<GridPane>
<children>
<TitledPane text="testGridPane" GridPane.columnIndex="0" GridPane.rowIndex="0" />
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="80.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
This code defines a GridPane with a first column with a width of 80%. The TitledPane is set in the first cell of the first column of this GridPane, and can (because you need to be sure that the width constraints of the TitledPane match your needs) occupy 80% of the width of the GridPane.
Please note that I removed all information not relevant to your question. By the way, Oracle's Scene Builder tool is very useful to define complex FXML layout.
It seems like many answers have already been provided and they should work. However, there is a way to set percentages:
<fx:define>
<Screen fx:factory="getPrimary" fx:id="screen" />
</fx:define>
This would help you detect the dimensions of the current screen, the application is being displayed on. Now that we have the display dimensions, we can play with it in FXML as follows:
<HBox fx:id="hroot" prefHeight="${screen.visualBounds.height}" prefWidth="${screen.visualBounds.width}"> Your FXML elements inside the root... </HBox>
Note that I use visualBounds, since this would get me the available space on the screen, since I don't want an overlap with the taskbar in Windows for example. For fullscreen applications, you would just use 'bounds'.
Now, to come to your point of using percentages, you can actually play with the value of the prefheight and prefWidth. You can put calculations inside the ${}.
Optionally:
If you want to have all your elements use relative sizes, just refer to them, using their ID and width or height property, and make your calculation.
<VBox fx:id="VBSidebar" prefWidth="${hroot.width*0.15}" prefHeight="${hroot.height}"> more elements.. </VBox>
Hope this helps!
You can simulate it - basic example that simulates 50% for two cols in an HBox. You can add dummy panes to get thirds, etc.
HBox {
VBox {
static hgrow : "ALWAYS",
Label {
text : "Privacy",
alignment : "CENTER",
styleClass : ["h2", "heading"]
}
},
VBox {
static hgrow : "ALWAYS",
Label {
text : "Messages",
alignment : "CENTER",
styleClass : ["h2", "heading"]
},
Label {text:""}
}
}

WPF - Border with a OpacityMask/VisualBrush: Memory Leaks

A brief explanation about my app:
the application in which I'm working on is such a greeting cards designer. Imagine something in which there is a background image, and an indefinite number of "layers" (in particular, pictures) that stay over the background and can be moved, resized, moved front and back, etc...
It is also possibile to apply particular shapes to these layers, like a star, an ellipse, .. and after the card is made, it's possibile to save is to jpeg file.
The problem
Everything works correctly, but I detected that when a shape is applied to a layer, a memory leak is generated.
Here is the code of the UserControl of each layer:
<UserControl>
.....
<Grid x:Name="_myGrid" >
<Border x:Name="im_the_problem" BorderThickness="0" OpacityMask="{Binding Path=MyMask.Data, Converter={StaticResource MaskConverter}}">
<!-- My Image... -->
</Border>
</Grid>
</UserControl>
where MaskConverter code is the following:
public class MaskConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
String maskData = value as String;
if (maskData == null)
return null;
if (maskData == "")
return null;
VisualBrush vb = new VisualBrush();
vb.Visual = XamlReader.Parse(maskData) as Visual;
return vb;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
The Parameter "MyMask.Data" is a XAML Path (that is the shape that I'm applying) that I dinamically load from a textfile that contains different shapes.
So, the principle is that if I have the border named *im_the_problem*, the memory is NOT released. If I comment *im_the_problem* (so I'll just have rectangular layers/pictures without shapes) everything work like a charm, without memory leaks.
The problem should be in the OpacityMask + VisualBrush.
Am I doing something wrong?
Or is there a known problem? Is there a way to do the same (apply a shape to a picture..) in a different manner?
Thanks.
You might be able to try binding the MyMask.Data to an actual Path.Data, and setting the Path.Fill to an ImageBrush created from the image?
You need to freeze your VisualBrush ;)
I had this problem in a DataGrid's column template where I was using a <Canvas><Path /></Canvas> (as a static-resource) into a VisualBrush (also a static-resource) and using that as the OpacityMask for a Rectangle. Whenever the DataGrid was reloaded the Rectangle wouldn't release VisualBrush references to the OpacityMask, I used a memory-profiler tool to reveal that all the VisualBrush objects were using the bulk of memory.
I don't understand why or how this happened - but I'm glad I'm not alone (even if I had the same problem some 6.5 years later...).
My XAML was something like this:
<DataGrid.Resources>
<Canvas x:Key="icon" ...>
<Path ... />
</Canvas>
<VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
I read that setting IsFrozen = true (done using this technique: https://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you ) would help memory issues with Brushes, however this seemingly had no effect at all. Weird.
I thought I'd experiment and I reasoned that if the issue was leaking the VisualBrush then I wondered if having it as a StaticResource was messing with object-references, so I changed it to an "owned" object, like so:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
>
<VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" />
</Rectangle>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
This fixed the issue! And I still don't know why - I wonder if it's a bug in WPF?
On a related note, I came to realise that using a VisualBrush was overkill as I'm rendering just a simple Path - VisualBrush is expensive because it renders an entire WPF view - I also learned from other documentation that Path itself isn't necessary for rendering simple shapes because itself is a complete UIElement and FrameworkElement - which are "heavier" types.
I changed my code to store the path in a PathGeometry value inside a GeometryDrawing static-resource which is loaded into a DrawingBrush:
<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." />
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
>
<DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" />
</Rectangle>
Doing this also made a dent in memory usage, and hopefully, performance.
In your project I see you're not using the path information as a resource, but the same technique applies: load your path into a PathGeometry (or rather, StreamGeometry object, which is even faster and is meant for immutable geometry) and set that as the Drawing for a DrawingBrush.

Resources