create a number of circular frames that matches the number of items in a list xamarin.forms - xamarin.forms

i don't know if my title suits my question but the idea is that i want to create circular frames according to the number of items in a list and if the number of frames created is more than what the screen can fit, i want the frames to continue on another row. i managed to create the frames but i don't know how to arrange them as i said. i thought about using a grid but the thing is, if i use a grid then i'll have to define a static number of columns in each row. but what if the user uses a tablet, then the screen size will be bigger and more frames could fit in the row. this is the code i wrote till now:
main.xaml.cs
public MainPage()
{
InitializeComponent();
for(int i=0; i < 10; i++)
{
Frame circleImageFrame = new Frame
{
Margin = 10,
BorderColor = Color.Black,
CornerRadius = 50,
HeightRequest = 60,
WidthRequest = 60,
IsClippedToBounds = true,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start,
Content = new Image
{
Source = ImageSource.FromFile("user_profile.png"),
Aspect = Aspect.AspectFill,
Margin = -20,
HeightRequest = 100,
WidthRequest = 100
}
};
thislayout.Children.Add(circleImageFrame);
}
}
main.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="stdprofiles.MainPage">
<StackLayout x:Name="thislayout" Orientation="Horizontal">
</StackLayout>
</ContentPage>
in these pictures i am trying to illustrate my point.
what layout should i use? thanks in advance

Related

Limiting Label's width

So basically what i have is a Frame, with a Horizontal StackLayout which has 2 Labels in it:
(Label has colored background, Frame is white)
My problem is, when i have a longer name label, the price label doesn't get enough space and gets cut:
Which property should i change in order to not cut price label?
Here is the portion of code that creates the frame:
Frame elementFrame = new Frame {
BackgroundColor = Xamarin.Forms.Color.White,
Padding = 20,
};
StackLayout elementStackLayout = new StackLayout {
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.Fill,
BackgroundColor = Xamarin.Forms.Color.Orange
};
Label elementName = new Label {
BackgroundColor = Xamarin.Forms.Color.Aqua,
Text = FinalProduct.GetAttribute("Nome"),
HorizontalOptions = LayoutOptions.Start,
};
Label elementPrice = new Label {
BackgroundColor = Xamarin.Forms.Color.Aqua,
LineBreakMode = LineBreakMode.NoWrap,
HorizontalOptions = LayoutOptions.EndAndExpand,
Text = "€" + ( Decimal.Parse(FinalProduct.GetAttribute("Prezzo")) * Int16.Parse(FinalProduct.GetAttribute("Quantita")) ).ToString("0.00"),
HorizontalTextAlignment = TextAlignment.End
};
elementStackLayout.Children.Add(elementName);
elementStackLayout.Children.Add(elementPrice);
elementFrame.Content = elementStackLayout;
I tried messing around with HorizontalOptions, Label's LineBreakMode but with no success.
StackLayout lacks a way to tell which item to "squeeze", unless you use a "hardcoded number" for both WidthRequest and MinimumWidthRequest on elementPrice.
Grid has a solution for this case, "Auto" vs "*":
<Grid ColumnDefinitions="*,Auto" HorizontalOptions="Fill">
<Label Grid.Column="0" ... />
<Label Grid.Column="1" x:Name="elementPrice" ... />
</Grid>
"Auto" in Column "1" will be given all the width it wants.
"*" in Column "0" gets what is left.

Xamarin Forms Collection View Extra Padding

I"m trying out the Xamarin Forms Collection View. It appears to have some extra padding around each item in the list. I can't see how to remove it.
Here is a picture of my view. The view has an aqua background. The 2 column grid in the template has labels set to red.
And here is the XAML/C#
<CollectionView
x:Name="BodyView"
SelectionMode="Single"
HorizontalOptions="FillAndExpand"
BackgroundColor="Aqua"
Grid.Row="2" />
BodyView.ItemTemplate = new DataTemplate(() =>
{
var converter = (IValueConverter) Application.Current.Resources["GridCellConverter"];
Grid grid = new Grid( );
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
foreach (var col in _gridColumns)
{
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var content = new Label();
content.Style = (Style)Application.Current.Resources["GridCellLabel"];
content.BackgroundColor = Color.Red;
Binding binding = new Binding("CellData", BindingMode.OneWay, converter, col.PageFieldId);
content.SetBinding(Label.TextProperty, binding);
grid.Children.Add(content, grid.ColumnDefinitions.Count - 1, 0);
}
return grid;
});
I zeroed everything I could find to zero.
I tried setting a negative margin on the grid but it won't move left.
Is there any way to remove the padding?
What you are looking for is the Grid's Row and Column Spacing!
Grid grid = new Grid( ){ ColumnSpacing= "0", RowSpacing="0" };
Also, this needs to be removed:
grid.Margin = new Thickness(-20, 0, 0, 0);
A quick question though are you using it in UWP?
Also since you are using CollectionView why not use a single item in DataTemplate that goes into a GridItemsLayout?
More information here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout#vertical-grid

Xamarin forms FFImageLoading CornersTranformation

I have a UI design like at following image. I'm using FFImageLoading plugin and Corner Transformations but I could not cut image form top to bottom of image. How can I do this ?
I'm trying following code but it's not working.
var imgProd = new CachedImage { Source = temp.imgSource, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, Margin = 0, DownsampleHeight = vm.featureStackHeight, DownsampleToViewSize = true, Aspect = Aspect.Fill};
imgProd.Transformations.Add(new CornersTransformation { CornersTransformType = CornerTransformType.TopLeftCut | ,TopLeftCornerSize=50 });
The following works in xaml:
<ffimageloading:CachedImage Source ="{Binding ImageFile}"
<ffimageloading:CachedImage.Transformations>
<fftransformations:CornersTransformation
CornersTransformType="TopLeftCut"
TopLeftCornerSize="50" />
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>

