Esempio n. 1
0
			// The hovered child view.
			// The next target in the target list.
			public static android.view.ViewGroup.HoverTarget obtain(android.view.View child)
			{
				android.view.ViewGroup.HoverTarget target;
				lock (sRecycleLock)
				{
					if (sRecycleBin == null)
					{
						target = new android.view.ViewGroup.HoverTarget();
					}
					else
					{
						target = sRecycleBin;
						sRecycleBin = target.next;
						sRecycledCount--;
						target.next = null;
					}
				}
				target.child = child;
				return target;
			}
Esempio n. 2
0
			public void recycle()
			{
				lock (sRecycleLock)
				{
					if (sRecycledCount < MAX_RECYCLED)
					{
						next = sRecycleBin;
						sRecycleBin = this;
						sRecycledCount += 1;
					}
					else
					{
						next = null;
					}
					child = null;
				}
			}
Esempio n. 3
0
		protected internal override bool dispatchHoverEvent(android.view.MotionEvent @event
			)
		{
			int action = @event.getAction();
			// First check whether the view group wants to intercept the hover event.
			bool interceptHover = onInterceptHoverEvent(@event);
			@event.setAction(action);
			// restore action in case it was changed
			android.view.MotionEvent eventNoHistory = @event;
			bool handled = false;
			// Send events to the hovered children and build a new list of hover targets until
			// one is found that handles the event.
			android.view.ViewGroup.HoverTarget firstOldHoverTarget = mFirstHoverTarget;
			mFirstHoverTarget = null;
			if (!interceptHover && action != android.view.MotionEvent.ACTION_HOVER_EXIT)
			{
				float x = @event.getX();
				float y = @event.getY();
				int childrenCount = mChildrenCount;
				if (childrenCount != 0)
				{
					android.view.View[] children = mChildren;
					android.view.ViewGroup.HoverTarget lastHoverTarget = null;
					{
						for (int i = childrenCount - 1; i >= 0; i--)
						{
							android.view.View child = children[i];
							if (!canViewReceivePointerEvents(child) || !isTransformedTouchPointInView(x, y, child
								, null))
							{
								continue;
							}
							// Obtain a hover target for this child.  Dequeue it from the
							// old hover target list if the child was previously hovered.
							android.view.ViewGroup.HoverTarget hoverTarget = firstOldHoverTarget;
							bool wasHovered;
							{
								for (android.view.ViewGroup.HoverTarget predecessor = null; ; )
								{
									if (hoverTarget == null)
									{
										hoverTarget = android.view.ViewGroup.HoverTarget.obtain(child);
										wasHovered = false;
										break;
									}
									if (hoverTarget.child == child)
									{
										if (predecessor != null)
										{
											predecessor.next = hoverTarget.next;
										}
										else
										{
											firstOldHoverTarget = hoverTarget.next;
										}
										hoverTarget.next = null;
										wasHovered = true;
										break;
									}
									predecessor = hoverTarget;
									hoverTarget = hoverTarget.next;
								}
							}
							// Enqueue the hover target onto the new hover target list.
							if (lastHoverTarget != null)
							{
								lastHoverTarget.next = hoverTarget;
							}
							else
							{
								lastHoverTarget = hoverTarget;
								mFirstHoverTarget = hoverTarget;
							}
							// Dispatch the event to the child.
							if (action == android.view.MotionEvent.ACTION_HOVER_ENTER)
							{
								if (!wasHovered)
								{
									// Send the enter as is.
									handled |= dispatchTransformedGenericPointerEvent(@event, child);
								}
							}
							else
							{
								// enter
								if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
								{
									if (!wasHovered)
									{
										// Synthesize an enter from a move.
										eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
										eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_ENTER);
										handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
										// enter
										eventNoHistory.setAction(action);
										handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
									}
									else
									{
										// move
										// Send the move as is.
										handled |= dispatchTransformedGenericPointerEvent(@event, child);
									}
								}
							}
							if (handled)
							{
								break;
							}
						}
					}
				}
			}
			// Send exit events to all previously hovered children that are no longer hovered.
			while (firstOldHoverTarget != null)
			{
				android.view.View child = firstOldHoverTarget.child;
				// Exit the old hovered child.
				if (action == android.view.MotionEvent.ACTION_HOVER_EXIT)
				{
					// Send the exit as is.
					handled |= dispatchTransformedGenericPointerEvent(@event, child);
				}
				else
				{
					// exit
					// Synthesize an exit from a move or enter.
					// Ignore the result because hover focus has moved to a different view.
					if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
					{
						dispatchTransformedGenericPointerEvent(@event, child);
					}
					// move
					eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
					eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_EXIT);
					dispatchTransformedGenericPointerEvent(eventNoHistory, child);
					// exit
					eventNoHistory.setAction(action);
				}
				android.view.ViewGroup.HoverTarget nextOldHoverTarget = firstOldHoverTarget.next;
				firstOldHoverTarget.recycle();
				firstOldHoverTarget = nextOldHoverTarget;
			}
			// Send events to the view group itself if no children have handled it.
			bool newHoveredSelf = !handled;
			if (newHoveredSelf == mHoveredSelf)
			{
				if (newHoveredSelf)
				{
					// Send event to the view group as before.
					handled |= base.dispatchHoverEvent(@event);
				}
			}
			else
			{
				if (mHoveredSelf)
				{
					// Exit the view group.
					if (action == android.view.MotionEvent.ACTION_HOVER_EXIT)
					{
						// Send the exit as is.
						handled |= base.dispatchHoverEvent(@event);
					}
					else
					{
						// exit
						// Synthesize an exit from a move or enter.
						// Ignore the result because hover focus is moving to a different view.
						if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
						{
							base.dispatchHoverEvent(@event);
						}
						// move
						eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
						eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_EXIT);
						base.dispatchHoverEvent(eventNoHistory);
						// exit
						eventNoHistory.setAction(action);
					}
					mHoveredSelf = false;
				}
				if (newHoveredSelf)
				{
					// Enter the view group.
					if (action == android.view.MotionEvent.ACTION_HOVER_ENTER)
					{
						// Send the enter as is.
						handled |= base.dispatchHoverEvent(@event);
						// enter
						mHoveredSelf = true;
					}
					else
					{
						if (action == android.view.MotionEvent.ACTION_HOVER_MOVE)
						{
							// Synthesize an enter from a move.
							eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
							eventNoHistory.setAction(android.view.MotionEvent.ACTION_HOVER_ENTER);
							handled |= base.dispatchHoverEvent(eventNoHistory);
							// enter
							eventNoHistory.setAction(action);
							handled |= base.dispatchHoverEvent(eventNoHistory);
							// move
							mHoveredSelf = true;
						}
					}
				}
			}
			// Recycle the copy of the event that we made.
			if (eventNoHistory != @event)
			{
				eventNoHistory.recycle();
			}
			// Done.
			return handled;
		}