Xamarin maximum grid row/ column definitions - c#

I've only started playing with xamarin recently but I'm making a roguelike using xamarin and I had the idea of using a grid for the player map (each X Y position in the grid would be representing the randomly generated map) I've hit a snag though in that putting things any thing over the 55th column seems to push them off the screen (See image below)
Here's my code so far:
StackLayout stackLayout = new StackLayout() { VerticalOptions = LayoutOptions.FillAndExpand };
Grid grid = new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
stackLayout.Children.Add(grid);
for (int i = 0; i < 300; i++)
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
}
// Row 0
// The BoxView and Label are in row 0 and column 0, and so only needs to be added to the
// Grid.Children collection to get default row and column settings.
grid.Children.Add(new BoxView
{
Color = Color.Green
});
grid.Children.Add(new Label
{
Text = "Row 0, Column 0",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
});
// This BoxView and Label are in row 0 and column 1, which are specified as arguments
// to the Add method.
grid.Children.Add(new BoxView
{
Color = Color.Blue
}, 55, 0);
grid.Children.Add(new Label
{
Text = "Row 0, Column 1",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 1, 0);
// Row 1
// This BoxView and Label are in row 1 and column 0, which are specified as arguments
// to the Add method overload.
grid.Children.Add(new BoxView
{
Color = Color.Teal
}, 0, 1, 1, 2);
grid.Children.Add(new Label
{
Text = "Row 1, Column 0",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 0, 1, 1, 2); // These arguments indicate that that the child element goes in the column starting at 0 but ending before 1.
// They also indicate that the child element goes in the row starting at 1 but ending before 2.
grid.Children.Add(new BoxView
{
Color = Color.Purple
}, 1, 2, 1, 2);
grid.Children.Add(new Label
{
Text = "Row1, Column 1",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 1, 2, 1, 2);
// Row 2
// Alternatively, the BoxView and Label can be positioned in cells with the Grid.SetRow
// and Grid.SetColumn methods.
BoxView boxView = new BoxView { Color = Color.Red };
Grid.SetRow(boxView, 2);
Grid.SetColumnSpan(boxView, 2);
Label label = new Label
{
Text = "Row 2, Column 0 and 1",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
Grid.SetRow(label, 2);
Grid.SetColumnSpan(label, 2);
grid.Children.Add(boxView);
grid.Children.Add(label);
Title = "Basic Grid demo";
Content = grid;
So I guess the question is a few folds, how can I "Zoom" out on the grid view to see the other cells of the grid? Additionally, am I even going about this the right way ? or is there a better approach that using a grid?

You should warp the content into a ScrollView and set Content = scrollView, then you can scroll to see all the elements:
public MainPage()
{
InitializeComponent();
StackLayout stackLayout = new StackLayout() { VerticalOptions = LayoutOptions.FillAndExpand };
Grid grid = new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
stackLayout.Children.Add(grid);
//......
grid.Children.Add(boxView);
grid.Children.Add(label);
Title = "Basic Grid demo";
//warp the content into a ScrollView
ScrollView scrollView = new ScrollView { Content = stackLayout };
scrollView.Orientation = ScrollOrientation.Both;
Content = scrollView;
}

Related

.Net Maui Grid doesn't change after being updated

I'm new to .Net Maui and I'm stuck on a probably very stupid problem.
In a ContentPage, I defined a ScrollView and a Grid by parameterizing it with 4 columns, this is the XAML code:
<ScrollView x:Name="scrollView">
<Grid x:Name="tabella"
ColumnDefinitions="*,2*,2*,*"
Margin="10,10,10,10" />
</ScrollView>
When the page is loaded, it calls the Populate() method, here's the code:
private void PopolaTabella(List<ClassPrenotazione> prenotazioni)
{
tabella.RowDefinitions.Clear();
CreaIntestazione();
int riga = 1;
foreach (ClassPrenotazione prenotazione in prenotazioni)
{
AggiungiRiga(riga, prenotazione);
riga++;
}
scrollView.ForceLayout();
}
And here's the CreaIntestazione() code:
private void CreaIntestazione()
{
tabella.RowDefinitions.Add(new RowDefinition(60));
tabella.Add(new Border
{
StrokeThickness = 1,
Stroke = Brush.Black,
BackgroundColor = Color.FromArgb("f05924")
}, 0, 0);
tabella.Add(new Label
{
Text = "Nr.",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 0, 0);
tabella.Add(new Border
{
StrokeThickness = 1,
Stroke = Brush.Black,
BackgroundColor = Color.FromArgb("f05924")
}, 1, 0);
tabella.Add(new Label
{
Text = "Data",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 1, 0);
tabella.Add(new Border
{
StrokeThickness = 1,
Stroke = Brush.Black,
BackgroundColor = Color.FromArgb("f05924")
}, 2, 0);
tabella.Add(new Label
{
Text = "Orario",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}, 2, 0);
}
AggiungiRiga is the same of CreaIntestazione but with data.
When the page appears for the first time, everything works nice.
When an element is removed from "prenotazioni", the Populate() command is called again. At this point, the Grid does not change.
I have done many tests and the only result I have obtained is by changing table.RowDefinitions.Clear(); with table.Clear(); and adding Content = table as the last command.
In this way, the updated table is shown, but obviously scrolling no longer works.
Can you help me please?
The Grid control isn’t the optimal choice for your scenario.
If you want to show multiple data rows like in your table definition, you should use CollectionView together with an ObservableCollection.
Both are made to suit your needs. The two documentation links have plenty of usage samples and detailed explanations.
Hope this helps.

ChartView within StackLayout cuts off Chart

Here is my code:
List<Entry> entries = new List<Entry>
{
new Entry(7)
{
Color = SKColor.Parse("#166DA3"),
},
new Entry(3)
{
Color = SKColors.Transparent,
}
};
public RoundScore2()
{
Content = _contentLayout; // layout inherited from a different class
Label congrats = new Label
{
Text = "Congratulations!",
FontAttributes = FontAttributes.Bold,
FontSize = 30,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.Start,
TextColor = Color.Black
};
_contentStack.Children.Add(congrats); // _contentStack inherited from same class, _contentStack is added to _contentLayout
ChartView Chart1 = new ChartView
{
VerticalOptions = LayoutOptions.CenterAndExpand,
HeightRequest = 80
};
_contentStack.Children.Add(Chart1);
Chart1.Chart = new DonutChart() { Entries = entries, HoleRadius = 5 };
Button nextRound = new Button
{
Text = "Start Round " + roundCounter.ToString(),
Margin = new Thickness(10, 20, 10, 10),
TextColor = Color.Black,
BackgroundColor = Color.FromHex("48AADF"),
FontFamily = "Source Sans Pro",
FontSize = 20,
FontAttributes = FontAttributes.Bold,
CornerRadius = 8,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.StartAndExpand,
WidthRequest = 180
};
_contentStack.Children.Add(nextRound);
}
Stack overflow is not letting me add the photo right now ("Failed to upload image; couldn't reach imgur")...but basically, I can only see the horizontal middle section of the pie chart. There is enough space for the chart to show, but it is just cut off. I have tried setting VerticalOptions = LayoutOptions.FillAndExpand along with LayoutOptions.CenterAndExpand and no luck. Does anyone know why this is happening?
Edit: even with the Label and Button taken out, the view is still cut off.
but basically, I can only see the horizontal middle section of the pie chart.
From shared code of ChartView, I'm guessing that whether the width of chart view is too small.
ChartView Chart1 = new ChartView
{
VerticalOptions = LayoutOptions.CenterAndExpand,
HeightRequest = 80
};
If so , you can add HorizontalOptions as follow:
ChartView Chart1 = new ChartView
{
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
HeightRequest = 80
};
In addition , also can add HorizontalOptions for StackLayout:
_contentStack.HorizontalOptions = LayoutOptions.FillAndExpand;
_contentStack.VerticalOptions = LayoutOptions.FillAndExpand;
It worked after changing VerticalOptions = LayoutOptions.Center and HorizontalOptions = LayoutOptions.Fill as well as changing HoleRadius = .5f.

How to navigate to a new page in xamarin forms using ONLY c#

I am working on a simple app that keeps track of life for a card game. I am very new to xamarin so I am starting small and just slowly adding more functionality. Currently, I have two pages; One page (the page it starts on (root page?) that has only one lifetotal number, two buttons for incrementing and decrementing, and one button to switch to a two player layout, and then a second page with two lifetotals and 4 buttons (an increment and decrement for each lifetotal). I am writing all of this in C# and I would like to keep it that way, however, I am having trouble finding a way to make it so that button that switches to the two player layout will present the second page. Everything ive googled seems to point back to xml which I want to avoid. Can anyone help me understand how to do this?
I am building off an app my buddy made for to understand how xamarin works so thats what all the weird comments are
code: (the delegate i need to fill in is at the bottom, called moreplayers)
namespace SampleApp
{
//contentpage is the base class for all pages.
//You should make a base class for this page that isn't contentpage, but inherits from content page, then you can add custom methods that extend across all pages.
//Like adding a progress spinner, or disabling all UI elements.
public class MainPage : ContentPage
{
public MainPage()
{
CreateUI();
}
private void CreateUI()
{
Stats Player1 = new Stats();
Player1.LifeTotal = 20;
//abstracting out a function to build UI is good, but breaking this down further is better.
var MainGrid = new Grid()//grids are the bread and butter of xamarin forms, the documentation has lots of good examples I won't try to replicate here.
{
HorizontalOptions = LayoutOptions.FillAndExpand,//these are on all UI elements, gotta specify them or the default values will probably screw up.
VerticalOptions = LayoutOptions.FillAndExpand
};
//I usually make a bunch of nice extensions on the Grid to add rows and columns easily
MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
MainGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
//grid where life total label will live
var GridForLifeTotal = new Grid()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
GridForLifeTotal.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForLifeTotal.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForLifeTotal.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
//grid where buttons will live
var GridForButtons = new Grid()
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
GridForButtons.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForButtons.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
GridForButtons.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
MainGrid.Children.Add(GridForLifeTotal, 0, 0); //add items to the grid based on position
MainGrid.Children.Add(GridForButtons, 0, 1);
//Add labels
var lifeLabel = new Label()
{
Text = Player1.LifeTotal.ToString(),
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 60
};
GridForLifeTotal.Children.Add(lifeLabel, 0, 0);
//Add buttons
var UpButton = new Button()
{
Text = "+",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 30
};
UpButton.Clicked += delegate {
//delegates are bad form but it's late and I'm tired you should put this login in a view model class and have that view model be a private property on this view.
//View (this), View Model (the logic layer) then a Model to hold the life total and any other user data?
Player1.LifeTotal += 1;
lifeLabel.Text = Player1.LifeTotal.ToString();
};
var DownButton = new Button()
{
Text = "-",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = 30
};
DownButton.Clicked += delegate {
//delegates are bad form but it's late and I'm tired
Player1.LifeTotal -= 1;
lifeLabel.Text = Player1.LifeTotal.ToString();
};
var MorePlayers = new Button()
{
Text = "2 Player Game",
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.End,
FontSize = 30
};
MorePlayers.Clicked += delegate
{
//need to figure out what goes here
};
GridForButtons.Children.Add(UpButton, 0, 0);
GridForButtons.Children.Add(DownButton, 1, 0);
GridForButtons.Children.Add(MorePlayers, 0, 1);
Content = MainGrid;//very important, otherwise you don't actually see anything you've built
}
}
}
first, you need to wrap MainPage in a NavigationPage when you first assign it in your App.xaml.cs
MainPage = new NavigationPage(new MainPage());
then, to navigate to the next page in your delegate
this.Navigation.PushAsync(new Page2());

Xamarin - Image overflowing StackLayout

I am trying to make a gallery style grid view in Xamarin forms for iOS and Android but have an issue where layout options seem to be ignored and I get different results for iOS and Android.
Basic layout is:
frame with a border(red) containing a stack layout (pink) set to FillAndExpand for both horizontal and vertical options which contains a label at the top and an image below set to fill the rest of the stack.
The image seems to just expand outside of the stack and the frame and ignore the vertical options set.
I have tried setting these vertical options to Fill, FillAndExpand, CentreAndExpand but all have the same result.
If i remove the Stack layout and label and have the image as the only child element in the frame then it works as expected but I am required to also show a label.
The result is the same in landscape and portrait orientations.
Results on platform with iOS being the main issue here:
Code for adding an image to the grid:
var imageSource = ImageSource.FromStream(() => new MemoryStream(imageData));
var framedImage = new Frame
{
Padding = 0,
Margin = 3,
GestureRecognizers = { tapGesture },
Content = new StackLayout
{
Padding = 10,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Pink,
Children =
{
textLabel,
new Image
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Source = imageSource,
Aspect = Aspect.AspectFit
},
}
},
BackgroundColor = StyleSheet.BackgroundColorLight,
BorderColor = StyleSheet.OutlineColorDark,
CornerRadius = 5,
HasShadow = false
};
grid.Children.Add(framedImage, columnCounter, rowCounter);
Thanks in advance!
Fixed it by doing this:
var image = new Image
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Source = imageSource,
Aspect = Aspect.AspectFit
};
var framedImage = new Frame
{
Padding = 2,
Margin = 1,
GestureRecognizers = { tapGesture },
Content = image,
HasShadow = false,
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand
};
var innergrid = new Grid
{
RowDefinitions =
{
new RowDefinition {Height = new GridLength(20, GridUnitType.Auto)},
new RowDefinition {Height = new GridLength(20, GridUnitType.Star)},
}
};
innergrid.Children.Add(textLabel, 0, 0);
innergrid.Children.Add(framedImage, 0, 1);
var frame = new Frame
{
Padding = 5,
Margin = 3,
GestureRecognizers = { tapGesture },
Content = innergrid,
BackgroundColor = StyleSheet.BackgroundColorLight,
BorderColor = StyleSheet.OutlineColorDark,
CornerRadius = 5,
HasShadow = true
};
grid.Children.Add(frame, columnCounter, rowCounter);
I might have a go with the new FlexLayout to see if i can have simpler code

Using Xamarin ZXing.Net.Mobile - scanner stretched = ISSUE

I am currently using the package ZXing.Net.Mobile for Xamarin Forms.
I want content on the top of the screen and at the bottom of the screen and I want the scanner to be somewhere in the middle.
If I specify the height of the scanner, it stretches it making it ugly and not nice to have (because the scanner is meant to be used for full screen?).
I want to have some content on the top of the screen with a dynamic height, then I want the scanner with height 150-200, then I want some content to be shown on the rest of the screen.
I was looking into ZXingDefaultOverlay but I could not get it to work as I wanted.
Anyone has an idea, example or an answer that can help me?
Following is the sample code where I have used Grid
for showing content on top and bottom of the screen and middle screen contains scanner.
public ZXingDefaultOverlay()
{
BindingContext = this;
RowSpacing = 0;
VerticalOptions = LayoutOptions.FillAndExpand;
HorizontalOptions = LayoutOptions.FillAndExpand;
RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition { Height = new GridLength(2, GridUnitType.Star) });
RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
Children.Add(new BoxView
{
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent,
Opacity = 0.7,
}, 0, 0);
Children.Add(new BoxView
{
VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.Transparent,
Opacity = 0.7,
}, 0, 2);
StackLayout ImageLabelContainer = new StackLayout();
Image imgBox = new Image();
imgBox.Source = "scan_qr.png";
imgBox.VerticalOptions = LayoutOptions.Fill;
imgBox.HorizontalOptions = LayoutOptions.FillAndExpand;
ImageLabelContainer.Children.Add(imgBox);
Label lblSuccess = new Label();
lblSuccess.Margin = new Thickness(0, 7, 0, 0);
lblSuccess.HorizontalTextAlignment = TextAlignment.Center;
lblSuccess.TextColor = Color.Green;
lblSuccess.AutomationId = "zxingDefaultOverlay_BottomTextLabel";
lblSuccess.SetBinding(Label.TextProperty, new Binding(nameof(BottomText)));
ImageLabelContainer.Children.Add(lblSuccess);
Children.Add(ImageLabelContainer, 0, 1);
}
Here you can set height of the rows as per your requirement.

Categories

Resources