maui
maui copied to clipboard
Entry and Editor: option to disable borders and underline (focus)
Description
Would be very usefull a property called HideBorder of boolean type. The same for the underline that appears bellow the control when it has the focus.
Public API Changes
<Entry HideBorder="true" HideUnderLine="true" />
Intended Use-Case
This change is useful when you need to design a cleaner UI.
Instead of these two boolean properties I would prefer BorderThickness
(set to 0 to hide the borders) and UnderlineColor
+ UnderlineFocusedColor
(set to transparent to hide it). This supports much more scenarios and aligns better with other control properties.
it doesn't necessarily have to be "instead of"... one thing doesn't invalidate the other
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
This is really easy to do using handlers:
In CreateMauiApp add this:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.
This is really easy to do using handlers:
In CreateMauiApp add this:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.
Tried, works, thank you! Instead of placing it in MauiProgram/CreateMauiApp() I placed it in Platforms/Android/MainApplication/CreateMauiApp: `namespace MyNamespace { [Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { }
protected override MauiApp CreateMauiApp()
{
// Remove Entry control underline
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) =>
{
h.PlatformView.BackgroundTintList =
Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
});
return MauiProgram.CreateMauiApp();
}
}
}` It is for Android only, would be nice to see the magic line for iOS as well.
Any update for iOS to remove underline ?
Here is iOS workaround.
public class BorderlessEntry : Entry
{
public BorderlessEntry()
{
}
}
public App()
{
InitializeComponent();
SetupHandlers();
MainPage = new AppShell();
}
private void SetupHandlers()
{
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
if (view is BorderlessEntry)
{
#if IOS || MACCATALYST
handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
#endif
}
});
}
For Android, it accepts the enum with namespace but for iOS, it does not. The app fails to compile.
Do you know the reason for this?
It's strange that android specific code only works inside device info platform and as common but not working when added inside compile directive so I'm trying to use the DeviceInfo platform instead.
Это очень легко сделать с помощью обработчиков: В CreateMauiApp добавьте это:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Затем просто создайте подкласс элемента управления Entry и добавьте свойство NoUnderline, а в XAML установите для него значение True.Попробовал, работает, спасибо! Вместо того, чтобы поместить его в MauiProgram/CreateMauiApp(), я поместил его в Platforms/Android/MainApplication/CreateMauiApp: `namespace MyNamespace { [Application] public class MainApplication: MauiApplication { public MainApplication (дескриптор IntPtr, владение JniHandleOwnership) : base (дескриптор, владение ) { }
protected override MauiApp CreateMauiApp() { // Remove Entry control underline Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); }); return MauiProgram.CreateMauiApp(); } }
}` Это только для Android, было бы неплохо увидеть волшебную строку и для iOS.
I also used this method, but I have a text in the border, which cuts it off from above, how is it possible to indent the text so that it is centered on the border?
This would be a nice implementation. It's worth noting that the workaround in the thread doesn't seem to work on some newer versions of Android.
I wanted this behavior disabled globally (I mean it is a BorderlessEntry
control), so I just set that style in the ConnectHandler
:
namespace Project.Droid.Handlers
{
public class BorderlessEntryHandler : EntryHandler
{
protected override void ConnectHandler( AppCompatEditText platformView )
{
base.ConnectHandler( platformView );
platformView.Background = null;
platformView.SetPadding( 0, 0, 0, 0 );
// We do this to hide the bottom underline in MAUI.
platformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf( Colors.Transparent.ToAndroid() );
}
}
}
& of course register my handler in the MauiProgram
:
#if ANDROID
handlers.AddHandler( typeof( BorderlessEntry ), typeof( Droid.Handlers.BorderlessEntryHandler ) );
#endif
使用处理程序真的很容易做到:
在CreateMauiApp中添加以下内容:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
然后,只需子类 Entry 控件并添加 NoUnderline 属性,并在 XAML 中将其设置为 True。
What if I only want to change a certain entry separately? Your method is globally effective. @hartez
@nnn149 You can make this conditional on a custom property which you can then e.g. set in XAML:
internal class OurEntry : Entry
{
public bool NoUnderline { get; set; }
}
and then
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(OurEntry.NoUnderline), (h, v) =>
{
// Remove underline:
var oe = v as OurEntry;
if (oe != null && oe.NoUnderline)
h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
});
@nnn149 You can make this conditional on a custom property which you can then e.g. set in XAML:
internal class OurEntry : Entry { public bool NoUnderline { get; set; } }
and then
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(OurEntry.NoUnderline), (h, v) => { // Remove underline: var oe = v as OurEntry; if (oe != null && oe.NoUnderline) h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Thank you, it works!
Where's the windows solutions... is Maui going to be like Xamarin where it's only iOS and Android...
would be nice to see for windows, but also i do not want blue underline to appear when entry is focused on windows
this is how i removed entry's borders for windows
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if WINDOWS
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) =>
{
h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness()
{
Bottom = 0,
Top = 0,
Left = 0,
Right = 0,
};
});
#endif
This is really easy to do using handlers: In CreateMauiApp add this:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.Tried, works, thank you! Instead of placing it in MauiProgram/CreateMauiApp() I placed it in Platforms/Android/MainApplication/CreateMauiApp: `namespace MyNamespace { [Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { }
protected override MauiApp CreateMauiApp() { // Remove Entry control underline Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); }); return MauiProgram.CreateMauiApp(); } }
}` It is for Android only, would be nice to see the magic line for iOS as well.
Thanks! This works great. Is there a way to change the colour of the caret?
Those changes are enough to remove all visual effects from the entry:
gradientDrawable.SetColor(global::Android.Graphics.Color.Transparent);
nativeView.SetBackground(gradientDrawable);
I did it for all platforms, you can take a look at it: https://github.com/enisn/Xamarin.Forms.Plainer/blob/7015e41fb1d681b8f044f027a70e0d4b70a96f77/src/Plainer.Maui/Handlers/EntryViewHandler.cs#L36-L40
Is there a way to just change colors of the underline?
Those changes are enough to remove all visual effects from the entry:
gradientDrawable.SetColor(global::Android.Graphics.Color.Transparent); nativeView.SetBackground(gradientDrawable);
I did it for all platforms, you can take a look at it: https://github.com/enisn/Xamarin.Forms.Plainer/blob/7015e41fb1d681b8f044f027a70e0d4b70a96f77/src/Plainer.Maui/Handlers/EntryViewHandler.cs#L36-L40
Net 8 Preview 7, additionally requires: nativeView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
This is really easy to do using handlers:
In CreateMauiApp add this:
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { // Remove underline: h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); });
Then just subclass Entry control and add the NoUnderline property and in XAML set it to True.
In my case I don't subclass Entry, Just add handler in MauiProgram and work for every Entry in my xlml pages
Using .net 8 (8.0.0-rc.2.9373/8.0.100-rc.2), what am I doing wrong? I'm trying to get rid of the Entry underline in Android, and adding
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { #if ANDROID h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); #endif });
to MauiProgram.cs will make the entire entry transparent. Adding BackgroundColor in styles.xaml or setting it on the Entry in my .xaml file doesn't change the color. So right now I can choose from ugly underline, or no BackgroundColor?
Is the goto really to create my own entry, referencing different handlers that sets the "BackgrundTintList" to my desired BackgroundColor?
Using .net 8 (8.0.0-rc.2.9373/8.0.100-rc.2), what am I doing wrong? I'm trying to get rid of the Entry underline in Android, and adding
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderline", (h, v) => { #if ANDROID h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid()); #endif });
to MauiProgram.cs will make the entire entry transparent. Adding BackgroundColor in styles.xaml or setting it on the Entry in my .xaml file doesn't change the color. So right now I can choose from ugly underline, or no BackgroundColor?
Is the goto really to create my own entry, referencing different handlers that sets the "BackgrundTintList" to my desired BackgroundColor?
I ran into this too (setting the BackgroundTintList
hides any MAUI BackgroundColor
), and was able to work around it like this:
// Either transparent or the provided background color
var backgroundTint = editor.BackgroundColor.IsDefault() ? Android.Content.Res.ColorStateList.ValueOf( Colors.Transparent.ToAndroid() )
: Android.Content.Res.ColorStateList.ValueOf( editor.BackgroundColor.ToAndroid() );
handler.PlatformView.BackgroundTintList = backgroundTint;
this is how i removed entry's borders for windows
public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); #if WINDOWS Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) => { h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness() { Bottom = 0, Top = 0, Left = 0, Right = 0, }; }); #endif
I don't think this works when the Entry is highlighted. At least I dod something similar (but not 100% the same, using a Handler) and I couldn't get this approach to work properly when entry got focused (border would appear).
However, the following seems to work fine on Windows when using handlers - this would be the native Windows implementation of a custom view:
using MauiEntry = Microsoft.Maui.Controls.Entry;
public class NativeTextField : Grid, IDisposable
{
private readonly TextField _textField;
private readonly TextBox _textBox;
// keep a reference, so we can unhook event on Dispose
private MauiEntry _entry;
// TextField is my virtual view, a custom class that behaves a bit like an entry
public NativeTextField(TextField textField)
{
_textField = textField;
_entry = new MauiEntry();
_entry.Focused += Entry_Focused;
_textBox = (TextBox)_entry.ToPlatform(textField.Handler!.MauiContext!);
}
public void Dispose()
{
_entry.Focused -= Entry_Focused;
GC.SuppressFinalize(this);
}
// when focused: recursively look for a child border and if found, hide it
private void Entry_Focused(object? sender, Microsoft.Maui.Controls.FocusEventArgs e)
{
if (_textBox.GetFirstChildOfType<Border>() is Border border)
{
border.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
}
}
}
// instead of this manual implementation, could also use a CommunityToolkit WinUI Nuget package that has some Linq stuff
internal static class DependencyObjectExtensions
{
internal static DependencyObject? GetFirstChildOfType<T>(this DependencyObject textBox) where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(textBox);
for (var i = 0; i < childCount; i++)
{
var child = VisualTreeHelper.GetChild(textBox, i);
if (child.GetType().Equals(typeof(T)))
{
return child;
}
else
{
if (GetFirstChildOfType<T>(child) is T obj)
{
return obj;
}
}
}
return null;
}
}
P.S.: I think more or less the same code could be used in a Behavior, which would probably be a better idea than writing a custom Entry
.
That works nicely to remove that bottom border of the Entry control but its not removing the border of the text when I type something in the Entry. Is there a quick hack to remove that as well?
I've tried changing the BackgroundColor as well as setting the Background to null as suggested in many links but that did not do the trick for the underline of the text when typing in the Entry.
For context, my issue is on android, by adding h.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(Colors.Transparent.ToAndroid());
I can perfectly fine remove the bottom border but as you can see here, when typing something, I still get a different underline which I would like to remove as well.
Best regards.
Have you made any further progress on this issue?
It would be very useful to have BorderColor and BorderWisth properties on any control. I would like to set these properties similarly as the BackgroundColor.
There is clearly a need for these properties.
It should not be necessary that every developer has to add similar code on platform level to get this done. This should be part of MAUI.
I am looking forward to these properties in the next version :-)
Thanks
This is the solutiont to just change the color!!! I spent so long looking for it :') Go to -> Platforms/Android/Resources/values/colors.xml
Is there a way to just change colors of the underline?
This is such a ubiquitous requirement, this absolutely be in .NET MAUI. Yep easy enough to do with handlers but there have been a couple of regressions, so making this part of .NET MAUI itself would ensure these get picked up in testing of releases. This is absolutely something nearly everyone needs and would be awesome to include.
this is how i removed entry's borders for windows
public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); }); #if WINDOWS Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoUnderlineWindows", (h, v) => { h.PlatformView.BorderThickness = new Microsoft.UI.Xaml.Thickness() { Bottom = 0, Top = 0, Left = 0, Right = 0, }; }); #endif
I was able to remove the borders, in Windows, when Entry is with focus with this line:
nativeView.Style = null;
No need to add color resources in Platform\Windows\App.xaml too.