I'm trying to implement a kind of collapsable StackLayout.
Every tine the user clicks the button, it expands or collapse the stacklayout to show/hide more details.
I was able to achieve more/less this with the code below, but it doesn't look right and the effect isn't great, because it grows immediately and I'm applying the effect to other element.
Do you have any suggestions to do this, I'm using xamarin Forms?
XAML
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Sample.MyStackLayout" >
<StackLayout x:Name="TopLayout">
<StackLayout Orientation="Horizontal">
<Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand" />
<Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
</StackLayout>
<BoxView Color="Black" HeightRequest="1" />
<StackLayout Orientation="Horizontal">
<Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand" />
<Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="some text" VerticalOptions="Center" HorizontalOptions="StartAndExpand" />
<Label Text="123" VerticalOptions="Center" HorizontalOptions="End" FontSize="Large" />
</StackLayout>
<Button x:Name="btn" Text="Button" Clicked="btnClicked" />
</StackLayout>
<StackLayout x:Name="MoreDetails" IsVisible="False">
<Label Text="some text 1"></Label>
<Label Text="some text 2"></Label>
<Label Text="some text 3"></Label>
<Label Text="some text 4"></Label>
<Label Text="some text 5"></Label>
<Label Text="some text 6"></Label>
<Label Text="some text 7"></Label>
<Label Text="some text 8"></Label>
</StackLayout>
</StackLayout>
Code
public AccountInfo()
{
InitializeComponent();
}
bool isExpanded = false;
protected async void btnClicked(object sender, EventArgs e)
{
if (isExpanded)
{
await MoreDetails.FadeTo(0);
MoreDetails.IsVisible = !isExpanded;
}
else
{
MoreDetails.IsVisible = !isExpanded;
await MoreDetails.FadeTo(1);
}
isExpanded = !isExpanded;
}
You can create a Custom control that does this for you. If you create an 'ExpandableView' Content View with Xaml like:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyProject.CustomControls.ExpandableView">
<StackLayout x:Name="Layout" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout x:Name="SummaryRegion"/>
<StackLayout x:Name="DetailsRegion" IsVisible="False"/>
</StackLayout>
</ContentView>
And wire up the .cs class like so:
public partial class ExpandableView: ContentView
{
private TapGestureRecognizer _tapRecogniser;
private StackLayout _summary;
private StackLayout _details;
public ExpandableView()
{
InitializeComponent();
InitializeGuestureRecognizer();
SubscribeToGuestureHandler();
}
private void InitializeGuestureRecognizer()
{
_tapRecogniser= new TapGestureRecognizer();
SummaryRegion.GestureRecognizers.Add(_tapRecogniser);
}
private void SubscribeToGuestureHandler()
{
_tapRecogniser.Tapped += TapRecogniser_Tapped;
}
public virtual StackLayout Summary
{
get { return _summary; }
set
{
_summary = value;
SummaryRegion.Children.Add(_summary);
OnPropertyChanged();
}
}
public virtual StackLayout Details
{
get { return _details; }
set
{
_details = value;
DetailsRegion.Children.Add(_details);
OnPropertyChanged();
}
}
private void TapRecogniser_Tapped(object sender, EventArgs e)
{
if (DetailsRegion.IsVisible)
{
DetailsRegion.IsVisible = false;
}
else
{
DetailsRegion.IsVisible = true;
}
}
And define it in your xaml like so:
<CustomControls:ExpandableView>
<CustomControls:ExpandableView.Summary>
<StackLayout>
YOUR STUFF HERE
</StackLayout>
</CustomControls:ExpandableView.Summary>
<CustomControls:ExpandableView.Details>
<StackLayout>
YOUR STUFF HERE
</StackLayout>
</CustomControls:ExpandableView.Details>
</CustomControls:ExpandableView>
Where CustomControls is the reference to namespace where the ExpandableView exists.
You can expand this further by adding things such as animations on expand, highlight the 'Summary Region' when expanded etc...
In your APP class, add flag to enable experimental feature:
Device.SetFlags(new string[] { "Expander_Experimental" });
Then, you can use it like this:
<Expander>
<Expander.Header>
<StackLayout>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Text="One label" />
<Label Grid.Row="1" Text="One label" />
<Label Grid.Row="2" Text="One label" />
<Label Grid.Row="0" Grid.Column="1" Text="123" />
<Label Grid.Row="1" Grid.Column="1" Text="123" />
<Label Grid.Row="2" Grid.Column="1" Text="123" />
<Image x:Name="Your_Image_DropDown" Grid.Row="3"
Grid.ColumnSpan="2" Source="YOUR IMAGE LINK/SOURCE HERE"
HorizontalOptions="Center"/>
</Grid>
</StackLayout>
</Expander.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="AUTO"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Text="One label" />
<Label Grid.Row="1" Text="One label" />
<Label Grid.Row="2" Text="One label" />
<Label Grid.Row="0" Grid.Column="1" Text="123" />
<Label Grid.Row="1" Grid.Column="1" Text="123" />
<Label Grid.Row="2" Grid.Column="1" Text="123" />
</Grid>
</Expander>
For more information
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/expander
Wrap your everything but MoreDetails to another stack layout and name it "TopLayout"
void ShowMore(){
TopLayout.TranslateTo(0, -TopLayout.Bounds.Height, 300, Easing.Linear);
MoreDetails.LayoutTo(new Rectangle(0, 0, MoreDetails.Bounds.Width, MoreDetails.Bounds.Height + TopLayout.Bounds.Height), 300, Easing.Linear);
}
void ShowLess(){
TopLayout.TranslateTo(0, 0, 300, Easing.Linear);
MoreDetails.LayoutTo(new Rectangle(0, MoreDetails.Bounds.Height, MoreDetails.Bounds.Width, MoreDetails.Bounds.Height - MoreDetails.Bounds.Height), 300, Easing.Linear);
}
100 - here is your displacement value
As a bonus:
MoreLessImage.RotateXTo(180, Duration, TargetEasing);
you can morph your button like this to animate ShowMore/ShowLess image
We can achieve collapsible view using Xamarin Community Toolkit's Expander. Xamarin Community Toolkit also provides a lot of views, controls, behaviors, extensions, effects, etc.
Related
I have recently started using .Net MAUI. however, I have now encountered a problem with which I could not find any help on the internet. I want when I click a button that a defined click function is called. However, I can't pass a parameter to the "Clicked" attribute. How do I do that?
I tried to solve my problem with the help of various posts in different online forums, but none of these posts helped and so I am creating my own.
My code so far:
XAML:
<Grid RowSpacing="50" Margin="50">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Stroke="Transparent"
StrokeThickness="3"
StrokeShape="RoundRectangle 30,30,30,30"
HorizontalOptions="Center"
BackgroundColor="White"
Grid.Row="0"
Grid.Column="0">
<Border.GestureRecognizers>
<TapGestureRecognizer Tapped="onStudentSelected"/> <!-- Here i want to give a param -->
</Border.GestureRecognizers>
<VerticalStackLayout WidthRequest="300" HeightRequest="250">
<Border Stroke="#21B1FF"
StrokeThickness="3"
StrokeShape="RoundRectangle 15,15, 15, 15"
HorizontalOptions="Center"
BackgroundColor="White"
Margin="10">
<VerticalStackLayout WidthRequest="240">
<Label FontSize="25" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" Text="Max Muster" Padding="10"/>
</VerticalStackLayout>
</Border>
<Border Stroke="#21B1FF"
StrokeThickness="3"
StrokeShape="RoundRectangle 15,15, 15, 15"
HorizontalOptions="Center"
BackgroundColor="White">
<VerticalStackLayout WidthRequest="240">
<Label Margin="5" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" Text="Newest Grade: 5.8" Padding="10"/>
<Label Margin="5" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" Text="Average: 4.5" Padding="10"/>
<Label Margin="5" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" Text="Best Subject: Math" Padding="10"/>
</VerticalStackLayout>
</Border>
</VerticalStackLayout>
</Border>
</Grid>
C#:
private async void onStudentSelected(object sender, EventArgs e, int id)
{
await Shell.Current.GoToAsync("StudentDetail" + id);
}
Am grateful for any help :)
you can get the id from the BindingContext
private async void onStudentSelected(object sender, EventArgs e)
{
// assuming your Model class is "Student"
var border = (Border)sender;
var item = (Student)border.BindingContext;
var id = item.Id;
await Shell.Current.GoToAsync("StudentDetail" + id);
}
alternately (and more aligned with MVVM) you can use Command and CommandParameter
Just as Jason said, you can use the Command and CommandParameter.
Here is the demo for you to refer to.
<TextCell Text="Customimze an Entry"
Detail="Select text on focus"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type views:CustomizeEntryPage}" />
Code behind:
public ICommand NavigateCommand { get; private set; }
public MainPage()
{
InitializeComponent();
NavigateCommand = new Command<Type>(
async (Type pageType) =>
{
Page page = (Page)Activator.CreateInstance(pageType);
await Navigation.PushAsync(page);
});
BindingContext = this;
}
Hope everyone is well. I'm running into a UI problem with my cross platform app for xamarin.forms. Basically it shows different on ios when compared to android.
I have a function on the AdminPage that when button clicks opens the PopupView, the popUp will either contain details on the user, or the order, for this example we are using orderDetails
private void ShowUserDetails_Clicked(object Sender, EventArgs e)
{
Button button = (Button)Sender;
string UserId = button.CommandParameter.ToString();
PopupNavigation.Instance.PushAsync(new PopupView(-1, int.Parse(UserId)));
}
The problem lies in the UI of the popUp, if you notice the android phone on the left of the image below. It loads the way I want it to. Displaying lable for email | phone number, followed by listview of OrderDetails below. As you can see it looks fine on the android. The problem is on the ios. Where is the whitespace coming from at the top of the PopUpView?
If you take a close look at the PopUpView on the iphone 11, there is a scroll bar to the right of the popUp . It starts where the text starts, and I cant scroll any further up. Its almost as if there is an extra row placed before anything else. I have looked extensively through the code and can't figure it out. So I want to remove the whitespace, have even tried listview.scrollTo for the listview but with no success..any help would be great thank you
<?xml version="1.0" encoding="utf-8" ?>
<pages:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BottleShop.Views.PopupView"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
xmlns:converters="clr-namespace:BottleShop.ViewModels.Converters">
<StackLayout x:Name="StackSearchResultsOuter" BackgroundColor="Transparent" HorizontalOptions="Center" VerticalOptions="Center">
<StackLayout.Resources>
<converters:ProductIdToProductNameConverter x:Key="converter"/>
</StackLayout.Resources>
<BoxView x:Name="InvisibleSpacer" BackgroundColor = "Transparent"
HeightRequest="80" />
<StackLayout x:Name="StackLayoutOrders" IsVisible="{Binding SLOrders}">
<ListView BackgroundColor="White" ItemsSource="{Binding PreviousOrderDetailsForUserLV}" HasUnevenRows="True" SeparatorVisibility="None">
<ListView.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="0" x:Name="UserInfoLabel" HorizontalOptions="Center" Margin="10,10,0,0"/>
<BoxView Grid.Row="1"
Grid.ColumnSpan="4"
BackgroundColor="LightGray"/>
<Label Grid.Column="0" Text="Product" Grid.Row="1" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="1" Grid.Row="1" Text="Quantity" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="2" Grid.Row="1" Text="Price" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="3" Grid.Row="1" Text="Sub" HorizontalOptions="Center" Margin="0,10,0,0"/>
<!--<BoxView Grid.Row="1"
Grid.ColumnSpan="4"
HeightRequest="1"
BackgroundColor="LightGray"/> -->
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10" RowSpacing="10" ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="43*" />
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="24*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand" Text="{Binding ProductId, Converter={StaticResource converter}}"/>
<Label Grid.Column="1" Grid.Row="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Text="{Binding Quantity}"/>
<Label Grid.Column="2" Grid.Row="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Text="{Binding PriceOfItem, StringFormat='£{0:0.00}'}"/>
<Label Grid.Column="3" Grid.Row="0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Text="{Binding SubtotalForThisItem, StringFormat='£{0:0.00}'}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
<StackLayout x:Name="StackLayoutUsers" IsVisible="{Binding SLUsers}">
<ListView x:Name="UsersListView" BackgroundColor="White" ItemsSource="{Binding AllExistingUsersLV}" HasUnevenRows="True" SeparatorVisibility="None">
<ListView.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="Address Line 1" Grid.Row="0" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="1" Grid.Row="0" Text="Line 2" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="2" Grid.Row="0" Text="Town" HorizontalOptions="Center" Margin="0,10,0,0"/>
<Label Grid.Column="3" Grid.Row="0" Text="Mobile" HorizontalOptions="Center" Margin="0,10,0,0"/>
<BoxView Grid.Row="1"
Grid.ColumnSpan="4"
HeightRequest="1"
BackgroundColor="LightGray"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10" RowSpacing="10" ColumnSpacing="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="43*" />
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="24*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" HorizontalOptions="StartAndExpand" VerticalOptions="EndAndExpand" Text="{Binding AddressLine1}"/>
<Label Grid.Column="1" Grid.Row="0" HorizontalOptions="StartAndExpand" VerticalOptions="EndAndExpand" Text="{Binding AddressLine2}"/>
<Label Grid.Column="2" Grid.Row="0" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand" Text="{Binding City}"/>
<Label Grid.Column="3" Grid.Row="0" HorizontalOptions="EndAndExpand" VerticalOptions="EndAndExpand" Text="{Binding MobileNumber}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</StackLayout>
<!-- </Grid> -->
</pages:PopupPage>
using BottleShop.Data;
using BottleShop.Models;
using Microsoft.AppCenter.Crashes;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.Forms.Xaml;
namespace BottleShop.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PopupView //: ContentView
{
public ObservableCollection<OrderDetailsModel> PreviousOrderDetailsForUserLV { get; set; }
OrdersDatabaseController RecentOrdersController = new OrdersDatabaseController();
public ObservableCollection<UserModel> AllExistingUsersLV { get; set; }
UserDatabaseController UserController = new UserDatabaseController();
public bool SLOrders { get; set; }
public bool SLUsers { get; set; }
public PopupView(int OrderId, int UserId)
{
try
{
InitializeComponent();
//Show Orders PopUp
if (OrderId != -1)
{
SLOrders = true;
SLUsers = false;
List<OrderDetailsModel> RecentOrderDetailsList = RecentOrdersController.GetAllOrderDetailsByOrderId(OrderId);
PreviousOrderDetailsForUserLV = new ObservableCollection<OrderDetailsModel>(RecentOrderDetailsList as List<OrderDetailsModel>);
int startingHeightOfSL = 180;
int countOfOrderDetailRecords = PreviousOrderDetailsForUserLV.Count;
var tempHeightofStackSearchResults = countOfOrderDetailRecords * 40;
if (countOfOrderDetailRecords > 1)
{
StackSearchResultsOuter.HeightRequest = startingHeightOfSL + tempHeightofStackSearchResults;
}
else
{
StackSearchResultsOuter.HeightRequest = startingHeightOfSL;
}
UserInfoLabel.Text = "Email: " + PreviousOrderDetailsForUserLV[0].UserName + " | " + "Mobile: " + PreviousOrderDetailsForUserLV[0].UserMobileNumber;
}
else //Show Users PopUp
{
if(UserId != -1)
{
var a = 1;
SLOrders = false;
SLUsers = true;
List<UserModel> UsersList = UserController.GetUserWithId(UserId);
if (UsersList != null)
{
AllExistingUsersLV = new ObservableCollection<UserModel>(UsersList as List<UserModel>);
}
StackSearchResultsOuter.HeightRequest = 180;
}
}
BindingContext = this;
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
}
}
I am working on a small project in xamarin, I have written a code to display my items in a collection view. It turned out great but after I click plus button to add it to my orders, I can't transfer the item to other view, I can't get the data by using get set, please help. here is my code:
xaml
<ContentPage.Content>
<StackLayout>
<Frame BackgroundColor="{AppThemeBinding Light=#F7F7F7, Dark=#191919}"
Padding="0, 15" CornerRadius="0" HasShadow="False">
<StackLayout Orientation="Horizontal" VerticalOptions="Center" HorizontalOptions="Center" Spacing="10">
<Image Source="breakfast" HeightRequest="50"/>
<Label Text="Breakfast" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
TextColor="{AppThemeBinding Light=Black, Dark=White}" FontSize="30" FontAttributes="Bold"/>
</StackLayout>
</Frame>
<StackLayout Padding="20" BackgroundColor="{AppThemeBinding Light=White, Dark=Black}" Spacing="50">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CollectionView ItemsSource="{Binding Orders}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" VerticalItemSpacing="30"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding ImageURL}"
WidthRequest="50" HeightRequest="50"
Grid.Column="0"/>
<StackLayout Orientation="Vertical" Grid.Column="1">
<Label x:Name="orderName" Text="{Binding OrderName}" FontSize="Title">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="AddOrder" />
</Label.GestureRecognizers>
</Label>
<Label Text="{Binding Price, StringFormat='{0}$'}" FontSize="Subtitle"/>
</StackLayout>
<ImageButton Grid.Column="2"
Source="plus" HeightRequest="50" Clicked="AddOrder"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<StackLayout Padding="0, 120, 0, 0">
<ImageButton Source="back" HorizontalOptions="Center"
HeightRequest="60" Clicked="Back"/>
</StackLayout>
</StackLayout>
</StackLayout>
</ContentPage.Content>
this is the UI https://i.stack.imgur.com/QR133.png
After that I also tried assigning ImageButton with x:Name="addOrder" but I can't use it in .cs file,
cs file:
public partial class Breakfast : ContentPage
{
public Breakfast()
{
InitializeComponent();
}
void Back(object sender, EventArgs args)
{
Application.Current.MainPage = new Main();
}
async void AddOrder(object sender, EventArgs args)
{
await this.DisplayToastAsync("added to orders", 3000);
}
}
after pressing plus button it's running the AddOrder function because the DisplayToastAsync (or the popup window) is showing, there is no problem, the problem is how can I move the list item to My Orders View?
All answers and comments are appreciated! 😊
you can do something like this
async void AddOrder(object sender, EventArgs args)
{
var btn = (ImageButton)sender;
var item = (MyClassName)btn.BindingContext;
// navigate to the next page and pass item on the constructor
Navigation.PushAsync(new MyNextPage(item));
}
I'm trying to learn the basics of Xamarin.Forms in preparation for my first project in a few months time. To do this I've tried to make a calculator and I'm currently trying to get the layout right. I want it to have the "Display" take up say 1/4 of the screen and the buttons take up the remaining 3/4 of the screen, and when orientation changes I'd like it to change ratios.
Currently I have sort of accomplished this in portrait view
However when I rotate the screen it looks like this:
I want to be able to move the display bit from the left side to the top of the screen and maybe change it's size so it can accommodate all 4 rows of text.
This is my XAML for the CalcPage.
<?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="Calculator.Pages.CalcPage"
Title="Calculator">
<ContentPage.ToolbarItems>
<ToolbarItem Name="Settings" Text="Settings" Priority="0" Activated="Settings_Activated"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout x:Name="MainStack" Spacing="0" >
<StackLayout x:Name="DisplayStack" VerticalOptions="FillAndExpand" Spacing="0">
<Grid x:Name="DisplayGrid">
<Grid.RowDefinitions>
<RowDefinition Height ="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label x:Name="NumLabel1" Text ="" FontSize="Medium" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="Center" Grid.Row="0"/>
<Label x:Name="OpLabel" Text="" FontSize="Small" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" Grid.Row="1"/>
<Label x:Name="NumLabel2" Text ="" FontSize="Medium" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="Center" Grid.Row="2"/>
<Label x:Name="ResLabel" Text ="" FontSize="Large" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="Center" Grid.Row="3"/>
</Grid>
</StackLayout>
<StackLayout x:Name="ButtonStack" VerticalOptions="FillAndExpand" Spacing="0">
<Grid x:Name="ButtonsGrid">
<Grid.RowDefinitions>
<RowDefinition Height="18*"/>
<RowDefinition Height="18*"/>
<RowDefinition Height="18*"/>
<RowDefinition Height="18*"/>
<RowDefinition Height="18*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
</Grid.ColumnDefinitions>
<Button ClassId="Btn0" Text="0" Clicked="NumBtnClk_Event" Grid.Row="3" Grid.Column="1"
StyleClass="Default"/>
<Button ClassId="Btn1" Text="1" Clicked="NumBtnClk_Event" Grid.Row="2" Grid.Column="0"/>
<Button ClassId="Btn2" Text="2" Clicked="NumBtnClk_Event" Grid.Row="2" Grid.Column="1"/>
<Button ClassId="Btn3" Text="3" Clicked="NumBtnClk_Event" Grid.Row="2" Grid.Column="2"/>
<Button ClassId="Btn4" Text="4" Clicked="NumBtnClk_Event" Grid.Row="1" Grid.Column="0"/>
<Button ClassId="Btn5" Text="5" Clicked="NumBtnClk_Event" Grid.Row="1" Grid.Column="1"/>
<Button ClassId="Btn6" Text="6" Clicked="NumBtnClk_Event" Grid.Row="1" Grid.Column="2"/>
<Button ClassId="Btn7" Text="7" Clicked="NumBtnClk_Event" Grid.Row="0" Grid.Column="0"/>
<Button ClassId="Btn8" Text="8" Clicked="NumBtnClk_Event" Grid.Row="0" Grid.Column="1"/>
<Button ClassId="Btn9" Text="9" Clicked="NumBtnClk_Event" Grid.Row="0" Grid.Column="2"/>
<Button ClassId="Btn+" Text="+" Clicked="OprBtnClk_Event" Grid.Row="0" Grid.Column="3"/>
<Button ClassId="Btn-" Text="-" Clicked="OprBtnClk_Event" Grid.Row="1" Grid.Column="3"/>
<Button ClassId="BtnX" Text="X" Clicked="OprBtnClk_Event" Grid.Row="2" Grid.Column="3"/>
<Button ClassId="Btn/" Text="/" Clicked="OprBtnClk_Event" Grid.Row="3" Grid.Column="3"/>
<Button ClassId="Btn." Text="." Clicked="BtnClkPoint_Event" Grid.Row="3" Grid.Column="0"/>
<Button ClassId="BtnC" Text="AC" Clicked="BtnClkClear_Event" Grid.Row="3" Grid.Column="2"/>
<Button ClassId="Btn=" Text="=" Clicked="BtnClkEquals_Event" Grid.Row="4" Grid.Column="3"/>
</Grid>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
In the C# I have this function for detecting orientation changes.
private double width = 0;
private double height = 0;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if(this.width != width || this.height != height)
{
this.width = width;
this.height = height;
}
if(width > height)
{
MainStack.Orientation = StackOrientation.Horizontal;
DisplayStack.VerticalOptions = LayoutOptions.Start;
ButtonStack.VerticalOptions = LayoutOptions.End;
}
else
{
MainStack.Orientation = StackOrientation.Vertical;
}
}
In landscape mode, remove in both Display and Buttons stack the VerticalOptions = FillAndExpand, and add HorizontalOptions = FillAndExpand
Hello I am working on a app in xamarin forms and my home screen UI looks like this:
how do I get the nav bar to go right under the flashcards card?
here's my xaml code:
<?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="AppName.AppNameHome">
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView x:Name="listView" HasUnevenRows="true" ItemSelected="OnItemSelected"> Grid.Row="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame Padding="0,0,0,8" BackgroundColor="#d2d5d7">
<Frame.Content>
<Frame Padding="15,15,15,15" OutlineColor="Gray" BackgroundColor="White">
<Frame.Content>
<StackLayout Padding="20,0,0,0" Orientation="Horizontal">
<Image
HorizontalOptions="Start"
Source="{Binding Image}"/>
<Label
HorizontalOptions="CenterAndExpand"
Text="{Binding Name}"
FontFamily="OpenSans-Light"
FontSize="24"/>
</StackLayout>
</Frame.Content>
</Frame>
</Frame.Content>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Grid Grid.Row="1" BackgroundColor="#eff3f6" Padding="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Button Grid.Row="0" Grid.Column="1" Image="books.png" HorizontalOptions="CenterAndExpand" BackgroundColor="Transparent" Clicked="OpenBooks" />
<Button Grid.Row="0" Grid.Column="2" HorizontalOptions="EndAndExpand" BorderColor="Transparent" BackgroundColor="Transparent" Clicked="gotosettings" />
</StackLayout>
</Grid>
</Grid>
</ContentPage>
EDIT here's my c# code:
using System;
using System.Collections.Generic;
using AppName.Math;
using Xamarin.Forms;
using Plugin.Messaging;
using AppName.Flashcards;
using AppName.Science;
namespace AppName
{
public partial class AppNameHome : ContentPage
{
public SchoolToolsHome()
{
InitializeComponent();
var name = new List<Tools>
{
new Tools("Internet", "web.png"),
new Tools("E-Mail", "email.png"),
new Tools("Math", "math.png"),
new Tools("Science", "sci.png"),
new Tools("Handwriting","handwriteing.png"),
new Tools("FlashCards", "flashcard.png"),
};
listView.ItemsSource = name;
}
void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var tools = e.SelectedItem as Tools;
if (tools == null)
{
return;
}
ContentPage page = null;
switch (tools.Name)
{
case "Math":
page = new MathPage();
break;
case "Internet":
Device.OpenUri(new Uri("http://www.google.com"));
page = new AppNameHome();
break;
case "E-Mail":
Device.OpenUri(new Uri("mailto:"));
page = new AppNameHome();
break;
case "FlashCards":
page = new FlashCardHome();
break;
case "Science":
page = new ScienceHome();
break;
default:
page = new AppNameHome();
break;
}
((ListView)sender).SelectedItem = null;
page.BindingContext = tools;
Navigation.PushAsync(page);
}
public void OpenBooks(object sender, EventArgs e)
{
switch (Device.OS)
{
case TargetPlatform.iOS:
Device.OpenUri(new Uri("itms-books:"));
break;
case TargetPlatform.Android:
DependencyService.Get<OpenBookInterface>().openBooks();
break;
}
}
public void gotosettings(object sender, EventArgs e)
{
Navigation.PushAsync(new SettingsPage());
}
}
}
any help would be amazing!
Thanks in advance!
Have you tried ListView.Footer?
Gets or sets the string, binding, or view that will be displayed at
the bottom of the list view.
So you would have something like:
<ListView x:Name="listView" HasUnevenRows="true" ItemSelected="OnItemSelected"> Grid.Row="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame Padding="0,0,0,8" BackgroundColor="#d2d5d7">
<Frame.Content>
<Frame Padding="15,15,15,15" OutlineColor="Gray" BackgroundColor="White">
<Frame.Content>
<StackLayout Padding="20,0,0,0" Orientation="Horizontal">
<Image
HorizontalOptions="Start"
Source="{Binding Image}"/>
<Label
HorizontalOptions="CenterAndExpand"
Text="{Binding Name}"
FontFamily="OpenSans-Light"
FontSize="24"/>
</StackLayout>
</Frame.Content>
</Frame>
</Frame.Content>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<Grid BackgroundColor="#eff3f6" Padding="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Button Grid.Row="0" Grid.Column="1" Image="books.png" HorizontalOptions="CenterAndExpand" BackgroundColor="Transparent" Clicked="OpenBooks" />
<Button Grid.Row="0" Grid.Column="2" HorizontalOptions="EndAndExpand" BorderColor="Transparent" BackgroundColor="Transparent" Clicked="gotosettings" />
</StackLayout>
</Grid>
</ListView.Footer>
</ListView>