move focus

main
Stepan Pilipenko 3 weeks ago
parent de6eae9d06
commit 06abd87560

@ -9,6 +9,12 @@ public class FileSystemItem : INotifyPropertyChanged
public string FullName { get; set; } = string.Empty;
public bool IsDirectory { get; set; }
private static string _padding = DefinePadding();
private static string DefinePadding()
{
return new string('\u00A0', 300);
}
public string DisplayText
{
get
@ -17,9 +23,9 @@ public class FileSystemItem : INotifyPropertyChanged
return "[No Name]";
if (Name == "..")
return "⬆️ ..";
return "⬆️ .." + _padding;
return IsDirectory ? $"📁 {Name}" : $"📄 {Name}";
return IsDirectory ? $"📁 {Name + _padding}" : $"📄 {Name + _padding}";
}
}

@ -55,6 +55,8 @@ public partial class MainPage : ContentPage, INotifyPropertyChanged
// Для двойного нажатия
private FileSystemItem? _lastClickedItem;
private int _lastLeftSelectedIndex = 0;
private int _lastRightSelectedIndex = 0;
private bool? _lastIsLeftPanel;
public MainPage(IFileSystemService fileService)
@ -147,14 +149,87 @@ public partial class MainPage : ContentPage, INotifyPropertyChanged
UpdateVisualSelection();
}
// Переключаем фокус с указанием направления
private void MoveFocus(bool moveForward = true)
{
var allFocusable = GetFocusableElements();
var current = allFocusable.FirstOrDefault(x => x.IsFocused);
var next = moveForward ?
GetNextFocusable(current, allFocusable) :
GetPreviousFocusable(current, allFocusable);
next?.Focus();
}
// Следующий элемент (для Down/Tab)
private View GetNextFocusable(View current, List<View> allElements)
{
if (current == null) return allElements.FirstOrDefault();
var currentIndex = allElements.IndexOf(current);
if (currentIndex == -1) return allElements.FirstOrDefault();
var nextIndex = (currentIndex + 1) % allElements.Count;
return allElements[nextIndex];
}
// Предыдущий элемент (для Up/Shift+Tab)
private View GetPreviousFocusable(View current, List<View> allElements)
{
if (current == null) return allElements.LastOrDefault();
var currentIndex = allElements.IndexOf(current);
if (currentIndex == -1) return allElements.LastOrDefault();
var prevIndex = (currentIndex - 1 + allElements.Count) % allElements.Count;
return allElements[prevIndex];
}
private List<View> GetFocusableElements()
{
return this.GetVisualTreeDescendants()
.OfType<View>()
.Where(x => x.IsEnabled && x.IsVisible)
.OrderBy(GetVisualTreeOrder) // Сортируем по порядку в визуальном дереве
.ToList();
}
private int GetVisualTreeOrder(View view)
{
// Простой способ - используем порядок в визуальном дереве
var parent = view.Parent as Layout;
if (parent != null)
{
var index = parent.Children.IndexOf(view);
return index >= 0 ? index : 0;
}
return 0;
}
// Обработчики выделения (вызываются при изменении Selection в CollectionView)
private void OnLeftSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Обновляем индексы при программном изменении selection
if (e.CurrentSelection.FirstOrDefault() is FileSystemItem selectedItem)
{
_leftSelectedIndex = LeftItems.IndexOf(selectedItem);
_isLeftPanelActive = true;
System.Diagnostics.Debug.WriteLine($"L !!! {_leftSelectedIndex} {_lastLeftSelectedIndex}");
if (_lastLeftSelectedIndex < LeftItems.Count && _lastLeftSelectedIndex >= 0)
{
// Автоматически переключаем фокус при достижении границ
if (_leftSelectedIndex > _lastLeftSelectedIndex)
{
// Достигли конца списка - переходим к следующему элементу
MoveFocus(moveForward: true);
}
else if (_leftSelectedIndex < _lastLeftSelectedIndex)
{
// Достигли начала списка - переходим к предыдущему элементу
MoveFocus(moveForward: false);
}
}
UpdateVisualSelection();
}
}
@ -165,6 +240,23 @@ public partial class MainPage : ContentPage, INotifyPropertyChanged
{
_rightSelectedIndex = RightItems.IndexOf(selectedItem);
_isLeftPanelActive = false;
System.Diagnostics.Debug.WriteLine($"R !!! {_rightSelectedIndex} {_lastRightSelectedIndex}");
if (_rightSelectedIndex < RightItems.Count && _rightSelectedIndex >= 0)
{
// Автоматически переключаем фокус при достижении границ
if (_rightSelectedIndex > _lastRightSelectedIndex)
{
// Достигли конца списка - переходим к следующему элементу
MoveFocus(moveForward: true);
}
else if (_rightSelectedIndex < _lastRightSelectedIndex)
{
// Достигли начала списка - переходим к предыдущему элементу
MoveFocus(moveForward: false);
}
}
UpdateVisualSelection();
}
}
@ -197,8 +289,8 @@ public partial class MainPage : ContentPage, INotifyPropertyChanged
private void SetFocusToItem(CollectionView collectionView, FileSystemItem item)
{
// Используем Dispatcher чтобы дождаться рендеринга
Dispatcher.Dispatch(() =>
{
//Dispatcher.Dispatch(() =>
//{
var container = FindButtonContainer(collectionView, item);
if (container is Button button)
{
@ -206,10 +298,20 @@ public partial class MainPage : ContentPage, INotifyPropertyChanged
_currentFocusedButton = button;
_lastClickedItem = item;
// Простой способ - используем текущие индексы
if (_isLeftPanelActive)
{
_lastLeftSelectedIndex = _leftSelectedIndex;
}
else
{
_lastRightSelectedIndex = _rightSelectedIndex;
}
// Прокручиваем к выбранному элементу
collectionView.ScrollTo(item, position: ScrollToPosition.MakeVisible, animate: false);
}
});
//});
}
private Button? FindButtonContainer(CollectionView collectionView, FileSystemItem item)

Loading…
Cancel
Save