How can I make Label text Underline in WinPhone using Xamarin Forms ?
You have top create a new control in your PCL/shared project inheriting from Label.
public class Exlabel : Label
{
}
In your windows phone project create a Custom Renderer for it as follows and use the TextBlock.TextDecorations Property to set the underline.
The label is rendered as TextBlock in windows.
Sample (untested):
[assembly: ExportRenderer(typeof(Exlabel), typeof(ExlabelRenderer))]
namespace CustomRenderer.WinPhone81
{
public class ExlabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.TextDecorations = TextDecorations.UnderLine;
}
}
}
}
If you are using the windows phone check out this sample - How to format texts of TextBlock using xaml in Windows Phone.
For WinRT you can use this - TextBlock underline in WinRT.
In SilverLight WinPhone (the old and not so supported template), you can also use the Margin to achieve what you require, similar to How to make an underlined input text field in Windows Phone?.
Try using following xaml;
<StackLayout Orientation="Vertical">
<Label Text="SomeText"/>
<BoxView HeightRequest="1" HorizontalOptions="FillAndExpand" BackgroundColor="Black"/>
</StackLayout>
this should do it for all 3 platforms. :)
I think you need to create a custom view for this as a Layout/Grid that has a Label and a BoxView with a small heightRequest below the label to act as a line.
Create a label renderer in your WinPhone project:
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Documents;
[assembly: ExportRenderer(typeof(ExtendedLabel), typeof(ExtendedLabelRenderer))]
namespace SampleProject.WinPhone
{
public class ExtendedLabelRenderer: LabelRenderer
{
ExtendedLabel element;
TextBlock control;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if((ExtendedLabel)Element == null || Control == null)
return;
element = (ExtendedLabel)Element;
control = Control;
UnderlineText();
}
void UnderlineText()
{
control.Text = string.Empty;
Underline ul = new Underline();
Run run = new Run();
run.Text = element.Text;
ul.Inlines.Add(run);
control.Inlines.Add(ul);
}
}
}
Related
I am using xamarin forms SearchBar control. I want to remove clear button x icon without using custom renderer.
<controls:ExSearchBar
x:Name="entrySearch"
BackgroundColor="White"
CornerRadius="6"
BorderWidth="1"
HeightRequest="45"
Text="{Binding SearchText}"
HorizontalOptions="FillAndExpand"
Placeholder="search">
</controls:ExSearchBar>
This is ExSearchBar control in shared project
public class ExSearchBar : SearchBar
{
public static readonly BindableProperty ElevationProperty = BindableProperty.Create(nameof(Elevation), typeof(float), typeof(ExFrame), default(float));
public float Elevation
{
get { return (float)GetValue(ElevationProperty); }
set { SetValue(ElevationProperty, value); }
}
}
How can I do that?
The situation you are describing is the exact reason why Xamarin Forms ships with the ability to create custom renderers. The forms team define the UI elements in abstract (seperate from their native implementation) and when there is a specific feature that is not defined in their API, you must go down to the platform level to change it.
You can also use an Effect to achieve the same result, I have provided a custom renderer for iOS & Android to show you how you would go about achieving the UI you desire:
iOS:
public class SearchBarButtonRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
Control.SearchTextField.ClearButtonMode = UITextFieldViewMode.Never;
}
}
}
Really simple, just remove the clear button from the underlying UITextField
Android
public class SearchBarButtonRenderer : SearchBarRenderer
{
private readonly Context _context;
public SearchBarButtonRenderer(Context context)
: base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
// Get Search Close Button Drawable
var closeButtonId = Resources.GetIdentifier("android:id/search_close_btn", null, null);
var searchEditText = Control.FindViewById<ImageView>(closeButtonId);
// Get Close Button Drawable To Replace Existing Drawable
var closeDrawable = GetCloseButtonDrawable() as VectorDrawable;
if (closeDrawable is null) return;
// Apply Transparent Color To Drawable (To Make Invisible)
var buttonColor = Xamarin.Forms.Color.Transparent.ToAndroid();
closeDrawable.SetTint(buttonColor);
// Set Drawable On Control
searchEditText.SetImageDrawable(closeDrawable);
}
}
private Drawable GetCloseButtonDrawable()
{
return ContextCompat.GetDrawable(_context, Resource.Drawable.abc_ic_clear_material);
}
}
A little bit of a fiddle, find the close button drawable and replace it with a custom styled drawable
Using Xamarin Forms (version 2.5.0.121934), I'm working on an app targeting Android, iOS, and UWP. I need to add underlining and strikethrough to some text, which require custom renderers. For Android and iOS, everything is working fine, and on UWP, applying strikethrough or underline works correctly, but removing those decorations isn't working.
Here's the entirety of the UWP renderer:
[assembly: ExportRenderer(typeof(EnhancedLabel), typeof(EnhancedLabelRenderer))]
namespace myApp.UWP
{
public class EnhancedLabelRenderer : LabelRenderer
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var strikethrough = ((EnhancedLabel)sender).Strikethrough;
var underline = ((EnhancedLabel)sender).Underline;
if (strikethrough && underline)
{
Control.TextDecorations = TextDecorations.Strikethrough | TextDecorations.Underline;
}
else if (strikethrough)
{
Control.TextDecorations = TextDecorations.Strikethrough;
}
else if (underline)
{
Control.TextDecorations = TextDecorations.Underline;
}
else
{
Control.TextDecorations = TextDecorations.None;
}
}
}
}
EnhancedLabel is a simple class that extends Xamarin.Forms.Label and adds the simple BindableProperty fields that specify strikethrough or underlining.
The renderer is properly setting TextDecorations.None, but that isn't having an effect on the UI. I've worked through this in the debugger, and can actually see that the state of the TextBlock within the ExtendedLabel has TextDecorations.None, but the UI is still drawing it with underlining or strikethrough (essentially, either of those can be added, but neither can be removed).
I've gone through the Xamarin documentation and looked at the bugs in Bugzilla, and haven't found any clues. Has any one else encountered this? Wondering if there's a UWP-specific call I need to make that I missed, or if using TextDecorations is the wrong way to apply the styles, or if I've actually stumbled across a bug.
Bug in UWP as in Xaml below:
<TextBlock>
<Run Text="Decorations can be toggled on and off"/>
</TextBlock>
<TextBlock Text="Decorations will not toggle off"/>
It is the same issue if you code the TextBlock:
TextBlock textBlock = new TextBlock { FontSize = 18.0 };
textBlock.Inlines.Add(new Windows.UI.Xaml.Documents.Run { Text = "This text will not stick on text decoration." });
TextBlock textBlockBad = new TextBlock
{
FontSize = 18.0,
Text = "This text will not enable the TextDecorations to be turned off"
};
Same behaviour found with Typography.Capitals
Just need to use only Inlines for TextBlocks and presumably RichTextBlocks to avoid these issues.
Wondering if there's a UWP-specific call I need to make that I missed, or if using TextDecorations is the wrong way to apply the styles, or if I've actually stumbled across a bug.
If you want yo use TextDecorations, you could use the Run instance to pack the decorated text like the follow.
Underline ul = new Underline();
ul.TextDecorations = TextDecorations.Strikethrough;
Run r = new Run();
r.Text = "Here is an underlined text";
ul.Inlines.Add(r);
MyTextBlock.Inlines.Add(ul);
For you requirement, I have create a CustomLabel that you could use directly.
CustomLabel.cs
public class CustomLabel : Label
{
public static readonly BindableProperty DeckProperty = BindableProperty.Create(
propertyName: "Deck",
returnType: typeof(TextDeck),
declaringType: typeof(CustomLabel),
defaultValue: default(TextDeck));
public TextDeck Deck
{
get { return (TextDeck) GetValue(DeckProperty); }
set { SetValue(DeckProperty, value); }
}
}
public enum TextDeck
{
None = 0,
//
// Summary:
// Underline is applied to the text.
Underline = 1,
//
// Summary:
// Strikethrough is applied to the text.
Strikethrough = 2
}
CustomLabelRenderer.cs
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var element = Element as CustomLabel;
var underline = new Underline();
var run = new Run();
switch (element.Deck)
{
case TextDeck.None:
underline.TextDecorations = TextDecorations.None;
break;
case TextDeck.Strikethrough:
underline.TextDecorations = TextDecorations.Strikethrough;
break;
case TextDeck.Underline:
underline.TextDecorations = TextDecorations.Underline;
break;
}
run.Text = element.Text;
underline.Inlines.Add(run);
Control.Inlines.Clear();
Control.Inlines.Add(underline);
}
}
}
Usage
<local:CustomLabel Deck="Underline" Text="Welcome to Xamarin.Forms!" />
I am working with search bar in xamarin forms. I am not able to remove search text in search bar by clicking cross button. I am using custom renderer for remove cancel text in search bar. When I am using that renderer I am not able delete the text, If I remove that renderer it work's fine. what the wrong I have done in renderer file. Here is the sample code in renderer for hide the cancel button beside the search bar.
Renderer Sample code:
protected override void OnElementPropertyChanged(object sender, PropertyChnagedEventArgs e)
{
Control.ShowCancelButton = false;
}
When I try to remove text in search bar by clicking cross image in search bar it's not working in xamarin ios but it's working fine in ios.
Sample code :
<StackLayout Grid.Column = "0" Orientation = "Horizontal">
<Image Source = "backarrow.png" HorizontalOptions = "StartAndExpand" VerticalOptions = "CenterAndExpand" />
<controls:CustomSearchbar x:Name = "CustomSearchbar" BackgroundColor ="Transparent" Text ="{Binding SearchTag}" SearchCommand ="{Binding RestaurantSearchCommand}" GHorizontalOptions = "StartAndExpand" VerticalOptions = "CenterAndExpand" >
Here is the code I am using for search bar. Here 'customsearchbar' class is inherited from searchrenderer.
It works fine for me.
Here's my code for example:
MySearchBar.cs in PCL:
using Xamarin.Forms;
namespace Kevin_XF
{
public class MySearchBar : SearchBar
{
}
}
MySearchBarRenderer.cs in iOS platform:
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Kevin_XF.iOS;
using Kevin_XF;
using System.ComponentModel;
[assembly: ExportRenderer(typeof(MySearchBar),typeof(MySearchBarRenderer))]
namespace Kevin_XF.iOS
{
public class MySearchBarRenderer: SearchBarRenderer
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Control != null)
{
Control.ShowsCancelButton = false;
}
}
}
}
Xaml code in MainPage.xaml:
<StackLayout>
<local:MySearchBar x:Name = "CustomSearchbar" BackgroundColor ="Transparent" HorizontalOptions = "StartAndExpand" VerticalOptions = "CenterAndExpand" />
</StackLayout>
It works like this:
I followed this tutorial to create underline effect. However, when my page starts it breaks without exception being caught. Has anyone managed to create underline effect? Here is a code:
UnderlineEffect.cs:
namespace XX.CustomForms
{
public class UnderlineEffect : RoutingEffect
{
public const string EffectNamespace = "XX.CustomForms";
public UnderlineEffect() : base($"{EffectNamespace}.{nameof(UnderlineEffect)}")
{
}
}
}
UnderlineLabel_Droid.cs:
[assembly: ResolutionGroupName(UnderlineEffect.EffectNamespace)]
[assembly: ExportEffect(typeof(UnderlineEffect), nameof(UnderlineEffect))]
namespace XX.Droid.Renderers
{
public class UnderlineEffect : PlatformEffect
{
protected override void OnAttached()
{
SetUnderline(true);
}
protected override void OnDetached()
{
SetUnderline(false);
}
protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
if (args.PropertyName == Label.TextProperty.PropertyName || args.PropertyName == Label.FormattedTextProperty.PropertyName)
{
SetUnderline(true);
}
}
private void SetUnderline(bool underlined)
{
try
{
var textView = (TextView)Control;
if (underlined)
{
textView.PaintFlags |= PaintFlags.UnderlineText;
}
else
{
textView.PaintFlags &= ~PaintFlags.UnderlineText;
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot underline Label. Error: ", ex.Message);
}
}
}
}
And my xaml:
xmlns:custom="clr-namespace:XX.CustomForms;assembly=XX"
<Label Text="Privacy Notice" HorizontalTextAlignment="Center" >
<Label.Effects>
<custom:UnderlineEffect />
</Label.Effects>
</Label>
Xamarin Forms added a TextDecorations property to Labels. Update to Xamarin Forms 3.3.0+ and just set:
C#
Label label = new Label {
TextDecorations = TextDecorations.Underline
}
XAML
<Label TextDecorations="Underline"/>
Docs Link
Be aware that there was a bug on iOS when an underlined Label is in a ListView. Looks like it has been fixed and released in 3.5.0. I am still using a custom renderer on iOS for now until I am ready to update to the latest version.
GitHub issue
So continue using the iOS effect if you have not updated to XF 3.5.0 yet.
The lengths some people are going to to get underlined text in Xamarin is insane. Here's a way to do it without a thousand line custom renderer. The negative margin trick came from this guy.
<StackLayout HorizontalOptions="Start">
<Label Text="Underlined Text" />
<BoxView HeightRequest="1" BackgroundColor="Purple" HorizontalOptions="FillAndExpand" Margin="0,-7,0,0" />
</StackLayout>
Use TextDecorations property in Label class.
<Label Text="Underlined Text" TextDecorations="Underline"/>
To be able to add an underline to a label, we created custom renderers that inherits from Label.
public class CustomLabel : Label
{
public static readonly BindableProperty IsUnderlinedProperty = BindableProperty.Create("IsUnderlined", typeof(bool), typeof(CustomLabel), false);
public bool IsUnderlined
{
get { return (bool) GetValue(IsUnderlinedProperty); }
set { SetValue(IsUnderlinedProperty, value); }
}
}
In your xaml page you can use it as:
<s:CustomLabel IsUnderlined="True" Text="UnderlinedText" FontSize="18" HorizontalOptions="CenterAndExpand">
Note that s is the namespace declared in the root element of xaml page.
Now your renderer in Android would be something like that:
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null && Element != null)
{
if (((CustomLabel)Element).IsUnderlined)
{
Control.PaintFlags = PaintFlags.UnderlineText;
}
}
}
}
I have an Entry in my ContentPage and am doing rendering in Xamarin Android.
Here my problem is EditText background color is white and cursor color is also white.
Here I want to change the cursor color to black.
Is there any way to change the cursor color?
Here is my code.
Entry to ExtendedEntry :
public class ExtendedEntry : Entry { }
Use ExtendedEntry in Content Page :
var txtPhoneNumber = new ExtendedEntry { Placeholder = "Phone Number", Keyboard = Keyboard.Numeric, TextColor = Color.Black };
Render the ExtendedEntry in Xamarin Android :
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ExtendedEntry), typeof(ExtendedEntryRender))]
namespace Project.Droid
{
public class ExtendedEntryRender : EntryRenderer
{
// Override the OnElementChanged method so we can tweak this renderer post-initial setup
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{ // perform initial setup
// lets get a reference to the native control
var nativeEditText = (global::Android.Widget.EditText)Control;
// do whatever you want to the textField here!
nativeEditText.SetBackgroundResource(Resource.Drawable.text_box);
}
}
}
}
Can any one help me to solve this problem?
Thanks in advance.
You can change the cursor color using:
IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));
IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID (IntPtrtextViewClass, "mCursorDrawableRes", "I");
JNIEnv.SetField (Control.Handle, mCursorDrawableResProperty, 0); // replace 0 with a Resource.Drawable.my_cursor
0 will keep the same color as the TextColor on your Entry.
Edit: To change the cursur color the only option is to change the theme by adding for example:
Theme = "android:style/Theme.Holo.light" in MainActivity