The layout i want is like this: http://imgur.com/etb9ZKZ
I want the image (illustrated with the color green) to fill the entire layoutcontol. On top of image positioned at the bottom with full width i want a textbox/label to put a title. The title view should have a black semi-transparent background.
This is the best i've got (the code below), but it has a few issues:
#1 - The text doesnt wrap like it is suppose to. It just cuts the sentence, like the rest is going off screen.
#2 - The image doesnt scale to the width of the container.
Label lblTitle = new Label()
{
BackgroundColor = new Color(0, 0, 0, 0.8),
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
};
lblTitle.SetBinding(Label.TextProperty, "headline");
Image imgBanner = new Image()
{
/*
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.End,
Aspect = Aspect.Fill
*/
};
imgBanner.SetBinding(Image.SourceProperty, "ImageUrlSource");
AbsoluteLayout.SetLayoutFlags(lblTitle, AbsoluteLayoutFlags.PositionProportional | AbsoluteLayoutFlags.WidthProportional);
AbsoluteLayout.SetLayoutBounds(lblTitle, new Rectangle(0, 1, 1, AbsoluteLayout.AutoSize));
AbsoluteLayout.SetLayoutFlags(imgBanner, AbsoluteLayoutFlags.SizeProportional);
AbsoluteLayout.SetLayoutBounds(imgBanner, new Rectangle(0, 0, 1, 1));
AbsoluteLayout layout = new AbsoluteLayout()
{
HorizontalOptions = LayoutOptions.Fill,
Children =
{
imgBanner,
lblTitle
}
};
View = layout;
You should use Grid instead.
Label lblTitle = new Label()
{
BackgroundColor = new Color(0, 0, 0, 0.8),
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
};
lblTitle.SetBinding(Label.TextProperty, "headline");
Image imgBanner = new Image()
{
/*
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.End,
Aspect = Aspect.Fill
*/
};
imgBanner.SetBinding(Image.SourceProperty, "ImageUrlSource");
//=========== Addition Start Here ============//
Grid grid = new Grid();
grid.RowDefinitions =
{
new RowDefinition{ Height=new GridLength(200,GridUnitType.Absolute) },
new RowDefinition{ Height=new GridLength(30,GridUnitType.Absolute},
}
grid.Children.Add(imgBanner,0,1,0,2); //two rowspan
// == .Add(imgBanner,column,column+columnspan,row,row+rowspan)
grid.Children.Add(lblTitle,0,1,1,2); //one rowspan
View = grid;
Related
I want to create dynamic grid layout with one row with 2 column and another row with only one column with colspan 2.
And every column may contain on overlay image at top right corner.
For this i tried to add relative layout in grid layout but the issue is image tag in relative layout is not occupying complete width.
code to create relative layout
for (int i = 0; i < temp.Count; i++)
{
var data = temp[i];
var framelyt = new Frame { CornerRadius = 4, IsClippedToBounds = true, HasShadow = false, Padding = 0, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
Image imageStack = new Image { Source = "placeholder_image1", Margin = 0, Aspect = Aspect.Fill, HorizontalOptions = LayoutOptions.FillAndExpand };
Image cmpltimageStack = new Image { Source = "completed_icon", Aspect = Aspect.Fill, HeightRequest = 32, IsVisible=true };
RelativeLayout relativeLayout = new RelativeLayout { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, BackgroundColor = Color.Beige };
framelyt.Content = imageStack;
relativeLayout.Children.Add(framelyt, Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}), Constraint.Constant(0)); relativeLayout.Children.Add(cmpltimageStack,
Constraint.RelativeToParent((parent) =>
{
return parent.Width - 50;
}),
Constraint.Constant(0));
gridStckActivity.Children.Add(relativeLayout, column, row);
if (column == 1)
{
column = 0;
isSingle = true;
row++;
}
else
{
column = 1;
}}
It was working on android device properly but on iOS it was leaving some space on right padding. After adding x,y and width constraint it worked properly on both device.
Here is the revised code.
for (int i = 0; i < temp.Count; i++)
{
var data = temp[i];
var framelyt = new Frame { CornerRadius = 4, IsClippedToBounds = true, HasShadow = false, Padding = 0, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
Image imageStack = new Image { Source = "placeholder_image1", Margin = 0, Aspect = Aspect.Fill, HorizontalOptions = LayoutOptions.FillAndExpand };
Image cmpltimageStack = new Image { Source = "completed_icon", Aspect = Aspect.Fill, HeightRequest = 32, IsVisible=true };
RelativeLayout relativeLayout = new RelativeLayout { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, BackgroundColor = Color.Beige };
framelyt.Content = imageStack;
relativeLayout.Children.Add(framelyt, Constraint.Constant(0), Constraint.Constant(0),Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}));
relativeLayout.Children.Add(cmpltimageStack,
Constraint.RelativeToParent((parent) =>
{
return parent.Width - 50;
}),
Constraint.Constant(0));
gridStckActivity.Children.Add(relativeLayout, column, row);
if (column == 1)
{
column = 0;
isSingle = true;
row++;
}
else
{
column = 1;
} }
I have a grid with only one row with the height of GridLength.Star.
In the first column I have an svg that fills the cell.
In the second column I have a label.
The svg is a square and should take the place to fill it in vertical and horizontal direction but not more.
The label should take the rest of the width.
I tried to set
column1.Width = GridLength.Auto;
column2.Width = GridLength.Star;
but it will always be devided in the middle.
So I got:
svg..........|label........
instead of (what I want):
svg|label..................
Any ideas?
UPDATE
Label label = new Label();
SvgCachedImage svgImage = new SvgCachedImage();
svgImage.HorizontalOptions = LayoutOptions.CenterAndExpand;
svgImage.VerticalOptions = LayoutOptions.CenterAndExpand;
Grid grid = new Grid();
grid.Children.Add( svgImage );
grid.Children.Add( label );
RowDefinition row = new RowDefinition();
ColumnDefinition column1 = new ColumnDefinition();
ColumnDefinition column2 = new ColumnDefinition();
row.Height = GridLength.Star;
grid.RowDefinitions = new RowDefinitionCollection { row1 };
column1.Width = GridLength.Auto;
column2.Width = GridLength.Star;
grid.ColumnDefinitions = new ColumnDefinitionCollection { column1, column2 };
UPDATE 2
Sorry it is no Fill but a CenterAndExpand
I got the answer. I simply need to set the height of the svg to its widthRequest:
svgImage.WidthRequest = svgImage.Height;
column1.Width = GridLength.Auto;
column2.Width = GridLength.Star;
grid.Children.Add( svgImage, 0, 0 );
grid.Children.Add( label, 1, 0 );
Well, its very simple actually the reason behind it is the GridLength.Auto you have there all you need to do is change the Grid column definitions into something like this:
XAML
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/> // svg
<ColumnDefinition Width="4*"/> // label
</Grid.CoulmnDefinitions>
C#
Grid grid= new Grid
{
ColumnDefinitions =
{
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
new RowDefinition { Height = new GridLength(4, GridUnitType.Star) },
}
}
grid.Children.Add(svgImage, 0, 0);
grid.Children.Add(label, 0, 1);
Move:
grid.Children.Add( svgImage );
grid.Children.Add( label );
to after you've set up your row/column definitions, and then change to:
grid.Children.Add(svgImage, 0, 0);
grid.Children.Add(label, 0, 1);
You basically have to tell the grid which row/column to put your elements. By adding them to the grid before initialising the column definitions, the ColumnDefinitions have defaulted to GridLength.Star.
I've tidied up your code. Note that I have changed the Height assignments.
Label label = new Label()
{
Text = "Some text" // Just some placeholder text
};
SvgCachedImage svgImage = new SvgCachedImage()
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Grid grid = new Grid();
// NOTE: use GridLength class to set the Height/Width of rows/columns
RowDefinition row = new RowDefinition()
{
Height = new GridLength(1, GridUnitType.Star)
}
ColumnDefinition column1 = new ColumnDefinition()
{
Width = new GridLength(1, GridUnitType.Auto)
}
ColumnDefinition column2 = new ColumnDefinition()
{
Width = new GridLength(1, GridUnitType.Star)
}
// Use existing instances of the definitions
grid.RowDefinitions.Add(row1);
grid.ColumnDefinitions.Add(column1);
grid.ColumnDefinitions.Add(column2);
grid.Children.Add(svgImage, 0, 0);
grid.Children.Add(label, 1, 0);
As I was typing this out I noticed that you had simply set the Width property to GridLength.Star/Auto. According to the docs, you should be using the GridLength class, not the Enum.
I want to display text in a format in label, but it's displaying an incorrect value.
It's showing the correct value in debug mode. But its displayed wrong on the screen. Ideally, the screen should display total and subtotal as image one.
Code to format string
string paymentFormat = "{0,-25} {1,8}\n";
string paymentMode = "Total"; // Or Subtotal
string paymentAmount = "604.00";
string test = string.Format(paymentFormat, paymentMode, paymentAmount);
Update
public class AlertPopupViewItem : ContentView
{
Label HeaderLabel,MessageLabel;
public Button OKButton, CancelButton;
AbsoluteLayout _overlay;
LoggerService logservice;
public bool ButtonValue = false;
StackLayout CancelStackLayout, OKStackLayout;
string PageSource = string.Empty;
public AlertPopupViewItem()
{
logservice = new LoggerService();
logservice.WriteData(Constants.DEBUG_LOGGING, "Alert Message Popup ctor.. Start");
_overlay = new AbsoluteLayout
{
BackgroundColor = Color.Black.MultiplyAlpha(0.5),
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
};
Grid mainGrid = new Grid
{
HeightRequest = 40,
BackgroundColor = Color.White,
Padding = 20,
RowDefinitions =
{
new RowDefinition { Height = new GridLength(15, GridUnitType.Star) },//0 Title
new RowDefinition { Height = new GridLength(3, GridUnitType.Star) },//1 Line
new RowDefinition { Height = new GridLength(80, GridUnitType.Star) },//2 Message
new RowDefinition { Height = new GridLength(12, GridUnitType.Star) },//3 OK-Cancel
}
};
HeaderLabel = new Label
{
FontAttributes = FontAttributes.Bold,
FontSize = 22,
TextColor = Color.Black,
HorizontalTextAlignment= TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions =LayoutOptions.CenterAndExpand
};
BoxView divider = new BoxView
{
HeightRequest = 1,
Color = Color.Gray,
VerticalOptions = LayoutOptions.End,
};
MessageLabel = new Label
{
FontAttributes = FontAttributes.None,
FontSize = 13,
HorizontalTextAlignment = TextAlignment.Start,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
TextColor = Color.Black
};
ScrollView scroll = new ScrollView()
{
Orientation = ScrollOrientation.Vertical
};
scroll.Content = MessageLabel;
Grid ButtonGrid = new Grid
{
HeightRequest = 35,
ColumnDefinitions =
{
new ColumnDefinition {Width=new GridLength(58,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(20,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(2,GridUnitType.Star) },
new ColumnDefinition {Width=new GridLength(20,GridUnitType.Star) }
}
};
CancelStackLayout = new StackLayout
{
Padding = new Thickness(-6, -6, -6, -6),
//VerticalOptions = LayoutOptions.Center,
BackgroundColor = Color.FromHex("#ff9500")
};
CancelButton = new Button
{
TextColor = Color.White,
FontSize = 15,
BorderRadius = 0,
Text = Localizer.Localize("CancelSmall"),
BackgroundColor = Color.FromHex("#01458e"),
HorizontalOptions =LayoutOptions.FillAndExpand,
VerticalOptions=LayoutOptions.FillAndExpand,
BorderColor = Color.Transparent
};
CancelButton.Clicked += CancelButtonClicked;
CancelStackLayout.Children.Add(CancelButton);
ButtonGrid.Children.Add(CancelStackLayout, 1, 0);
OKStackLayout = new StackLayout
{
Padding = new Thickness(-6, -6, -6, -6),
BackgroundColor = Color.FromHex("#ff9500")
};
OKButton = new Button
{
TextColor = Color.White,
FontSize = 15,
BorderRadius = 0,
Text = Localizer.Localize("OK"),
BackgroundColor = Color.FromHex("#01458e"),
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
BorderColor = Color.Transparent
};
OKButton.Clicked += OKButtonClicked;
OKStackLayout.Children.Add(OKButton);
ButtonGrid.Children.Add(OKStackLayout, 3, 0);
mainGrid.Children.Add(HeaderLabel, 0, 0);
mainGrid.Children.Add(divider, 0, 1);
mainGrid.Children.Add(scroll, 0, 2);
mainGrid.Children.Add(ButtonGrid, 0, 3);
AbsoluteLayout.SetLayoutFlags(mainGrid, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(mainGrid, Findlayoutbounds(new Rectangle(0.20, 0.25, 0.5, 0.50)));
_overlay.Children.Add(mainGrid);
Content = _overlay;
logservice.WriteData(Constants.DEBUG_LOGGING, "Alert Message Popup ctor.. End");
}
// ThreadHandle thread = new ThreadHandle();
private void CancelButtonClicked(object sender, EventArgs e)
{
ButtonValue = false;
this.IsVisible = false;
// thread.WorkMethod();
}
private void OKButtonClicked(object sender, EventArgs e)
{
ButtonValue = true;
if (PageSource == "StarterPage") ;
//MessagingCenter.Send(this, "ModifyValBooleanForAlert");
this.IsVisible = false;
// thread.WorkMethod();
}
Rectangle Findlayoutbounds(Rectangle fractionalRect)
{
if (fractionalRect.Width - 1 == 0)
fractionalRect.Width = 0.99;
if (fractionalRect.Height - 1 == 0)
fractionalRect.Height = 0.99;
Rectangle layoutbounds = new Rectangle
{
X = fractionalRect.X / (1 - fractionalRect.Width),
Y = fractionalRect.Y / (1 - fractionalRect.Height),
Width = fractionalRect.Width,
Height = fractionalRect.Height
};
return layoutbounds;
}
public void DisplayAlertPopup(string alertBoxTitle, string alertBoxContent,bool CancelDisplay)
{
HeaderLabel.IsVisible = false;
CancelStackLayout.IsVisible = CancelDisplay;
CancelButton.IsVisible = CancelDisplay;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
OKButton.Text = Localizer.Localize("OK");
CancelButton.Text = Localizer.Localize("CancelSmall");
HeaderLabel.IsVisible = true;
}
public void DisplayAlertPopup(string alertBoxTitle, string alertBoxContent, string ButtonText)
{
CancelStackLayout.IsVisible = false;
CancelButton.IsVisible = false;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
OKButton.Text = ButtonText;
}
public void DisplayAlertConditionalPopup(string alertBoxTitle, string alertBoxContent, bool CancelDisplay)
{
CancelStackLayout.IsVisible = CancelDisplay;
CancelButton.IsVisible = CancelDisplay;
HeaderLabel.Text = alertBoxTitle;
MessageLabel.Text = alertBoxContent;
this.IsVisible = true;
}
public void SetButtonText(string OKText, string CancelText)
{
if (OKText != null)
OKButton.Text = OKText;
if (CancelText != null)
CancelButton.Text = CancelText;
}
}
I get the formatted string from some other class and call the DisplayAlertPopup method. MessageLabel is the label for which I am setting this value.
Update2:
As suggested in answer, I have tried the below code to set the font for Android. But its also not displying the text in the required format.
MessageLabel = new Label
{
FontAttributes = FontAttributes.None,
FontSize = 13,
HorizontalTextAlignment = TextAlignment.Start,
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
TextColor = Color.Black,
FontFamily = "Droid Sans Mono"
};
You will need to use a fixed-width font. There is unfortunately none that is built-in across all platforms, but each platform has its own:
iOS - Courier New
Android - Droid Sans Mono
UWP - Consolas
If no built-in font suits you or you want to have the same experience on all platforms, you can also use custom fonts in Xamarin.Forms. This requires you to find a fixed-width font you like on a service like Google Fonts. Then you can follow the tutorial here on Xamarin Help, that describes how to include the TTF file in each platform and use it from XAML.
The short summary is:
Add the font to each platform project with appropriate build action (UWP - Content, iOS - Bundle Resource, Android - Android Asset)
Use the OnPlatform syntax to set the font (ideally creating a static resource so that it can be reused):
Resource:
<OnPlatform x:TypeArguments="x:String" x:Key="MyFontFamily">
<On Platform="Android" Value="MyFont.ttf#Open Sans" />
<On Platform="UWP" Value="/Assets/MyFont.ttf#Open Sans" />
<On Platform="iOS" Value="MyFont" />
</OnPlatform>
And use like this:
<Label FontFamily="{StaticResource MyFontFamily}" />
I have a StackLayout holding some elements for a custom cell in a ListView. The problem I am running in to is that my images are not landing on full pixel boundaries. This is causing the straight lines in my graphics to become blurry as they are not landing on pixel boundaries. Is there a way for me to easily prevent this behavior, perhaps in a custom renderer?
public InputEditCell()
{
image = new Image { HorizontalOptions = LayoutOptions.Start };
image.SetBinding(Image.SourceProperty, new Binding("Image.ImageNameSelect"));
image.BindingContext = _tempInputViewModel;
var tappedImageGesture = new TapGestureRecognizer
{
Command = new Command(OnImageTapped),
CommandParameter = image
};
image.GestureRecognizers.Add(tappedImageGesture);
nameEntry = new Entry()
{
TextColor = Color.FromHex("E60006"),
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Entry)),
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.FillAndExpand
};
nameEntry.SetBinding(Entry.TextProperty, "Name");
nameEntry.BindingContext = _tempInputViewModel;
var acceptImage = new Image
{
Source = ResourceHandler.GetAcceptImage(),
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End,
};
var tappedAcceptGesture = new TapGestureRecognizer
{
Command = new Command(OnAcceptTapped),
CommandParameter = acceptImage
};
acceptImage.GestureRecognizers.Add(tappedAcceptGesture);
var cancelImage = new Image
{
Source = ResourceHandler.GetCancelImage(),
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End,
};
var tappedCancelGesture = new TapGestureRecognizer
{
Command = new Command(OnCancelTapped),
CommandParameter = cancelImage
};
cancelImage.GestureRecognizers.Add(tappedCancelGesture);
var viewLayout = new StackLayout {
Orientation = StackOrientation.Horizontal,
Children = { image, nameEntry, acceptImage, cancelImage },
Padding = new Thickness(10, 10, 10 ,10)
};
View = viewLayout;
View.GestureRecognizers.Clear();
View.GestureRecognizers.Add(new TapGestureRecognizer());
}
I have a StackLayout coded like this:
StackLayout mainStackLayOut = new StackLayout{
BackgroundColor = Color.Blue,
//VerticalOptions = LayoutOptions.FillAndExpand,
//WidthRequest = width,
HorizontalOptions = LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Vertical
};
But I want the StackLayout to fill all the screen width and height, also I have tree buttons added like this:
StackLayout buttonsStackLayOut = new StackLayout
{
BackgroundColor = Color.White,
//VerticalOptions = LayoutOptions.Fill,
HorizontalOptions = LayoutOptions.Fill,
Orientation = StackOrientation.Horizontal,
Spacing = 0
};
mainStackLayOut.Children.Add(buttonsStackLayOut);
Image doctorImage = new Image
{
WidthRequest = width / 3,
HeightRequest = 50,
BackgroundColor = Color.Gray,
Source = ImageSource.FromFile ("about.png")
};
buttonsStackLayOut.Children.Add(doctorImage);
How can I fill all the screensize?
In the most simple form I have managed to achieve what you require.
I set the content of the screen to the main stack layout.
var mainStackLayout = new StackLayout { BackgroundColor = Color.Blue};
var buttonsStackLayout = new StackLayout { BackgroundColor = Color.White, Orientation = StackOrientation.Horizontal , Spacing = 0 };
Image about = new Image { HeightRequest = 50, Source = ImageSource.FromFile("about.jpg") };
Image twitter = new Image { HeightRequest = 50, Source = ImageSource.FromFile("twitter.jpg") };
Image refresh = new Image { HeightRequest = 50, Source = ImageSource.FromFile("refresh.jpg") };
buttonsStackLayout.Children.Add(about);
buttonsStackLayout.Children.Add(twitter);
buttonsStackLayout.Children.Add(refresh);
mainStackLayout.Children.Add(buttonsStackLayout);
this.Content = mainStackLayout;