ОБНОВЛЕНО – Урезан пользовательский контроль:
using CommunityToolkit.Maui.Core.Platform;
using CommunityToolkit.Mvvm.Input;
using System.Diagnostics;
namespace GSL.Presentation.CustomControls;
public partial class GSLEntryControl : ContentView
{
public GSLEntryControl()
{
try
{
InitializeComponent();
}
catch (Exception ex)
{
Debug.WriteLine($"GEORGE: Exception: {ex}");
}
}
[RelayCommand]
private void ClearText()
{
Text = string.Empty;
}
// All the updates will be done in the property set.
public static readonly BindableProperty IsInFocusProperty = BindableProperty.Create(
nameof(IsInFocus),
typeof(bool),
typeof(GSLEntryControl),
false,
BindingMode.OneWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
Debug.WriteLine("George: IsInFocusProperty Start");
if (bindable is GSLEntryControl editText)
{
editText.IsInFocus = (bool)newValue;
}
Debug.WriteLine("George: IsInFocusProperty End");
});
public string _text = string.Empty;
public string Text
{
get
{
return _text;
}
set
{
//Run all this code on the main UI Thread
Application.Current.Dispatcher.Dispatch(() =>
{
Debug.WriteLine("GEORGE: Text Set Start");
_text = value;
//IsClearButtonVisible = _text?.Length > 0;
//SetBorderColor();
Debug.WriteLine("GEORGE: Text Set End");
});
}
}
private bool _isInFocus = false;
public bool IsInFocus
{
get
{
return _isInFocus;
}
set
{
Debug.WriteLine($"GEORGE: IsInFocus Set Start. Value: {value}");
_isInFocus = value;
Application.Current.Dispatcher.Dispatch(async () =>
{
if (_isInFocus)
{
var tempResult = gslEntry.Focus();
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
#if ANDROID
handler.PlatformView.ShowSoftInputOnFocus = false;
#endif
});
//var workResult = await gslEntry.HideSoftInputAsync(CancellationToken.None);
//Debug.WriteLine($"GEORGE: Focus ShowKeyboard Result: {workResult}");
Debug.WriteLine($"GEORGE: Focus-KeyBoardShown: {gslEntry.IsSoftKeyboardShowing()}" );
}
else
{
gslEntry.Unfocus();
}
//SetBorderColor();
Debug.WriteLine("GEORGE: IsInFocus Set End");
});
}
}
//When entry is focused, change border color to blue
async void Entry_Focused(object sender, FocusEventArgs e)
{
Debug.WriteLine("GEORGE: Entry_Focused start");
//EntryFocused?.Invoke(sender, e);
bool workResult = false;
Application.Current.Dispatcher.Dispatch(async () =>
{
workResult = await gslEntry.HideSoftInputAsync(CancellationToken.None);
Debug.WriteLine($"GEORGE: Focus ShowKeyboard Result: {workResult}");
});
Debug.WriteLine("GEORGE: Entry_Focused end");
}
}
Вот XAML для элемента управления:
<ContentView.Resources>
<ResourceDictionary>
<mct:InvertedBoolConverter x:Key = "InvertedBoolConverter"/>
</ResourceDictionary>
</ContentView.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "auto"/>
<RowDefinition Height = "auto"/>
</Grid.RowDefinitions>
<Border x:Name = "entryFrame"
StrokeThickness = "2"
Padding = "0"
HeightRequest = "50"
VerticalOptions = "CenterAndExpand"
HorizontalOptions = "FillAndExpand"
Grid.Row = "0"
Grid.Column = "0"
Grid.ColumnSpan = "2">
<Grid HorizontalOptions = "FillAndExpand" VerticalOptions = "FillAndExpand" ColumnDefinitions = "*,auto">
<Entry x:Name = "gslEntry"
Margin = "10,0,0,0"
ReturnType = "Done"
Keyboard = "Text"
TextTransform = "Uppercase"
FontSize = "16"
Text = "{Binding Text,Mode=TwoWay}"
IsEnabled = "True"
Placeholder = ""
IsPassword = "False"
VerticalOptions = "CenterAndExpand"
HorizontalOptions = "FillAndExpand"
Grid.Column = "0"/>
<!-- Clear Button -->
<ImageButton Source = "ic_delete.xml"
x:Name = "clearButton"
WidthRequest = "32"
HeightRequest = "32"
VerticalOptions = "Center"
HorizontalOptions = "End"
Margin = "0,0,5,0"
Command = "{Binding ClearTextCommand}"
Grid.Column = "1"/>
</Grid>
</Border>
<Label x:Name = "invalidLabel"
Text = "Error"
Margin = "5,0,0,0"
HorizontalOptions = "FillAndExpand" VerticalOptions = "FillAndExpand"
IsVisible = "false"
Style = "{StaticResource ValidationErrorLabelStyle}"
Grid.Row = "1"/>
</Grid>
У меня есть код в событии IsInFocus, позволяющий скрыть клавиатуру, когда элемент управления вводом получает фокус. Я пробовал это несколькими способами, включая использование HideSoftInputAsync(CancellationToken.None) в элементе управления входом
Использование обработчика для Android, чтобы скрыть клавиатуру, как показано в текущем коде. Ни один из них не работает.
Я также пробовал добавлять и удалять асинхронность из диспетчера и полностью удалять диспетчер, но это не дало никакого эффекта.
Вы можете использовать обработчик, чтобы скрыть программную клавиатуру.
Во-первых, вам нужно создать пользовательскую запись.
public class NoKeyBoardEntry:Entry{
}
Во-вторых, вы можете добавить обработчик в GSLEntryControl.xaml.cs, чтобы скрыть клавиатуру, когда вы получаете фокус.
public partial class GSLEntryControl : ContentView
{
public GSLEntryControl()
{
InitializeComponent();
NokeyBoard();
}
void NokeyBoard()
{
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
{
if (view is NoKeyBoardEntry)
{
#if ANDROID
handler.PlatformView.ShowSoftInputOnFocus = false;
#endif
}
});
}
}
Наконец, вы можете создать пользовательскую запись следующим образом.
<ContentPage
...
xmlns:local = "clr-namespace:yourProject"
>
<local:NoKeyBoardEntry>
Вы можете попробовать код handler.PlatformView.GotFocus += (s, e) => { handler.PlatformView.ShowSoftInputOnFocus = false; };
, когда получите фокус записи.
Я добавил эту строку кода и теперь получаю ошибку компиляции: Код серьезности Описание Ошибка состояния подавления строки файла проекта CS1061 «AppCompatEditText» не содержит определения для «GotFocus» и нет доступного метода расширения «GotFocus», принимающего первый аргумент можно найти тип AppCompatEditText (вам не хватает директивы using или ссылки на сборку?) UserControlTest (net8.0-android) C:\Users\xff7wvm\source\repos\UserControlTest\UserControlTest\CustomControls\GSLEnt ryControl\GSLEntryControl.xaml.cs 91 Активен
Я обновляю ответ, и вы можете проверить его.
ОК. Итак, вы по сути говорите, что мне нужно заменить элемент управления Entry, используемый в моем пользовательском элементе управления, новым элементом NoKeyBoardEntry. Затем добавьте весь код обработчика в мой пользовательский элемент управления. Я не понимаю последнюю часть — создание пользовательской записи. Разве он не будет внутри моего пользовательского элемента управления, а не на странице контента?
Так что это работает для меня. В качестве примечания: я добавил распознаватель жестов касания в элемент управления NoKeybBoardEntry в моем пользовательском элементе управления, поэтому, если пользователю нужна клавиатура, он может нажать на элемент управления вводом, и я покажу это. <controls:NoKeyBoardEntry.GestureRecouncers> <TapGestureRecouncer Tapped = "TapGestureRecouncer_Tapped"/> </controls:NoKeyBoardEntry.GestureRecouncers>
В xaml
<ContentPage ...
HideSoftInputOnTapped = "True">
//rest of the code
</ContentPage>
У меня это работает, поэтому всякий раз, когда вы нажимаете за пределами ввода или другой управляющей клавиатуры, она закрывается. Работает как на iOS, так и на Android в последней версии .net 8.
Это не совсем то, что я ищу. Мне нужно запустить код, и в определенных ситуациях, когда элемент управления вводом получает фокус, я не хочу показывать клавиатуру.
@guangyBai Я попробовал приведенное выше предложение (см. обновленный код), но оно не оказало никакого эффекта. Я также значительно сократил код, чтобы упростить устранение неполадок...