adospace / reactorui-maui

MauiReactor is a MVU UI framework built on top of .NET MAUI
MIT License
588 stars 49 forks source link

Unable to disable keyboard and focus an entry component #193

Closed cris-m closed 8 months ago

cris-m commented 8 months ago

I am creating a OTP page with a keypad keyboard. But I am facing issue, the keypad cannot work since I am unable to focus the entry when render method run. the other issue is to disable the keyboard.

I want to disable keyboard when the render method execute because I will be using keypad. Focus the first entry and after text completed event, focus the next one. Calling EntryFocused property method to focus the entry but _entryRef is always null when the method execute.

public class SecretLockEntry: Component
{
    private Action<string>? _completedAction;
    public SecretLockEntry OnCompleted(Action<string> completedAction)
    {
        _completedAction = completedAction;
        return this;
    }
    public override VisualNode Render()
        =>  Grid([
                new LockEntry()
                    .OnTextChanged((text) => Console.WriteLine(text))
                    .EntryFocused(true),
                new LockEntry()
                    .GridColumn(1),
                new LockEntry()
                    .GridColumn(2),
                new LockEntry()
                    .GridColumn(3),
                new LockEntry()
                    .GridColumn(4),
                new LockEntry()
                    .GridColumn(5),
            ])
            .Rows("*")
            .Columns("*,*,*,*,*,*")
            .ColumnSpacing(4)
            .HorizontalOptions(MauiControls.LayoutOptions.Center);

    private void OnCompleted(string text)
    {
        _completedAction?.Invoke(text);
    }
}

public class LockEntry: Component
{
    private MauiControls.Entry? _entryRef;
    private Action<string>? _textChangedAction;

    public LockEntry OnTextChanged(Action<string> textChangedAction)
    {
        _textChangedAction = textChangedAction;
        return this;
    }

    public LockEntry EntryFocused(bool isFocused=true)
    {
        if(isFocused == false)
            _entryRef?.Unfocus();
        else
            _entryRef?.Focus();
        return this;
    }
    public override VisualNode Render()
        => Border([
            new  BorderlessEntry(entryRef => _entryRef = entryRef)
                .OnAfterTextChanged(OnTextChanged)
                .MaxLength(1)
                .VerticalTextAlignment(TextAlignment.Center)
                .HorizontalTextAlignment(TextAlignment.Center)
                .HeightRequest(42)
                .WidthRequest(42)
        ])
        .HeightRequest(42)
        .StrokeThickness(1)
        .Stroke(Themes.Current.Primary)
        .StrokeShape(
            new RoundRectangle()
                .HeightRequest(42)
                .WidthRequest(42)
                .CornerRadius(new CornerRadius(4))
        );

    private void OnTextChanged(string text)
    {
        _textChangedAction?.Invoke(text);
    }
}
adospace commented 8 months ago

Hi, I'm not sure if I correctly understood your question but I can suggest not using Entry at all. This is the solution I've built for KeeMind app: app: https://github.com/adospace/kee-mind https://github.com/adospace/kee-mind/blob/main/src/KeeMind/Pages/Components/PinBoard.cs

cris-m commented 8 months ago

thanks, I will check the repo.