Am trying to justify text in Label Xamarin Forms but couldnt , how to justify the text (not styling justify only) same like a picture without using webview
I have attached my code but its justify left only
string strText="MY LONG TEXT IS GOING HERE";
var lblMSG = new Label {TextColor = Color.Black };
lblMSG.Text=strText;
lblMSG.LineBreakMode = LineBreakMode.WordWrap;
lblMSG.HorizontalOptions = LayoutOptions.Fill;
lblMSG.HorizontalTextAlignment = TextAlignment.Start;
lblMSG.VerticalTextAlignment = TextAlignment.Center;
StackLayout stk= new StackLayout { Children = { lblMSG}, BackgroundColor = Color.White ,HorizontalOptions =LayoutOptions.FillAndExpand }
Instead of using a label. I used a HtmlWebViewSource.
An example is below:
XAML:
<StackLayout x:Name="webViewLayout"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<!-- view codebehind for WebView for overview text -->
</StackLayout>
Code Behind of XAML (viewModel.Model.Content = strText in your case):
var browser = new WebView();
browser.HorizontalOptions = LayoutOptions.FillAndExpand;
browser.VerticalOptions = LayoutOptions.FillAndExpand;
var source = new HtmlWebViewSource();
var text = "<html>" +
"<body style=\"text-align: justify;\">" +
String.Format("<p>{0}</p>", viewModel.Model.Content) +
"</body>" +
"</html>";
source.Html = text ;
browser.Source = source;
webViewLayout.Children.Add(browser);
If the question is about stretching the multi-line text to full width (text must touch left and right sides of the block), you can use platform renderer. See this reply.
Related
I have the problem that the content of the expander does not start at the left, how can I solve this?
As you can see on the picture, the contents of my expander are not shown to the far left. I have tried many settings, unfortunately I do not come to the solution. The expander itself also seems to have an edge opposite the stackpanel, which I also want to avoid.
Above the expander you can see a grid, which contains a text block with content. This grid has the right mass within the higher-level stack panel.
Expander exp = new Expander
{
Header = "TestExpander",
Width = spStackPanel.Width,
ExpandDirection = ExpandDirection.Down,
IsExpanded = true,
BorderBrush = Brushes.Yellow,
BorderThickness = new Thickness(1),
HorizontalAlignment = HorizontalAlignment.Left,
HorizontalContentAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
VerticalContentAlignment = VerticalAlignment.Top,
};
TextBox tx = new TextBox
{
Text = "testText"
};
exp.Content = tx;
spStackPanel.Children.Add(exp);
I can't comment so apologies for the somewhat vague answer, but it might help to share the styling and XAML used to create your screenshot. By default that isn't how an Expander looks, so my guess is that something in your styling or one of the higher level controls (e.g. StackPanel or Grid) is affecting the layout of the Expander.
Example being possibly a keyless style for TextBox that applies padding and/or horizontal alignment, which would then affect the content you're adding by creating a new TextBox in your snippet to give it that odd alignment.
I have written a test here, directly in a .cs file WITHOUT XML:
buttonGrid = new Grid();
buttonGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50) });
buttonGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50) });
Expander exp = new Expander()
{
Header = "Test Expander",
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(0),
IsExpanded = true
};
TextBlock label = new TextBlock()
{
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(0),
Text = "Test Text"
};
exp.Content = label;
Grid.SetRow(exp, 0);
buttonGrid.Children.Add(exp);
TextBlock text = new TextBlock()
{
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(0),
Text = "Test Text",
Foreground = Brushes.White
};
Grid.SetRow(text, 1);
buttonGrid.Children.Add(text);
I know that an expander doesn't usually look like this, so I ask my question ;-)
maybe someone has me a tip to look for.
I have made this in code-behind :
var finishedText = new Run("Some text");
var finishedUrl = new Run("http://somewhere");
var hyperlink = new Hyperlink(finishedUrl) { NavigateUri = new Uri("http://somewhere") };
hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
FinishedTextBlock.Inlines.Clear();
FinishedTextBlock.Inlines.Add(finishedText);
FinishedTextBlock.Inlines.Add(hyperlink);
FinishedTextBlock.Inlines.Add(Environment.NewLine);
FinishedTextBlock.Inlines.Add(finishedUrl);
In XAML :
<TextBlock Grid.Row="0"
x:Name="FinishedTextBlock"
Width="Auto"
Margin="10 10 0 0">
</TextBlock>
The text is not clickable.
What am I doing wrong?
The text is not clickable.
That is because your Hyperlink text is not even shown. You see the last Run that you have added to the Inlines collection, not the hyperlink itself.
You add the same Run named finishedUrl to your Hyperlink and its containing TextBlock, but you have to create a separate Run instance for the Hyperlink.
var finishedText = new Run("Some text");
var finishedUrl = "http://somewhere";
var finishedUrlRun = new Run(finishedUrl);
var hyperlink = new Hyperlink(finishedUrlRun) { NavigateUri = new Uri("http://somewhere") };
hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
FinishedTextBlock.Inlines.Clear();
FinishedTextBlock.Inlines.Add(finishedText);
FinishedTextBlock.Inlines.Add(hyperlink);
FinishedTextBlock.Inlines.Add(Environment.NewLine);
var finishedUrlRun1 = new Run(finishedUrl);
FinishedTextBlock.Inlines.Add(finishedUrlRun1);
Even better, just do not add the last Run, as it is redundant, and replace the NewLine with a LineBreak to get the same layout as in your image but with a link.
FinishedTextBlock.Inlines.Clear();
FinishedTextBlock.Inlines.Add(finishedText);
FinishedTextBlock.Inlines.Add(new LineBreak());
FinishedTextBlock.Inlines.Add(hyperlink);
Unless your hyperlink is inside a webview then nothing will happen when you click on a hyperlink.
You need to handle the RequestNavigate event and do something before you'll see a web browser appear with a page in it.
If this was a wpf page inside a frame, or navigationwindow then it would also navigate without code.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.documents.hyperlink?view=netcore-3.1
Remarks
Hyperlink implements the NavigateUri property that you set
with the Uri of the content that should be navigated to when the
Hyperlink is clicked. Hyperlink navigation can only occur, however, if
either the direct or indirect parent of a Hyperlink is a navigation
host, including NavigationWindow, Frame, or any browser that can host
XBAPs (which includes Internet Explorer 6 and later versions, and
Firefox 2.0+). For more information, see the Navigation Hosts topic in
Navigation Overview.
As it is, you need an event handler.
I'm not clear whether you intend the url to appear or a string. If you want a different string then this should work:
TextBlock tb = new TextBlock();
tb.Inlines.Add(new Run {Text="Some text" } );
tb.Inlines.Add(new LineBreak());
Run linkRun = new Run("Link To Google");
Hyperlink hyper = new Hyperlink(linkRun) { NavigateUri = new Uri(#"http://www.google.com") };
hyper.RequestNavigate += (o, e) => Process.Start(new ProcessStartInfo(e.Uri.ToString()){ UseShellExecute = true });
tb.Inlines.Add(hyper);
If you want the url to appear rather than some other string then:
TextBlock tb = new TextBlock();
tb.Inlines.Add(new Run { Text = "Some text" });
tb.Inlines.Add(new LineBreak());
string url = #"http://www.google.com";
Run linkRun = new Run(url);
Hyperlink hyper = new Hyperlink(linkRun){ NavigateUri = new Uri(url) };
hyper.RequestNavigate += (o, e) => Process.Start(new ProcessStartInfo(e.Uri.ToString()) { UseShellExecute = true });
tb.Inlines.Add(hyper);
sp.Children.Add(tb);
Note
One the process start, you will often get an error on win 10 machines without that useshellexecute in the process startinfo.
In older OS ( and you would see in old SO answers ) you used to be able to just process start with a URL and it would work with the default browser.
There is a linebreak inline which is intended to add a linebreak between a series of runs in a textblock.
In XAML, it needs to be like this:
<TextBlock Grid.Row="0"
x:Name="FinishedTextBlock"
Width="Auto"
Margin="10 10 0 0">
<Run Text="Some text" />
<LineBreak/>
<Hyperlink>http://somewhere</Hyperlink>
</TextBlock>
The hyperlink in your code does not content anything. The hyperlink constructor parameter
[finishedUrl] did not initialized the hyperlink to contain the string "http://somewhere".
You can change your code something like below:
var finishedText = new Run("Some text");
var finishedUrl = new Run("http://somewhere");
var hyperlink = new Hyperlink() { NavigateUri = new Uri("http://somewhere") };
hyperlink.Inlines.Add(finishedUrl.Text);
hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
FinishedTextBlock.Inlines.Clear();
FinishedTextBlock.Inlines.Add(finishedText);
FinishedTextBlock.Inlines.Add(Environment.NewLine);
FinishedTextBlock.Inlines.Add(hyperlink);
I am trying to display almost 300 lines on one page using label control, but i only showing first top lines, i am using the following code, how i can display all lines, is label the appropriate controls?
Label testt = new Label { Text = MainPage.part1, VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.CenterAndExpand, FontAttributes = FontAttributes.Bold, FontSize = 24, TextColor = Color.White };
StackLayout stacklayout = new StackLayout
{
Children = {
TitleOfBook,
testt
}
};
ScrollView scroll = new ScrollView
{
Content = stacklayout
,VerticalOptions=LayoutOptions.FillAndExpand,
HorizontalOptions=LayoutOptions.FillAndExpand
};
Content = scroll;
I came across a similar problem a while back. I believe the issue was that the label has a limit of 100 lines (or something along those lines). You can create a custom label and set the line limit to be higher.
Here is a link to the Xamarin Forum topic which may be able to give you an idea of implementation.
I want to display data that is on the List and also for the email. I have to Vice President and I want open link the of their email respectively to open to an external email platform. However, the code can't seems to work properly it opens only one email for the Vice President and the whole of the label containing it seems to react to it.
This is the screen shot of it.
My Xmal code
<Label Text="Vice-President:" FontSize="18" FontAttributes="Bold" XAlign="Center" TextColor="Black"/>
<StackLayout x:Name="vpDetails">
</StackLayout>
My C# Code
foreach (var item in leaderDetail)
{
Boolean IsPresident = item.IsPresident;
if (IsPresident == true)
{
lbPresidentName.Text = item.Name;
btnPresidentEmail.Text = item.Email;
var tgrPresident = new TapGestureRecognizer();
tgrPresident.Tapped += (s, e) => Device.OpenUri(new Uri("mailto:" + item.Email));
btnPresidentEmail.GestureRecognizers.Add(tgrPresident);
}
else
{
vpDetails.Children.Add(new Label { Text = item.Name ,FontSize=14, HorizontalOptions = LayoutOptions.Center});
vpDetails.Children.Add(new Label { Text = item.Email, FontSize=14, HorizontalOptions = LayoutOptions.Center, x:name="lbvPresident1Email"});
//lbvPresident1Name.Text = item.Name;
//lbvPresident1Email.Text = item.Email;
var tgrVPEmail = new TapGestureRecognizer();
tgrVPEmail.Tapped += (s, e) => Device.OpenUri(new Uri("mailto:" + item.Email));
lbvPresident1Email.GestureRecognizers.Add(tgrVPEmail);
}
}
This is because for multiple vice-presidents, you are just appending the text to the one label. This means that you first add one vice-president, and his Gesture recognizer with his e-mail and the append the text for the other and register another gesture recognizer. Then the tap gesture is recognized for the first one.
Basically what happens after the whole code runs is that the label lbvPresident1Name contains all vice-prezident names and e-mails and has multiple GestureRecognizers (one for each vice-prezident).
To overcome this issue, you should for example create a list of vice-presidents and add each vice-president as an item or add a container and create the labels for each of them on the fly.
To create a ListView in Xamarin.Forms see the documentation - https://developer.xamarin.com/samples/xamarin-forms/WorkingWithListview/
To create a container to which you can add items on the fly from the code, StackLayout component will be the best choice in your scenario. You will just put a StackLayout in place of the current label and then create Labels in the foreach loop and put them in the StackLayout using the Children.Add method.
To solve this problem you have to use the StackLayout as the container. Create a var of a Label and add into the foreach loop.
DetailedClub.xaml
<StackLayout x:Name="vpDetails"></StackLayout>
DetailedClub.xaml.cs
foreach (var item in leaderDetail)
{
//Create a new label for the Email
var VpEmail = new Label { Text = item.Email, FontSize = 14, HorizontalOptions = LayoutOptions.Center };
vpDetails.Children.Add(new Label { Text = item.Name ,FontSize=14, HorizontalOptions = LayoutOptions.Center});
vpDetails.Children.Add(VpEmail);
var tgrVPEmail = new TapGestureRecognizer();
tgrVPEmail.Tapped += (s, e) => Device.OpenUri(new Uri("mailto:" + item.Email));
VpEmail.GestureRecognizers.Add(tgrVPEmail);
}
I created some labels in a for loop on the behind code.
At the beginning it looks like that:
private void SlotLabelCreation(string name)
{
Label label = new Label();
label.Name = name;
label.HorizontalAlignment = HorizontalAlignment.Left;
label.VerticalAlignment = VerticalAlignment.Top;
label.Content = "[Free Slot]";
label.Foreground = Brushes.Gray;
label.BorderBrush = Brushes.Black;
label.BorderThickness = new Thickness(1);
label.Visibility = Visibility.Hidden;
MainGrid.Children.Add(label);
//the margin has been inserted later in other code.
}
everything was fine but when I inserted to the label other content which not contains the same amount of letters it looks like that:
sorry about the links.. it's because I can't upload images
http://s27.postimg.org/6halp6p37/pic2.png
I wanted to make all slots the same size so I added a MinWidth property to the labels.
The new result was:
http://s27.postimg.org/6z5r51eo3/pic3.png
now it looks better but I am wondering how could I center the content which inside the label.
Unfortunately I didn't find any solution to solve this problem.
p.s, HorizontalAlignment and VerticalAlignment don't solve the problem.
Thanks a lot, Alon P.
You should use HorizontalContentAlignment and VerticalContentAlignment properties