public void OnScrollViewDragStarted() { dragStartPosition = ScrollView.transform.position; dragStartTime = Time.time; if (_verticalMode) { _prevCenterTarget = CenterOnChild.DetermineCenterTarget(); CenterCardIndex = _carouselCards.FindIndex(x => (x as MonoBehaviour).transform == _prevCenterTarget); } }
public void OnScrollViewDragFinished() { dragEndPosition = ScrollView.transform.position; Transform newCenterTarget = null; if (!_verticalMode) { Vector2 drag = dragEndPosition - dragStartPosition; dragStartPosition = dragEndPosition = Vector3.zero; float sqrDragDistance = Vector3.SqrMagnitude(drag); if (sqrDragDistance > dragDistanceThreshold * dragDistanceThreshold || sqrDragDistance / ((Time.time - dragStartTime) / 1.5) > dragDistanceThreshold * dragDistanceThreshold) { // We dragged far enough: try centering on the next card in this direction. if (null == CenterOnChild.centeredObject) { newCenterTarget = CenterOnChild.DetermineCenterTarget(); } else { float dot = Vector3.Dot(drag, Vector3.right); int newIndex = (int)(CenterCardIndex - Mathf.Sign(dot)); if (newIndex >= 0 && newIndex < _carouselCards.Count) { newCenterTarget = (_carouselCards[newIndex] as MonoBehaviour).transform; } else { newCenterTarget = CenterOnChild.centeredObject.transform; } } } } if (null == newCenterTarget) { // Try recentering on centered object, if it exists if (_verticalMode) { newCenterTarget = CenterOnChild.DetermineCenterTarget(); } else { if (null != CenterOnChild.centeredObject) { CenterOnChild.Recenter(); } else { Debug.LogError("CardCarousel: centered on null"); } return; } } DateListItem dli = newCenterTarget.GetComponent <DateListItem>(); Transform nearestToDateLabel = null; int newTargetIndex = -1; if (null != dli) { // Make sure we still recycle the cards if we center on a date label // Find the nearest card in the direction we came from Vector3 deltaScroll = dli.transform.localPosition - _prevCenterTarget.transform.localPosition; RaycastHit[] hits = Physics.RaycastAll(dli.transform.position, -deltaScroll); if (null != hits && hits.Length > 0) { // Pull out only cards, so no date labels List <RaycastHit> hitList = hits.ToList().FindAll(x => null == x.collider.gameObject.GetComponent <DateListItem>()); // Sort by closest hitList.Sort((a, b) => a.distance.CompareTo(b.distance)); // Grab the first (closest) Transform closest = hitList[0].collider.transform; if (null == closest) { return; } Debug.LogWarning("Found " + closest.name); newTargetIndex = _carouselCards.FindIndex(x => (x as MonoBehaviour).transform == closest); } } else if (!_verticalMode) { CenterOnChild.CenterOn(newCenterTarget); } if (newTargetIndex < 0) { newTargetIndex = _carouselCards.FindIndex(x => (x as MonoBehaviour).transform == newCenterTarget); } if (0 > newTargetIndex) { return; } if (_verticalMode) { _prevCenterTarget = newCenterTarget; } int halfCarouselLength = _carouselLength / 2; int numCardsToMove = newTargetIndex - halfCarouselLength; CenterCardIndex = newTargetIndex; if (0 == numCardsToMove) { return; } // Slide the visible indices over an equal amount. // Clamp the number of cards moved if it would push us out of bounds. int oldMin = VisibleCardIndexMin; VisibleCardIndexMin = Mathf.Clamp(VisibleCardIndexMin + numCardsToMove, 0, _cardCache.Count - _carouselLength); int diff = VisibleCardIndexMin - oldMin; numCardsToMove = diff; VisibleCardIndexMax = Mathf.Clamp(VisibleCardIndexMax + numCardsToMove, _carouselLength - 1, _cardCache.Count - 1); int positiveEdge = numCardsToMove < 0 ? 0 : _carouselCards.Count; int negativeEdge = numCardsToMove < 0 ? _carouselCards.Count : 0; int negativeIndex = negativeEdge - (negativeEdge == _carouselLength ? 1 : 0); int positiveIndex = positiveEdge - (positiveEdge == _carouselLength ? 1 : 0); for (int i = 0; i < Mathf.Abs(numCardsToMove); i++) { IActivityViewModelBase movedCard = _carouselCards[negativeIndex]; IActivityViewModelBase edgeCard = _carouselCards[positiveIndex]; DateTime lastDate = DateTime.MinValue; if (_verticalMode) { lastDate = (edgeCard as ActivityTableCellViewModel).data.dateTime.Date; } int indexToPopulate = (numCardsToMove > 0 ? VisibleCardIndexMax - (numCardsToMove - 1 - i) : VisibleCardIndexMin + (Mathf.Abs(numCardsToMove) - 1 - i)); movedCard.Clear(); movedCard.Populate(_cardCache[indexToPopulate], _onCardClickedDelegate, _allowRecommending); DateTime newDate = _cardCache[indexToPopulate].dateTime.Date; Vector3 newPosition = (edgeCard as MonoBehaviour).transform.localPosition; if (_verticalMode) { float singleCardOffset = ((edgeCard as MonoBehaviour).GetComponent <Collider>() as BoxCollider).size.y + _cardPadding; newPosition.y -= (numCardsToMove > 0 ? 1 : -1) * singleCardOffset; if (lastDate != newDate) { // If we're moving positive, it's the newDate. Else it's lastDate. DateTime dateToShow = (numCardsToMove > 0 ? newDate : lastDate); Vector3 dateListItemPosition = newPosition; newPosition.y -= (numCardsToMove > 0 ? 1 : -1) * singleCardOffset; // Check if there's already a date label for this date. DateListItem[] dateLabels = ScrollView.transform.GetComponentsInChildren <DateListItem>(); var dateLabel = dateLabels.ToList().Find(x => x.dateTime.Date == dateToShow); if (dateLabel == null) { // Now at the singleCardOffset position, spawn a date label. GameObject dateListItemPrefab = (GameObject)Resources.Load(_cardPrefabPath + "DateListItem"); GameObject dateListItem = NGUITools.AddChild(ScrollView.gameObject, dateListItemPrefab); DateListItem dliScript = dateListItem.GetComponent <DateListItem>(); UIDragScrollView dateDragScrollView = dateListItem.AddComponent <UIDragScrollView>(); dateDragScrollView.scrollView = ScrollView; // Still respect relative dates DateTime now = DateTime.Now; DateTime yesterday = DateTime.Now.AddDays(-1); DateTime tomorrow = DateTime.Now.AddDays(1); if (dateToShow.Date == now.Date) { dliScript.dayLabel.text = "TODAY"; } else if (dateToShow.Date == yesterday.Date) { dliScript.dayLabel.text = "YESTERDAY"; } else if (dateToShow.Date == tomorrow.Date) { dliScript.dayLabel.text = "TOMORROW"; } else { dliScript.dayLabel.text = dateToShow.DayOfWeek.ToString().ToUpper(); } dliScript.dateLabel.text = dateToShow.ToString("M"); dliScript.dateTime = dateToShow.Date; dateListItem.gameObject.transform.localPosition = dateListItemPosition; } } } else { newPosition.x += (numCardsToMove > 0 ? 1 : -1) * (((edgeCard as MonoBehaviour).GetComponent <Collider>() as BoxCollider).size.x + _cardPadding); } (movedCard as MonoBehaviour).transform.localPosition = newPosition; _carouselCards.Insert(positiveEdge, movedCard); _carouselCards.RemoveAt(negativeEdge); } if (null != dli) { return; } CenterCardIndex = _carouselCards.FindIndex(x => (x as MonoBehaviour).transform == newCenterTarget); }