浏览代码

fix focus_traversal

/siyaoH-1.17-PlatformMessage
Shiyun Wen 4 年前
当前提交
49643f2b
共有 4 个文件被更改,包括 231 次插入66 次删除
  1. 2
      com.unity.uiwidgets/Runtime/widgets/focus_manager.cs
  2. 253
      com.unity.uiwidgets/Runtime/widgets/focus_traversal.cs
  3. 33
      com.unity.uiwidgets/Runtime/widgets/scroll_position.cs
  4. 9
      com.unity.uiwidgets/Runtime/widgets/scrollable.cs

2
com.unity.uiwidgets/Runtime/widgets/focus_manager.cs


}
}
Rect rect {
public Rect rect {
get {
D.assert(
context != null, () =>

253
com.unity.uiwidgets/Runtime/widgets/focus_traversal.cs


namespace Unity.UIWidgets.widgets {
/*public class FocusTraversalGroup : StatefulWidget {
public enum TraversalDirection {
up,
right,
down,
left,
// TODO(gspencer): Add diagonal traversal directions used by TV remotes and
// game controllers when we support them.
}
public class FocusTravesalUtils {
public static void _focusAndEnsureVisible(
FocusNode node,
ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy
) {
node.requestFocus();
Scrollable.ensureVisible(node.context, alignment: 1.0f, alignmentPolicy: alignmentPolicy);
}
public static BuildContext _getAncestor(BuildContext context, int count = 1) {
BuildContext target = null;
context.visitAncestorElements((Element ancestor)=> {
count--;
if (count == 0) {
target = ancestor;
return false;
}
return true;
});
return target;
}
public static HashSet<T> difference<T>(HashSet<T> aSet, HashSet<T> bSet) {
HashSet<T> result = new HashSet<T>();
foreach (var a in aSet) {
if (!bSet.Contains(a)) {
result.Add(a);
}
}
return result;
}
public static HashSet<T> intersaction<T>(HashSet<T> aSet, HashSet<T> bSet) {
HashSet<T> result = new HashSet<T>();
result = aSet;
foreach (var b in bSet) {
if (!aSet.Contains(b)) {
result.Add(b);
}
}
return result;
}
}
public class FocusTraversalGroup : StatefulWidget {
public FocusTraversalGroup(
Key key = null,
FocusTraversalPolicy policy = null,

public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new TextTreeRenderer.DiagnosticsProperty<FocusTraversalPolicy>("policy", policy));
properties.add(new DiagnosticsProperty<FocusTraversalPolicy>("policy", policy));
}
}
public class _FocusTraversalGroupState : State<FocusTraversalGroup> {

public override bool updateShouldNotify(InheritedWidget oldWidget) => false;
}
public abstract class FocusTraversalPolicy : TextTreeRenderer.Diagnosticable {
public abstract class FocusTraversalPolicy : Diagnosticable {
public class _FocusTraversalGroupInfo {
public _FocusTraversalGroupInfo(
_FocusTraversalGroupMarker marker,
FocusTraversalPolicy defaultPolicy = null,
List<FocusNode> members = null
) {
groupNode = marker?.focusNode;
policy = marker?.policy ?? defaultPolicy ?? new ReadingOrderTraversalPolicy();
members = members ?? new List<FocusNode>();
}
public readonly FocusNode groupNode;
public readonly FocusTraversalPolicy policy;
public readonly List<FocusNode> members;
}
public virtual FocusNode findFirstFocus(FocusNode currentNode) {
D.assert(currentNode != null);

public List<FocusNode> _sortAllDescendants(FocusScopeNode scope) {
D.assert(scope != null);
_FocusTraversalGroupMarker scopeGroupMarker = _getMarker(scope.context);
FocusTraversalPolicy defaultPolicy = scopeGroupMarker?.policy ?? ReadingOrderTraversalPolicy();
FocusTraversalPolicy defaultPolicy = scopeGroupMarker?.policy ?? new ReadingOrderTraversalPolicy();
BuildContext parentContext = _getAncestor(groupNode.context, count: 2);
BuildContext parentContext =FocusTravesalUtils._getAncestor(groupNode.context, count: 2);
groups[parentNode].members.add(groupNode);
groups[parentNode].members.Add(groupNode);
groups[groupNode] ??= _FocusTraversalGroupInfo(groupMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
D.assert(!groups[groupNode].members.contains(node));
groups[groupNode].members.add(node);
groups[groupNode] ??= new _FocusTraversalGroupInfo(groupMarker, members: new List<FocusNode>(), defaultPolicy: defaultPolicy);
D.assert(!groups[groupNode].members.Contains(node));
groups[groupNode].members.Add(node);
HashSet<FocusNode> groupKeys = groups.Keys.ToSet();
foreach ( FocusNode key in groups.keys) {
List<FocusNode> sortedMembers = groups[key].policy.sortDescendants(groups[key].members).toList();
groups[key].members.clear();
groups[key].members.addAll(sortedMembers);
HashSet<FocusNode> groupKeys = new HashSet<FocusNode>(groups.Keys);
foreach ( FocusNode key in groups.Keys) {
List<FocusNode> sortedMembers = groups[key].policy.sortDescendants(groups[key].members).ToList();
groups[key].members.Clear();
groups[key].members.AddRange(sortedMembers);
}
List<FocusNode> sortedDescendants = new List<FocusNode>();

}
visitGroups(groups[scopeGroupMarker?.focusNode]);
D.assert(
sortedDescendants.toSet().difference(scope.traversalDescendants.toSet()).isEmpty,
$"sorted descendants contains more nodes than it should: ({sortedDescendants.toSet().difference(scope.traversalDescendants.toSet())})"
FocusTravesalUtils.difference(new HashSet<FocusNode>(sortedDescendants),(new HashSet<FocusNode>(scope.traversalDescendants))).isEmpty(),
()=>$"sorted descendants contains more nodes than it should: ({FocusTravesalUtils.difference(new HashSet<FocusNode>(sortedDescendants),(new HashSet<FocusNode>(scope.traversalDescendants)))})"
scope.traversalDescendants.toSet().difference(sortedDescendants.toSet()).isEmpty,
"sorted descendants are missing some nodes: (${scope.traversalDescendants.toSet().difference(sortedDescendants.toSet())})"
FocusTravesalUtils.difference(new HashSet<FocusNode>(scope.traversalDescendants),new HashSet<FocusNode>(sortedDescendants)).isEmpty(),
()=>$"sorted descendants are missing some nodes: ({FocusTravesalUtils.difference(new HashSet<FocusNode>(scope.traversalDescendants),new HashSet<FocusNode>(sortedDescendants))})"
);
return sortedDescendants;
}

if (focusedChild == null) {
FocusNode firstFocus = findFirstFocus(currentNode);
if (firstFocus != null) {
_focusAndEnsureVisible(
FocusTravesalUtils._focusAndEnsureVisible(
alignmentPolicy: forward ? ScrollPositionAlignmentPolicy.keepVisibleAtEnd : ScrollPositionAlignmentPolicy.keepVisibleAtStart,
alignmentPolicy: forward ? ScrollPositionAlignmentPolicy.keepVisibleAtEnd : ScrollPositionAlignmentPolicy.keepVisibleAtStart
);
return true;
}

_focusAndEnsureVisible(sortedNodes.First(), alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd);
FocusTravesalUtils._focusAndEnsureVisible(sortedNodes.First(), alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd);
_focusAndEnsureVisible(sortedNodes.Last(), alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart);
FocusTravesalUtils._focusAndEnsureVisible(sortedNodes.Last(), alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart);
return true;
}

FocusNode previousNode = null;
foreach ( FocusNode node in maybeFlipped) {
if (previousNode == focusedChild) {
_focusAndEnsureVisible(
FocusTravesalUtils._focusAndEnsureVisible(
alignmentPolicy: forward ? ScrollPositionAlignmentPolicy.keepVisibleAtEnd : ScrollPositionAlignmentPolicy.keepVisibleAtStart,
alignmentPolicy: forward ? ScrollPositionAlignmentPolicy.keepVisibleAtEnd : ScrollPositionAlignmentPolicy.keepVisibleAtStart
);
return true;
}

public readonly TraversalDirection direction;
public readonly FocusNode node;
}
class _ReadingOrderDirectionalGroupData : Diagnosticable {
public class _ReadingOrderSortData : Diagnosticable {
public _ReadingOrderSortData(FocusNode node) {
D.assert(node != null);
this.node = node;
rect = node.rect;
directionality = _findDirectionality(node.context);
}
public readonly TextDirection directionality;
public readonly Rect rect;
public readonly FocusNode node;
public static TextDirection _findDirectionality(BuildContext context) {
return (context.getElementForInheritedWidgetOfExactType<Directionality>().widget as Directionality).textDirection;
}
public static TextDirection commonDirectionalityOf(List<_ReadingOrderSortData> list) {
IEnumerable<HashSet<Directionality>> allAncestors = list.Select((_ReadingOrderSortData member) => new HashSet<Directionality>(member.directionalAncestors));
HashSet<Directionality> common = null;
foreach ( HashSet<Directionality> ancestorSet in allAncestors) {
common ??= ancestorSet;
common = FocusTravesalUtils.intersaction(common,ancestorSet);
}
if (common.isEmpty()) {
return list.First().directionality;
}
foreach (var com in list.First().directionalAncestors) {
if (common.Contains(com)) {
return com.textDirection;
}
}
return common.First().textDirection;
}
/*public static void sortWithDirectionality(List<_ReadingOrderSortData> list, TextDirection directionality) {
mergeSort<_ReadingOrderSortData>(list, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b)=> {
switch (directionality) {
case TextDirection.ltr:
return a.rect.left.CompareTo(b.rect.left);
case TextDirection.rtl:
return b.rect.right.CompareTo(a.rect.right);
}
D.assert(false, ()=>"Unhandled directionality $directionality");
return 0;
});
}*/
public IEnumerable<Directionality> directionalAncestors {
get {
List<Directionality> getDirectionalityAncestors(BuildContext context) {
List<Directionality> result = new List<Directionality>();
InheritedElement directionalityElement = context.getElementForInheritedWidgetOfExactType<Directionality>();
while (directionalityElement != null) {
result.Add(directionalityElement.widget as Directionality);
directionalityElement = FocusTravesalUtils._getAncestor(directionalityElement)?.getElementForInheritedWidgetOfExactType<Directionality>();
}
return result;
}
_directionalAncestors ??= getDirectionalityAncestors(node.context);
return _directionalAncestors;
}
}
List<Directionality> _directionalAncestors;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<TextDirection>("directionality", directionality));
properties.add(new StringProperty("name", node.debugLabel, defaultValue: null));
properties.add(new DiagnosticsProperty<Rect>("rect", rect));
}
}
public class _ReadingOrderDirectionalGroupData : Diagnosticable {
public _ReadingOrderDirectionalGroupData(List<_ReadingOrderSortData> members) {
this.members = members;
}

TextDirection directionality {
public TextDirection directionality {
get {
return members.First().directionality;
}

Rect rect {
get {if (_rect == null) {
foreach(Rect rect in members.Select<Rect>(
foreach(Rect rect in members.Select(
(_ReadingOrderSortData data) => data.rect)){
_rect ??= rect;
_rect = _rect.expandToInclude(rect);

}
List<Directionality> _memberAncestors;
public static void sortWithDirectionality(List<_ReadingOrderDirectionalGroupData> list, TextDirection directionality) {
/*public static void sortWithDirectionality(List<_ReadingOrderDirectionalGroupData> list, TextDirection directionality) {
return a.rect.left.compareTo(b.rect.left);
return a.rect.left.CompareTo(b.rect.left);
return b.rect.right.compareTo(a.rect.right);
return b.rect.right.CompareTo(a.rect.right);
}
public override void debugFillProperties(TextTreeRenderer.DiagnosticPropertiesBuilder properties) {
}*/
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties.add(DiagnosticsProperty<TextDirection>("directionality", directionality));
properties.add(DiagnosticsProperty<Rect>("rect", rect));
properties.add(IterableProperty<String>("members", members.map<String>((_ReadingOrderSortData member) {
return ""${member.node.debugLabel}"(${member.rect})";
})));
properties.add(new DiagnosticsProperty<TextDirection>("directionality", directionality));
properties.add(new DiagnosticsProperty<Rect>("rect", rect));
//properties.add(new IterableProperty<string>("members", members.map<String>((_ReadingOrderSortData member) {
// return ""${member.node.debugLabel}"(${member.rect})";
//})));
public class ReadingOrderTraversalPolicy : FocusTraversalPolicy , DirectionalFocusTraversalPolicyMixin {
public class ReadingOrderTraversalPolicy : FocusTraversalPolicy , DirectionalFocusTraversalPolicyMixin
{
public List<_ReadingOrderDirectionalGroupData> _collectDirectionalityGroups(IEnumerable<_ReadingOrderSortData> candidates) {
TextDirection currentDirection = candidates.First().directionality;
List<_ReadingOrderSortData> currentGroup = new List<_ReadingOrderSortData>();

continue;
}
currentDirection = candidate.directionality;
result.Add(_ReadingOrderDirectionalGroupData(currentGroup));
result.Add(new _ReadingOrderDirectionalGroupData(currentGroup));
result.Add(_ReadingOrderDirectionalGroupData(currentGroup));
result.Add(new _ReadingOrderDirectionalGroupData(currentGroup));
if (bandGroup.members.length == 1) {
if (bandGroup.members.Count == 1) {
_ReadingOrderSortData.sortWithDirectionality(bandGroup.members, bandGroup.directionality);
// _ReadingOrderSortData.sortWithDirectionality(bandGroup.members, bandGroup.directionality);
public _ReadingOrderSortData _pickNext(List<_ReadingOrderSortData> candidates) {
/*public _ReadingOrderSortData _pickNext(List<_ReadingOrderSortData> candidates) {
mergeSort<_ReadingOrderSortData>(candidates, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b) => a.rect.top.compareTo(b.rect.top));
MERGESORT<_ReadingOrderSortData>(candidates, compare: (_ReadingOrderSortData a, _ReadingOrderSortData b) => a.rect.top.CompareTo(b.rect.top));
Rect band = Rect.fromLTRB(double.negativeInfinity, current.rect.top, double.infinity, current.rect.bottom);
Rect band = Rect.fromLTRB(float.NegativeInfinity, current.rect.top, float.PositiveInfinity, current.rect.bottom);
D.assert(topmost.rect.isEmpty || inBandOfTop.isNotEmpty);
D.assert(topmost.rect.isEmpty || inBandOfTop.isNotEmpty());
if (inBandOfTop.Count <= 1) {
return topmost;
}

if (bandGroups.Count == 1) {
return bandGroups.First().members.first;
return bandGroups.First().members.First();
return bandGroups.First().members.first;
}
return bandGroups.First().members.First();
}*/
public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
/*public override IEnumerable<FocusNode> sortDescendants(IEnumerable<FocusNode> descendants) {
List<_ReadingOrderSortData> data = new List<_ReadingOrderSortData>(){
foreach ( FocusNode node in descendants)
_ReadingOrderSortData(node),
};
List<_ReadingOrderSortData> data = new List<_ReadingOrderSortData>();
foreach (FocusNode node in descendants)
data.Add(new _ReadingOrderSortData(node));
List<FocusNode> sortedList = new List<FocusNode>();
List<_ReadingOrderSortData> unplaced = data;
_ReadingOrderSortData current = _pickNext(unplaced);

unplaced.Remove(current);
}
return sortedList;
}
}*/
}*/
}
}

33
com.unity.uiwidgets/Runtime/widgets/scroll_position.cs


using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public enum ScrollPositionAlignmentPolicy {
explicitPolicy,
keepVisibleAtEnd,
keepVisibleAtStart,
}
public abstract class ScrollPosition : ViewportOffset, ScrollMetrics {
protected ScrollPosition(
ScrollPhysics physics = null,

activity.applyNewDimensions();
}
public Future ensureVisible(RenderObject renderObject,
public Future ensureVisible(
RenderObject renderObject,
Curve curve = null
Curve curve = null,
ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy
float target = viewport.getOffsetToReveal(renderObject, alignment).offset.clamp(
minScrollExtent, maxScrollExtent);
float target = 0f;
switch (alignmentPolicy) {
case ScrollPositionAlignmentPolicy.explicitPolicy:
target = viewport.getOffsetToReveal(renderObject, alignment).offset.clamp(minScrollExtent, maxScrollExtent);
break;
case ScrollPositionAlignmentPolicy.keepVisibleAtEnd:
target = viewport.getOffsetToReveal(renderObject, 1.0f).offset.clamp(minScrollExtent, maxScrollExtent) ;
if (target < pixels) {
target = pixels;
}
break;
case ScrollPositionAlignmentPolicy.keepVisibleAtStart:
target = viewport.getOffsetToReveal(renderObject, 0.0f).offset.clamp(minScrollExtent, maxScrollExtent) ;
if (target > pixels) {
target = pixels;
}
break;
}
if (target == pixels) {
return Future.value();
}

9
com.unity.uiwidgets/Runtime/widgets/scrollable.cs


return widget == null ? null : widget.scrollable;
}
public static Future ensureVisible(BuildContext context,
public static Future ensureVisible(
BuildContext context,
Curve curve = null
Curve curve = null,
ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicitPolicy
) {
duration = duration ?? TimeSpan.Zero;
curve = curve ?? Curves.ease;

context.findRenderObject(),
alignment: alignment,
duration: duration,
curve: curve
curve: curve,
alignmentPolicy: alignmentPolicy
));
context = scrollable.context;
scrollable = of(context);

正在加载...
取消
保存