Setting a maximum height to a control, or getting ScrollView to respect other's MinimumHeightRequest

There is MinimumHeightRequest, but no MaximumHeightRequest for Views in Xamarin Forms. In its absence I'm trying to achieve the following:
I have two controls on my screen: a Signature and some legal-text. I would like the signature to take up much screen as possible, and for the legal-text to take the minimum space for itself but only up to half the parent height - and then to scroll if the text doesn't fit. I've tried StackLayout and Grid but neither quite do what I want in coping with all situations. If it existed simply setting a MaximumHeightRequest on the ScrollingLegal View would sort it out. But it doesn't. Here's what I've tried...
Controls defined as:
var Pad = new SignaturePadView() {
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
MinimumHeightRequest = Application.Current.MainPage.Height / 2,
};
// Put legal text in a scroll view in case it doesn't fit on the screen.
var ScrollingLegal = new ScrollView { VerticalOptions = LayoutOptions.End, Content = new Label { Text = caption } };
Arranged with StackLayout like this it looks great on an iPad - text at the bottom of the screen signature taking up all the other space. On a small iPhone though, the text takes up all the screen and the signature appears to ignore the MinimumHeightRequest (this might be a bug I suppose?).
Stack.Children.Add(Pad);
Stack.Children.Add(ScrollingLegal);
I can add a HeightRequest to the ScrollView but then it always takes up X height. With a small amount of text I don't want that.
I have also tried a Grid:
var GridLayout = new Grid
{
Padding = 1,
RowDefinitions = {
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) },
},
ColumnDefinitions = {
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
},
};
GridLayout.Children.Add(Pad, 0, 0);
GridLayout.Children.Add(ScrollingLegal, 0, 1);
But that too always gives too much space to the text.
Is there a way of setting a Max Height?

Binding data in Xamarin Forms

I have an enumerable datasource that I want to bind to a some control in Xamarin Forms.
I want the layout to look something like -
ColA | ColB | ColC | ColD
3 4 1 6
15 25 62 26
Just a standard table with a header.
I have tried the ListView but it doesn't support headers. I've tried TableLayout but it doesn't support binding to a datasource.
Have I missed something or is there some other control I should use.
Yeah theres no control out of the box for it, here's a one way to hack it:
Create a grid that has a row for your header (4 columns), the next row has a listview with a viewcell for your items, then you use a viewcell template, and in your template you have the grid with 4 columns ,and 4 labes ( 1 each column) just like the header, now the trick here is how will you bind 4 values in 1 viewcell, my sugestions is having a object like 'Something' that has Prop1, Prop2, Prop3, Prop4 , and now you bind label1 to Prop1, label2 to Prop2 and so one,
So when you create your datasource it will be something like:
var list = List<Something>();
list.Add(new Something() { Prop1 = 3, Prop2 = 4, Prop3 = 1, Prop4 = 6});
list.Add(new Something() { Prop1 = 15, Prop2 = 25, Prop3 = 62, Prop4 = 26});
this should accomplish what you need..
As Stephane Delcroix mentioned in this other StackOverflow question:-
"Horizontal ListView Xamarin.Forms"
The ListView does not natively support horizontal orientation, so you couldn't use this as your are ideally wanting to bind to an IEnumerable datasource.
There is another hack method mentioned in the following post:-
"How to adjust size of Horizontal ListView in Xamarin.Forms?"
that suggests to use Rotation to get around this, although this will more than likely be quite cumbersome and problematic in cases as rotation will apply outside a normal View bounds, unless it is a square dimension.
That would allow you to use your bindable datasource however by using the ItemTemplate property of the ListView and creating your DataTemplate with other control bindings specified in it.
It is however not ideal with the rotation hack, and personally I wouldn't even consider it.
The best method, at present, would be to do as Rui is mentioning, creating some kind of Grid of equal columns and do your formatting within.
You could also achieve this with a StackLayout specifying a specific WidthRequest for each of the child Views and then do your formatting from within each child View.
Should you need to display more than 4 columns, or more information than would fit on a typical device screen width, then you may want to put a ScrollView as the parent of this Grid or StackLayout, so you can view everything with better spacing rather than cramming everything in.
As a final alternative - you could write your own custom-renderer to support a horizontal ListView with a bindable datasource.
<Grid x:Name="dgvEmp">
<Grid.RowDefinitions>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
</Grid>
List<Employee> lstEmp;
public Gridbasic()
{
InitializeComponent();
lstEmp= new List<Employee>()
{
new Employee()
{
EmpId=1,EmpName="Test1",EmpSalary=12345
},
new Employee()
{
EmpId=2,
EmpName="Test2",
EmpSalary=12345
},
new Employee()
{
EmpId=3,
EmpName="Test3",
EmpSalary=12334
}
};
dgvEmp.Children.Add(new Label() {Text="EmpName" }, 0, 0);
dgvEmp.Children.Add(new Label() { Text = "EmpSal" }, 1, 0);
for(int i=0,j = 1; i <lstEmp.Count; i++)
{
Label lbl = new Label()
{
Text = lstEmp[i].EmpName
};
Label llblEmpSal = new Label()
{
Text = lstEmp[i].EmpSalary.ToString()
};
dgvEmp.Children.Add(lbl, 0, j);
dgvEmp.Children.Add(llblEmpSal, 1, j);
j++;
}
}

Resources