/** * Handle a MOVE event while sliding. * * @param y the y-position of the MOVE event in absolute screen coordinates. */ /* package */ void updateWhileSliding(int y) { int totalSlideAmount = y - mTouchDownY; // if (DBG) log("--------------> MOTION! y = " + y // + " (total slide = " + totalSlideAmount + ")"); // TODO: consider caching popupTopPosY and popupBottomPosY in // startSliding (to save a couple of method calls each time here.) // TODO: this block is duplicated above; use a single helper method instead. mMainFrame.getLocationInWindow(mTempLocation); final int mainFrameX = mTempLocation[0]; final int mainFrameY = 0; // mTempLocation[1]; // In the "top" position the CallCard is aligned exactly with the // top edge of the main frame. final int popupTopPosY = mainFrameY; // And in the "bottom" position, the bottom of the CallCard is // aligned exactly with the bottom of the main frame. final int popupBottomPosY = mainFrameY + mMainFrame.getHeight() - height; // Forcibly reposition the CallCard int newCardTop = mCardPreferredY + totalSlideAmount; // if (DBG) log(" ==> New card top: " + newCardTop); // But never slide *beyond* the topmost or bottom-most position: if (newCardTop < popupTopPosY) newCardTop = popupTopPosY; else if (newCardTop > popupBottomPosY) newCardTop = popupBottomPosY; // Forcibly reposition the PopupWindow. mCallCard.update(mCardPreferredX, newCardTop, -1, -1); }
/** * Bail out of an in-progress slide *without* activating whatever action the slide was supposed to * trigger. */ private void abortSlide() { if (DBG) log("abortSlide()..."); mSlideInProgress = false; // This slide had no effect. Nothing about the state of the // UI has changed, so no need to updateCardPreferredPosition() or // updateCardSlideHints(). But we *do* need to reposition the // PopupWindow back in its correct position. // TODO: smoothly animate back to the preferred position. mCallCard.update(mCardPreferredX, mCardPreferredY, -1, -1); }
/** * Initializes the internal state of the SlidingCardManager. * * @param phone the Phone app's Phone instance * @param inCallScreen the InCallScreen activity * @param mainFrame the InCallScreen's main frame containing the in-call UI elements */ /* package */ public void init(Phone phone, InCallScreen inCallScreen, ViewGroup mainFrame) { if (DBG) log("init()..."); mPhone = phone; mInCallScreen = inCallScreen; mMainFrame = mainFrame; // Slide hints mSlideUp = (ViewGroup) mInCallScreen.findViewById(R.id.slideUp); mSlideUpHint = (TextView) mInCallScreen.findViewById(R.id.slideUpHint); mSlideDown = (ViewGroup) mInCallScreen.findViewById(R.id.slideDown); mSlideDownHint = (TextView) mInCallScreen.findViewById(R.id.slideDownHint); mCallCard = (CallCard) mMainFrame.findViewById(R.id.callCard); mCallCard.setSlidingCardManager(this); }
/** * Update the "permanent" position (ie. the actual layout params) of the sliding card based on the * current call state. * * <p>This method sets mCardAtTop, mCallEndedState, mCardPreferredX, and mCardPreferredY. It also * repositions the PopupWindow if it's showing. * * <p>Note that *while sliding* we manually reposition the card on every motion event that comes * in. The x/y position we set here determines where the card should be while *not* sliding. * * <p>TODO: If the card position changes for some reason *other* than user action (i.e. as a * result of an onPhoneStateChanged() callback), we should smoothly animate the position change! * (For example, if you're in a call and the other end hangs up, the card should switch to "Call * ended" mode and smoothly animate to the bottom position.) */ public /* package */ void updateCardPreferredPosition() { if (DBG) log("updateCardPreferredPosition()..."); // if (DBG) log("- card's LayoutParams: " + mCallCard.getLayoutParams()); // Bail out if our View hierarchy isn't attached to a Window yet // (since the mMainFrame.getLocationOnScreen() call below // will fail.) if (mMainFrame.getWindowToken() == null) { if (DBG) log("updateCardPreferredPosition: View hierarchy unattached; bailing..."); return; } /* if (mMainFrame.getHeight() == 0) { // The code here needs to know the sizes and positions of some // views in the mMainFrame view hierarchy, so you're only // allowed to call this method *after* the whole in-call UI // has been measured and laid out. // (This is why we defer calling showPopup() until an // onGlobalLayout() call comes in.) throw new IllegalStateException( "updateCardPreferredPosition: main frame not measured yet"); } */ // Given the current state of the Phone and the UI, decide whether // the card should be at the TOP or BOTTOM of the screen right now. // Compute the possible coordinates onscreen for the popup. // TODO: this block is duplicated below; use a single helper method instead. mMainFrame.getLocationInWindow(mTempLocation); final int mainFrameX = mTempLocation[0]; final int mainFrameY = 0; // mTempLocation[1]; if (DBG) log("- mMainFrame loc in window: " + mainFrameX + ", " + mainFrameY); // In the "top" position the CallCard is aligned exactly with the // top edge of the main frame. final int popupTopPosY = mainFrameY; // And in the "bottom" position, the bottom of the CallCard is // aligned exactly with the bottom of the main frame. if (height == 0) { height = mCallCard.getHeight(); // Reposition the "slide hints". RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mSlideUp.getLayoutParams(); // Equivalent to setting android:layout_marginTop in XML lp.bottomMargin = height; mSlideUp.setLayoutParams(lp); lp = (RelativeLayout.LayoutParams) mSlideDown.getLayoutParams(); // Equivalent to setting android:layout_marginTop in XML lp.topMargin = height; mSlideDown.setLayoutParams(lp); height += 10; } final int popupBottomPosY = mainFrameY + mMainFrame.getHeight() - height; if (Receiver.ccCall != null && Receiver.ccCall.getState() != Call.State.DISCONNECTED) { // When the phone is in use, the position of the card is // determined solely by whether an incoming call is ringing or // not. final boolean hasRingingCall = Receiver.ccCall.getState() == Call.State.INCOMING; mCardAtTop = !hasRingingCall; mCallEndedState = false; } else { // Phone is completely idle! Display the CALL ENDED state // with the card at the bottom of the screen. mCardAtTop = false; mCallEndedState = true; } mCardPreferredX = mainFrameX; mCardPreferredY = mCardAtTop ? popupTopPosY : popupBottomPosY; if (DBG) log( "==> Setting card preferred position (mCardAtTop = " + mCardAtTop + ") to: " + mCardPreferredX + ", " + mCardPreferredY); // This is a no-op if the PopupWindow isn't showing. mCallCard.update(mCardPreferredX, mCardPreferredY, -1, -1); }