I need something like this:
And I have this right now:
XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="PetCare.Client.View.Forgot.ForgotPasswordView">
<ContentPage.Content>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" ></ColumnDefinition>
<ColumnDefinition Width="auto" ></ColumnDefinition>
<ColumnDefinition Width="2*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
x:Name="BackgroundTop">
</StackLayout>
<Image Grid.Row="0"
Grid.Column="1"
Grid.RowSpan="2"
x:Name="Icon"/>
<StackLayout Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="3"
Grid.RowSpan="4"
x:Name="BackgroundBot"
Spacing="0">
<Label Grid.Row="2"
Grid.Column="1"
x:Name="TextTitleLable"
/>
<StackLayout Grid.Row="3"
Grid.Column="1"
BackgroundColor="Red"
x:Name="BackgroundImage"
Spacing="0">
<Image x:Name="Phone"/>
</StackLayout>
<StackLayout Grid.Row="3"
Grid.Column="1"
BackgroundColor="Blue"
x:Name="BackgroundTextDescription"
Spacing="0">
<Label x:Name="TextDescription"></Label>
</StackLayout>
<StackLayout Grid.Row="4"
Grid.RowSpan="2"
x:Name="BackgroundInputNavigation">
<Entry x:Name="InputUser" />
<Label x:Name="ErrorMessage"/>
<Label x:Name="OtherOption"/>
</StackLayout>
</StackLayout>
<Button Grid.Row="8"
Grid.Column="1"
x:Name="BtnContinue"
Clicked="ClickedBtnContinue"/>
</Grid>
</ContentPage.Content>
</ContentPage>
C#:
//BackgrouTextndInputNavigation.
public ForgotPasswordView()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
SetColorsApp();
SetBtnContinueProperties();
SetTextTitleLableProperties();
SetIconProperties();
SetBackgroundTopProperties();
SetBackgroundBotProperties();
SetInputUserProperties();
SetOtherOptionProperties();
SetErrorMessageProperties();
SetPhoneProperties();
SetTextDescriptionProperties();
SetBackgroundImageProperties();
SetBackgroundTextDescriptionProperties();
}
private void SetBackgroundTextDescriptionProperties()
{
BackgroundTextDescription.Orientation = StackOrientation.Horizontal;
BackgroundTextDescription.HorizontalOptions = LayoutOptions.End;
BackgroundTextDescription.VerticalOptions = LayoutOptions.Center;
}
private void SetBackgroundImageProperties()
{
BackgroundImage.Orientation = StackOrientation.Horizontal;
BackgroundImage.HorizontalOptions = LayoutOptions.Start;
BackgroundImage.VerticalOptions = LayoutOptions.Center;
}
private void SetTextDescriptionProperties()
{
Label textPhoneNumber = new Label();
textPhoneNumber.Text = "XXXXX-XX89";
textPhoneNumber.TextColor = Color.FromHex(ColorsApp.ColorAppWarning);
textPhoneNumber.FontSize = 18;
string Text = "Foi enviada uma mensagem\ncom Código de Verificação\npara o Telefone "+ textPhoneNumber.Text+ "\ncadastrado em sua conta.\nInforme este Código para\nprosseguir.".Replace("\n", System.Environment.NewLine);
TextDescription.Text = Text;
TextDescription.FontSize = 18;
TextDescription.HorizontalTextAlignment = TextAlignment.End;
TextDescription.VerticalOptions = LayoutOptions.Center;
}
private void SetPhoneProperties()
{
Phone.Source = ImageSource.FromFile("phone.png");
Phone.HorizontalOptions = LayoutOptions.Start;
Phone.VerticalOptions = LayoutOptions.Center;
Phone.HeightRequest = 110;
}
private void SetErrorMessageProperties()
{
ErrorMessage.FontAttributes = FontAttributes.Bold;
ErrorMessage.Margin = new Thickness(0, 0, 0, 30);
}
private void SetOtherOptionProperties()
{
var tap = new TapGestureRecognizer();
tap.Tapped += async (s, e) => await Navigation.PushAsync(new OtherOptionResetPasswordView());
OtherOption.Text = "Usar outra opção de verificação";
OtherOption.FontSize = 18;
OtherOption.GestureRecognizers.Add(tap);
OtherOption.TextColor = Color.FromHex(ColorsApp.ColorAppPrimary);
tap = null;
}
private void SetInputUserProperties()
{
InputUser.Placeholder = "Inserir o Código";
InputUser.Margin = new Thickness(0, 20, 0, 0);
}
private void SetBackgroundBotProperties()
{
BackgroundBot.Padding = 30;
BackgroundBot.HeightRequest = 300;
BackgroundBot.HorizontalOptions = LayoutOptions.FillAndExpand;
BackgroundBot.VerticalOptions = LayoutOptions.FillAndExpand;
}
private void SetBackgroundTopProperties()
{
BackgroundTop.BackgroundColor = Color.FromHex(ColorsApp.ColorAppThemePrimary);
BackgroundTop.HorizontalOptions = LayoutOptions.FillAndExpand;
BackgroundTop.VerticalOptions = LayoutOptions.FillAndExpand;
BackgroundTop.Padding = 10;
}
private void SetIconProperties()
{
Icon.Source = ImageSource.FromFile("smartphone.png");
Icon.HorizontalOptions = LayoutOptions.Center;
Icon.VerticalOptions = LayoutOptions.Center;
}
private void SetTextTitleLableProperties()
{
TextTitleLable.HorizontalTextAlignment = TextAlignment.Start;
TextTitleLable.VerticalTextAlignment = TextAlignment.Start;
TextTitleLable.Text = "Verificar Identidade";
TextTitleLable.FontSize = 28;
TextTitleLable.TextColor = Color.FromHex(ColorsApp.ColorAppDark);
}
private void SetBtnContinueProperties()
{
BtnContinue.BackgroundColor = Color.FromHex(ColorsApp.ColorAppThemePrimary);
BtnContinue.VerticalOptions = LayoutOptions.End;
BtnContinue.HorizontalOptions = LayoutOptions.End;
BtnContinue.TextColor = Color.White;
BtnContinue.Padding = new Thickness(3);
BtnContinue.Margin = new Thickness(0, 0, 30, 30);
BtnContinue.Text = "Continuar";
BtnContinue.FontSize = 22;
BtnContinue.WidthRequest = 140;
}
private void SetColorsApp()
{
BackgroundBot.BackgroundColor = Color.FromHex(ColorsApp.ColorAppThemeDefault);
}
private async void ClickedBtnContinue(object sender, EventArgs e)
{
await Navigation.PushAsync(new ResetPasswordView());
}
I need two things: put the phone number in another color; and place the image next to the label.
I am very beginner, so I ask for some code along with the explanation. Please
It appears that even if the components are oriented horizontally, they
cannot stand side by side. I tried to put both in the same stack
layout but the stack layout height is based on the image, leaving one
or two lines of text hidden
Being honest with you, your Grid is a mess XD
First of all, you should be aware that by using Grid you should be able to get rid of most (if not all) of your Stacklayouts. Please take a look at the great docu that Xamarin has on Grid and many other topics :D
Next i share with you a Grid that i worked out to display what you want (notice the lack of Stacklayout!):
<Grid Padding="20" RowSpacing="70"
BackgroundColor="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Text="Verificar Identidade"
FontSize="30"/>
<Image Grid.Row="1" Grid.Column="0"
Source="TelefonImage"
WidthRequest="100"/>
<Label Grid.Row="1" Grid.Column="1"
FontSize="Medium"
HorizontalTextAlignment="End">
<Label.FormattedText>
<FormattedString>
<Span Text="Foi enviada uma mensagem com Código de Verificação para o Telefone "/>
<Span Text="XXXXX-XX89"
TextColor="Orange"/>
<Span Text=" cadastrado em sua conta. Informe este Código para prosseguir."/>
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>
On my side this looks like:
Also take note of what #Jason said in the comment: "everything you're doing in C# could be included in your XAML" (and that mean all the property setting).
I hope that will get you going!
Edit 1
I was able to quickly achieve the result in the image above by using the Hot Reload in Xamarin.Forms: play with it!
Related
I have been stuck with this issue for quite sometime now. It might be quite simple for you guys.
I have a collection view which has its item source that shows an observable collection. It shows messages from users when the app starts and then as a new message comes, I want to add the new message as the 1st element in the collectionview but it gets distorted and removes the prior items (only from the UI and not the actual observable collection data) and only shows 1 item. And when I navigate to other page and come back it shows correctly. Could someone please help me with this.
Xaml
<CollectionView Grid.Row="1" x:Name="myMessagesCV" SelectionMode="Single" SelectionChanged="MyMessagesCV_SelectionChanged" RemainingItemsThresholdReached="MyMessagesCV_RemainingItemsThresholdReached" RemainingItemsThreshold="5">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="8, 8, 8, 0">
<Grid Padding="0" ColumnSpacing="0" RowSpacing="0" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ffimageloading:CachedImage x:Name="userImage" Source="{Binding userImage}" Aspect="AspectFill" HeightRequest="75" Grid.Row="0" Grid.Column="0" CacheType="All" DownsampleToViewSize="True">
<ffimageloading:CachedImage.Transformations>
<transformations:CircleTransformation/>
</ffimageloading:CachedImage.Transformations>
</ffimageloading:CachedImage>
<Grid Grid.Row="0" Grid.Column="1" Padding="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Padding="10, 0, 0, 5" Text="{Binding userName}" LineBreakMode="TailTruncation" TextColor="Black" FontSize="Medium" Grid.Row="0" Grid.Column="0"/>
<Label Padding="10, 0, 0, 5" Text="{Binding message}" FontAttributes="{Binding newMessage}" FontSize="Small" TextColor="Black" Grid.Row="1" Grid.Column="0" HorizontalOptions="StartAndExpand" />
<Image Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Source="dot.png" Aspect="AspectFill" WidthRequest="10" IsVisible="{Binding IsNewMessage}" HorizontalOptions="Center" VerticalOptions="Center"/>
</Grid>
<BoxView BackgroundColor="LightGray" HeightRequest="1" Grid.Row="1" Grid.Column="1"/>
</Grid>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Code Behind Page
public ObservableCollection<Messages> MyMessagesList = new ObservableCollection<Messages>();
public async void GetMyMessages()
{
if (IsBusy)
return;
IsBusy = true;
var messages = await FirebaseDataHelper.GetMyMessages(uid);
var allmyMessages = await Task.WhenAll(FirebaseDataHelper.GetUserMessagesDetail(messages));
myunreadmsg = 0;
allmyMessagesCount = messages.Count;
IsSubscribe = false;
foreach (var message in allmyMessages)
{
if (message.Count > 0)
{
for (int i = 0; i < message.Count; i++)
{
if (message[i].status == "Delivered" && message[i].senderId != uid)
{
message[i].newMessage = FontAttributes.Bold;
message[i].IsNewMessage = true;
myunreadmsg++;
}
if (!MyMessagesList.Any(m => m.otheruserId == message[i].otheruserId) && message[i].message != null)
MyMessagesList.Add(message[i]);
}
}
}
myMessagesCV.ItemsSource = MyMessagesList;
}
public void GetMyNewMessages(Messages messageData)
{
IsSubscribe = false;
myunreadmsg = 0;
Messages newMessageData = new Messages();
if (messageData.status == "Delivered" && messageData.senderId != uid)
{
newMessageData.newMessage = FontAttributes.Bold;
newMessageData.IsNewMessage = true;
newMessageData.otheruserId = messageData.otheruserId;
newMessageData.senderId = messageData.senderId;
newMessageData.sellerId = messageData.sellerId;
myunreadmsg++;
}
else
{
newMessageData.newMessage = FontAttributes.None;
}
for (int i = 0; i < MyMessagesList.Count; i++)
{
if (MyMessagesList[i].otheruserId == messageData.otheruserId)
{
if (i == 0)
{
MyMessagesList[i].message = messageData.message;
if (myunreadmsg > 0)
{
MyMessagesList[i].IsNewMessage = true;
MyMessagesList[i].newMessage = FontAttributes.Bold;
}
break;
}
else
{
newMessageData.userName = MyMessagesList[i].userName;
newMessageData.userImage = MyMessagesList[i].userImage;
newMessageData.message = messageData.message;
newMessageData.time = messageData.time;
newMessageData.messageId = messageData.messageId;
MyMessagesList.Remove(MyMessagesList[i]);
MyMessagesList.Insert(0, newMessageData);
break;
}
}
}
myMessagesCV.ItemsSource = MyMessagesList;
}
Thank you guys. Hope I can solve this.
When your new message arrives, don't set ItemSource again like you do it in your GetMyNewMessages method:
myMessagesCV.ItemsSource = MyMessagesList;
Just insert your new message into MyMessagesList ObservableCollection.
MyMessagesList.Insert(0, newMessageData);
I made a simple project where it is demonstrated.
Here is xaml:
<ContentPage
x:Class="Search.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="White">
<Grid Margin="15">
<CollectionView
x:Name="CollectionView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding}" TextColor="Red" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
And here is code behind of this page:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
public ObservableCollection<int> Data { get; set; } = new ObservableCollection<int>(Enumerable.Range(1, 10));
protected override void OnAppearing()
{
base.OnAppearing();
Device.StartTimer(TimeSpan.FromSeconds(3), () =>
{
Data.Insert(0, new Random().Next(1, 1000));
return true;
});
CollectionView.ItemsSource = Data;
}
}
I'm learning how to develop UWP apps and I'm using Microsoft's documentation as tutorials/research.
I want to have an InkCanvas design similar to OneNote where the InkCanvas height and width can expand (as you're writing/drawing and reach the end of the window size) and can shrink (when you erase ink strokes and the extra size can decrease based on the position of the ink strokes until you get back to the original size).
I'm able to increase the InkCanvas width and height, but can't decrease when erasing ink strokes.
Here is a MainPage.xaml code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Heading"
FontSize="36"
FontWeight="Bold"
Margin="10"
Grid.Column="0"
Grid.Row="0"/>
<Grid BorderBrush="Red"
BorderThickness="2"
Margin="10"
Grid.Column="0"
Grid.Row="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
HorizontalScrollMode="Enabled"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Enabled" >
<Grid BorderBrush="Blue"
BorderThickness="2"
Margin="1">
<InkCanvas Name="inkCanvas"/>
</Grid>
</ScrollViewer>
</Grid>
And the MainPage.cs code:
public MainPage()
{
this.InitializeComponent();
nkCanvas.InkPresenter.StrokeInput.StrokeEnded += adjustInkCanvasSize;
}
private async void adjustInkCanvasSize(InkStrokeInput sender, PointerEventArgs args)
{
await Task.Delay(100);
var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
if (XBound > inkCanvas.ActualHeight - 200)
inkCanvas.Height = XBound + 200;
var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
if (YBound > inkCanvas.ActualWidth - 200)
inkCanvas.Width = YBound + 200;
}
The c# code also came from another stackoverflow solution, but not able to figure out the "decrease" part.
Any help would be much appreciated. Thanks
If you want the InkCanvas control to shrink when you erase ink strokes and the extra size can decrease based on the position of the ink strokes until the original size, you need to add the InkPresenter.StrokesErased event to manage the size of the InkCanvas control. For example:
Here is a MainPage.xaml code( To facilitate testing, I added the mouse support):
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Heading"
FontSize="36"
FontWeight="Bold"
Margin="10"
Grid.Column="0"
Grid.Row="0"/>
<Grid BorderBrush="Red"
BorderThickness="2"
Margin="10"
Grid.Column="0"
Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<InkToolbar x:Name="inkToolbar" VerticalAlignment="Top" Margin="10,0,10,0"
TargetInkCanvas="{x:Bind inkCanvas}" Grid.Row="0"/>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
HorizontalScrollMode="Enabled" Grid.Row="1"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Enabled" >
<Grid BorderBrush="Blue"
BorderThickness="2"
Margin="1">
<InkCanvas Name="inkCanvas" />
</Grid>
</ScrollViewer>
</Grid>
</Grid>
And the MainPage.cs code:
public sealed partial class MainPage : Page
{
private double originalX; //The original size
private double originalY;
private double maxX=0.0;
private double maxY=0.0;
private bool flag = true;
public MainPage()
{
this.InitializeComponent();
inkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch |
CoreInputDeviceTypes.Pen;
inkCanvas.InkPresenter.StrokeInput.StrokeEnded += adjustInkCanvasSize;
inkCanvas.InkPresenter.StrokesErased += InkPresenter_StrokesErased;
}
private async void InkPresenter_StrokesErased(InkPresenter sender, InkStrokesErasedEventArgs args)
{
await Task.Delay(100);
//The coordinate of the lower right corner of the erased ink stoke
var erasedInkX= args.Strokes.ElementAt(0).BoundingRect.Bottom;
var erasedInkY = args.Strokes.ElementAt(0).BoundingRect.Right;
var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
if (erasedInkX >=maxX&&XBound < inkCanvas.ActualHeight + 100)
{
if (XBound - 100 > originalX)
inkCanvas.Height = XBound - 100;
else
inkCanvas.Height = originalX; //The size of InkCanvas shrinks to the original size.
maxX = inkCanvas.Height;
}
var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
if (erasedInkY>=maxY&&YBound < inkCanvas.ActualWidth + 100)
{
if (YBound - 100 > originalY)
{
inkCanvas.Width = YBound - 100;
}
else
inkCanvas.Width = originalY;
maxY = inkCanvas.Width;
}
}
private async void adjustInkCanvasSize(InkStrokeInput sender, PointerEventArgs args)
{
await Task.Delay(100);
if(flag)
{
flag = false;
originalX = inkCanvas.ActualHeight; //Get the original size
originalY = inkCanvas.ActualWidth;
}
var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
if (XBound > maxX)
maxX = XBound; //maxX and maxY always hold the maximum size of StrokeContainer
if (XBound > inkCanvas.ActualHeight - 200)
inkCanvas.Height = XBound + 200;
var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
if (YBound > maxY)
maxY = YBound;
if (YBound > inkCanvas.ActualWidth - 200)
inkCanvas.Width = YBound + 200;
}
}
I am trying to create a menu page where I need to keep a button on screen even if a scroll, like button stops at the edge of the screen, and I have this layout in XML but I needed it in code behind to add some frame dynamic. This is what I made but it's not show up the same. Any suggestions please?
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.Margin>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,20,0,0" />
</OnPlatform>
</Grid.Margin>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="FIXED HEADER DEMO" Margin="12" Grid.Row="0" FontSize="14" />
<Grid x:Name="ContentGrid" RowSpacing="0" ColumnSpacing="0" Grid.Row="1">
<ScrollView x:Name="TheScroll">
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition x:Name="ImageRow" Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image x:Name="BearImage" Source="bear.jpg"
Aspect="AspectFill"
Grid.Row="0" />
<Label LineBreakMode="WordWrap"
Margin="12,5,12,5"
Grid.Row="1">
Text="abc"
</Label>
</Grid>
</ScrollView>
<Label x:Name="TitleText"
Text="Bear found in the wild!"
TextColor="White"
BackgroundColor="#FF264778"
HeightRequest="40"
VerticalOptions="Start" VerticalTextAlignment="Center"
HorizontalTextAlignment="Center" />
</Grid>
</Grid>
My code behind
public void PageConstructor()
{
Grid thirdG = new Grid
{
RowDefinitions =
{
new RowDefinition { Height = new GridLength(1,GridUnitType.Auto) },
new RowDefinition { Height = new GridLength(1,GridUnitType.Star) },
},
};
var image1 = new Image
{
Source = "bear.jpg",
};
var labeltext = new Label
{
LineBreakMode = LineBreakMode.WordWrap,
Text = msg + msg2 + msg3,
};
thirdG.Children.Add(image1, 0, 0);
thirdG.Children.Add(labeltext, 0, 1);
Grid secondG = new Grid
{
};
SecondTitle= new Label { Text = "Second title text", TextColor = Color.Black };
scrollV = new ScrollView { Content = thirdG };
secondG.Children.Add(SecondTitle);
secondG.Children.AddVertical(scrollV);
Grid firstG = new Grid
{
RowDefinitions =
{
new RowDefinition { Height = new GridLength(1,GridUnitType.Auto) },
new RowDefinition { Height = new GridLength(1,GridUnitType.Star) },
},
};
firstG.Children.Add(new Label { Text = "Title" }, 0, 0);
firstG.Children.Add(secondG, 0, 1);
Content = firstG;
}
According to your code, I find you use ScrollView in Grid, it will be covered by label TitleText, so I suggest you can put scrollview outside the grid
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Grid.Row="0"
Margin="12"
FontSize="14"
Text="FIXED HEADER DEMO" />
<ScrollView Grid.Row="1">
<Grid x:Name="ContentGrid">
<Grid.RowDefinitions>
<RowDefinition x:Name="ImageRow" Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image
x:Name="BearImage"
Grid.Row="0"
HeightRequest="50"
Source="a11.jpg"
WidthRequest="50" />
<Label
Grid.Row="1"
Margin="12,5,12,5"
LineBreakMode="WordWrap">
Text="abc"
</Label>
<Label
x:Name="TitleText"
BackgroundColor="#FF264778"
HeightRequest="40"
HorizontalTextAlignment="Center"
Text="Bear found in the wild!"
TextColor="White"
VerticalOptions="Start"
VerticalTextAlignment="Center" />
</Grid>
</ScrollView>
</Grid>
Same effect in code behind:
public Page3()
{
InitializeComponent();
var image1 = new Image
{
Source = "a11.jpg",WidthRequest=70,HeightRequest=70
};
var label1 = new Label
{
Text = "abc"
};
var label2 = new Label
{
Text = "Bear found in the wild!",HeightRequest=20,VerticalTextAlignment=TextAlignment.Center,HorizontalTextAlignment=TextAlignment.Center
};
Grid secondG = new Grid
{
RowDefinitions =
{
new RowDefinition { Height = new GridLength(1,GridUnitType.Auto) },
new RowDefinition { Height = new GridLength(1,GridUnitType.Star) },
},
};
var scrollV = new ScrollView { Content = secondG };
secondG.Children.Add(image1,0,0);
secondG.Children.Add(label1,0,1);
secondG.Children.Add(label2);
Grid firstG = new Grid
{
RowDefinitions =
{
new RowDefinition { Height = new GridLength(1,GridUnitType.Auto) },
new RowDefinition { Height = new GridLength(1,GridUnitType.Star) },
},
};
var labeltext = new Label
{
LineBreakMode = LineBreakMode.WordWrap,FontSize=14,
Text = "FIXED HEADER DEMO"
};
firstG.Children.Add(labeltext, 0, 0);
firstG.Children.Add(scrollV, 0, 1);
Content = firstG;
}
}
Desired Result :
I have a list of objects that contains the Title of every section in the menu and in this list I have the list of images and other information
I've been strugeling on how to display them properly
my xaml :
<ContentPage.Content>
<TableView Intent="Form">
<TableRoot>
<TableSection Title="Getting Started">
<ViewCell>
<Grid VerticalOptions="FillAndExpand" Padding = "20, 0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" ></RowDefinition>
<RowDefinition Height="Auto" ></RowDefinition>
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" x:Name="Titre" Orientation="Horizontal">
</StackLayout>
<ScrollView Grid.Row="1">
<StackLayout
Padding="0"
x:Name="Image">
</StackLayout>
</ScrollView>
</Grid>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
</ContentPage.Content>
The C# Method :
private void PopulateProductsLists(List<PlanDefinition> listArticles)
{
for (var i = 0; i < listArticles.Count; i++)
{
//Display Title
Titre.Children.Add((new Label { Text = listArticles[i].Name, Style = Device.Styles.TitleStyle, FontAttributes = FontAttributes.Bold, TextColor = Color.White }));
//Display Images from listArticles[i].ArticlesAvailable
for (int j= 0; j < listArticles[i].ArticlesAvailable.Count; j++)
{
listArticles[i].ArticlesAvailable[j].ImageProduit = "https://fit-plans.com/" + listArticles[i].ArticlesAvailable[j].UrlSmallImage;
Image image = new Image();
image.Source = ImageSource.FromUri(new Uri(listArticles[i].ArticlesAvailable[j].ImageProduit));
Image.Children.Add(image);
}
What I am droing wrong?
First of all here were my mistakes :
1- Not using a scrollable view
2- Using different stack layouts
The remedy to my issue :
<!----Scrollable view MUST be used otherwide data simply won't appear --->
<ScrollView
Grid.Column="0"
Grid.Row="1">
<Grid
RowSpacing="3"
x:Name="MyGrid"
ClassId="myGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackLayout VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
x:Name="ProduitsLayout">
<!----Products will be displayed here --->
</StackLayout>
</Grid>
</ScrollView>
And in the code behind :
private void PopulateProductsLists(List<PlanDefinition> listArticles)
{
int labelIndex = 0;
int count = 0;
for (var i = 0; i < listArticles.Count; i++)
{
//Calling a view to display data
item = new PlanOrderTemplate();
var lastHeight = "100";
var y = 0;
int column = 1;
var productTapGestureRecognizer = new TapGestureRecognizer();
//Add label in the stack layout
ProduitsLayout.Children.Add((new Label
{
Text = listArticles[i].Name,
Style = Device.Styles.TitleStyle,
FontAttributes = FontAttributes.Bold,
TextColor = Color.Black
}));
for (int j = 0; j < listArticles[i].ArticlesAvailable.Count; j++)
{
productTapGestureRecognizer.Tapped += OnProductTapped;
item = new PlanOrderTemplate();
listArticles[i].ArticlesAvailable[j].ThumbnailHeight = lastHeight;
//Applying binding to the view in order to display data
item.BindingContext = listArticles[i].ArticlesAvailable[j];
item.GestureRecognizers.Add(productTapGestureRecognizer);
//This is mandatory you need to call the add the view page to the stack layout
ProduitsLayout.Children.Add(item);
}
}
}
Now as for the view page I'm talking about : ProduitsLayout.xaml
Configure the image I want to load with a stepper
<StackLayout Orientation="Vertical"
Spacing="1">
<ffimageloading:CachedImage
FadeAnimationEnabled="true"
Source="{Binding ImageProduit}"
HeightRequest="{Binding ThumbnailHeight}"
Aspect="AspectFill"/>
<Label x:Name="lbldisp" Text="1" VerticalOptions="Center" HorizontalOptions="Center"></Label>
<Stepper Minimum="0" Maximum="10" Increment="1" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" ValueChanged="OnValueChanged" />
</StackLayout>
How to make animation stay within the canvas at bigger sizes when the user clicks around the edge of the canvas? Currently, if sizes are too big and if user clicks near the edge of the canvas, the ellipse will grow outside of the canvas to cover the buttons. I need the animation to stay within the canvas to make it look like a slice of pizza essentially.
Should look like this:
Size 50 where user clicks near top left of canvas
Currently looks like this:
Size 50 where user clicks near top left of canvas
Xaml:
<Window.Resources>
<Storyboard x:Key="anim">
<DoubleAnimation
Storyboard.TargetName="myCircle"
Storyboard.TargetProperty="RadiusX"
AutoReverse="True"/>
<DoubleAnimation
Storyboard.TargetName="myCircle"
Storyboard.TargetProperty="RadiusY"
AutoReverse="True"/>
<DoubleAnimation
Storyboard.TargetName="path"
Storyboard.TargetProperty="Opacity"
AutoReverse="True"/>
</Storyboard>
</Window.Resources>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="23"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Margin="0,0,0,1">
<Menu DockPanel.Dock="Top" Height="23">
<MenuItem Header="Main" RenderTransformOrigin="-1.896,0.643" HorizontalAlignment="Left" Width="39" Height="23">
<MenuItem Header="Exit, Esc" Click="MenuItem_Click_Exit"/>
</MenuItem>
</Menu>
</DockPanel>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="1" Name="pane">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" Name="pane2">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="35"/>
<RowDefinition Height="35"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Label Content="Size" Grid.Row="0" Grid.Column="0" Height="25" VerticalAlignment="Stretch"/>
<Label Content="Fill Color" Grid.Row="1" Grid.Column="0" Height="25" VerticalAlignment="Stretch"/>
<Label Content="Stroke Thickness" Grid.Row="2" Grid.Column="0" Height="25" VerticalAlignment="Stretch"/>
<Label Content="Stroke Color" Grid.Row="3" Grid.Column="0" VerticalAlignment="Top" Height="25"/>
<Slider x:Name="Slider_Size" Grid.Row="0" Grid.Column="1" Height="20" Width="45"
Minimum="5" Maximum="50"
AutoToolTipPlacement="BottomRight"
TickFrequency="1"
IsSnapToTickEnabled="True"
PreviewMouseUp="Slider_Size_PreviewMouseUp"/>
<Label Name="tempSize" Content="{Binding Path=Value, ElementName=Slider_Size}" Margin="0,25,0,131" Grid.Row="3" Visibility="Hidden"/>
<ComboBox Name="ComboBox_FillColor" Grid.Row="1" Grid.Column="1" Height="20" Width="45" SelectionChanged="ComboBox_FillColor_Selected"/>
<TextBox Name="textBox" Grid.Row="2" Grid.Column="1" Height="20" Width="45" TextChanged="textBox_TextChanged"/>
<ComboBox Name="ComboBox_StrokeColor" Grid.Row="3" Grid.Column="1" VerticalAlignment="Top" Height="20" Width="45" SelectionChanged="ComboBox_StrokeColor_Selected"/>
</Grid>
<Border Name ="border" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Black" Grid.Column="1" BorderThickness="2">
<Canvas Name="canvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MouseDown="Canvas_MouseDown">
<Path x:Name="path">
<Path.Data>
<EllipseGeometry x:Name="myCircle"/>
</Path.Data>
</Path>
<Canvas.Background>
<SolidColorBrush Color="White" Opacity="0"/>
</Canvas.Background>
</Canvas>
</Border>
</Grid>
</Grid>
C#:
public partial class MainWindow : Window
{
private int size;
private SolidColorBrush fillColor;
private SolidColorBrush strokeColor;
private List<SolidColorBrush> colors;
private int fillIndex;
private int strokeIndex;
private int strokeThickness = 1;
private int fillColorDefault;
private int strokeColorDefault;
private Point? _start = null;
public MainWindow()
{
InitializeComponent();
addColors();
textBox.Text = strokeThickness.ToString();
parse();
}
private void MenuItem_Click_Exit(object sender, RoutedEventArgs e) { Environment.Exit(1); }
private void Window_KeyUp_ESC(object sender, KeyEventArgs e)
{
if (Key.Escape == e.Key)
MenuItem_Click_Exit(sender, e);
}
private void addColors()
{
colors = typeof(Brushes).GetProperties().Select(p => p.GetValue(null, null) as SolidColorBrush).ToList();
int count = 0;
foreach (SolidColorBrush color in colors)
{
ComboBox_FillColor.Items.Add(new Rectangle() { Height = 12, Width = 17.5, Fill = color });
ComboBox_StrokeColor.Items.Add(new Rectangle() { Height = 12, Width = 17.5, Fill = color });
if (color.Color == Colors.Red)
{
fillIndex = count;
fillColor = colors[fillIndex];
ComboBox_FillColor.SelectedIndex = count;
fillColorDefault = count;
}
if (color.Color == Colors.Black)
{
strokeIndex = count;
strokeColor = colors[strokeIndex];
ComboBox_StrokeColor.SelectedIndex = count;
strokeColorDefault = count;
}
count++;
}
}
private void ComboBox_FillColor_Selected(object sender, RoutedEventArgs e) { fillIndex = ComboBox_FillColor.SelectedIndex; fillColor = colors[fillIndex]; }
private void ComboBox_StrokeColor_Selected(object sender, RoutedEventArgs e) { strokeIndex = ComboBox_StrokeColor.SelectedIndex; strokeColor = colors[strokeIndex]; }
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
path.Stroke = strokeColor;
path.StrokeThickness = strokeThickness;
path.Fill = fillColor;
path.HorizontalAlignment = HorizontalAlignment.Stretch;
path.VerticalAlignment = VerticalAlignment.Stretch;
path.Stretch = Stretch.None;
path.SetValue(Grid.ColumnProperty, 1);
_start = Mouse.GetPosition((UIElement)sender);
myCircle.Center = (Point)_start;
var sb = FindResource("anim") as Storyboard;
var x = sb.Children.First() as DoubleAnimation;
x.To = 2 * size;
x.Duration = new Duration(TimeSpan.FromSeconds(0.5));
var y = sb.Children.ElementAt(1) as DoubleAnimation;
y.To = 2 * size;
y.Duration = new Duration(TimeSpan.FromSeconds(0.5));
var z = sb.Children.Last() as DoubleAnimation;
z.From = 0.0;
z.To = 1.0;
z.Duration = new Duration(TimeSpan.FromSeconds(0.5));
sb.Begin(path);
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
//regex where any string of chars besides numbers
Regex pattern = new Regex(#"^([^0-9]*)$", RegexOptions.Compiled);
Match result = pattern.Match(textBox.Text);
if (textBox.Text.ToString() == string.Empty)
return;
else if (result.Success)
{
MessageBox.Show("Invalid character entered. Integer numbers only. Stroke Thickness will be reseted to a default of 1.");
strokeThickness = 1;
textBox.Text = strokeThickness.ToString();
textBox.SelectAll();
}
else
{
int x;
if (int.TryParse(textBox.Text, out x))
strokeThickness = int.Parse(textBox.Text);
}
}
private void Slider_Size_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
parse();
}
private void parse()
{
int x;
if (int.TryParse(tempSize.Content.ToString(), out x))
size = x;
}
}
}
So you don't need the ellipse to stay within the Canvas, but you want to clip away the parts leaving it, right? Just set ClipToBounds (of Canvas) to true (can be done in Xaml).