private void toggleMovableResize() { if (mMovableAnimationRunning) return; mMovableAnimationRunning = true; setCollapseButtonImage(!mMovableVisible); float startValue; float endValue; if (mMovableVisible) { startValue = 0.0f; endValue = -mMovableLayout.getHeight(); mMovableVisible = false; } else { startValue = -mMovableLayout.getHeight(); endValue = 0.0f; mMovableVisible = true; } ObjectAnimator anim = ObjectAnimator.ofFloat(mMovableLayout, "translationY", startValue, endValue); anim.setInterpolator(SMOOTH_INTERPOLATOR); anim.setDuration(MOVABLE_ANIMATION_DURATION); anim.addListener(mMovableAnimatorListener); anim.start(); }
/** 滚动发生时调用 */ @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); /** * 距离qq差别 :1.qq内容区域实现了一个缩放的效果 2.菜单的偏移量一直在变化 3.菜单也存在缩放和透明度的变化 实现1.需要将 0.7 ~ 1.0 (0.7 + 0.3 * * scale) 实现2.修改菜单的其实隐藏跨度 实现3.菜单透明度变化0.6 ~ 1.0 ( 0.6 + 0.4 *(1-scale))+缩放:0.7~1.0(1.0 - * scale*0.3) */ // l是当前SrocllX值 float scale = l * 1.0f / mMenuWidth; Log.i("SlidingMenu:onScrollChanged", "" + scale); // 调用属性动画 设置TranslationX 修改菜单的其实隐藏跨度,其实隐藏60% ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.6f); // 实现内容区域缩小 float contextScale = 0.7f + 0.3f * scale; // 设置缩放的中心点 设置内容区域缩放值 ViewHelper.setPivotX(mContent, 0); ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); ViewHelper.setScaleX(mContent, contextScale); ViewHelper.setScaleY(mContent, contextScale); // 实现菜单区域缩放 float menuScale = 1.0f - scale * 0.3f; // 实现菜单透明度变化 float menuAlpha = 0.6f + 0.4f * (1 - scale); // 调用属性动画实现 ViewHelper.setScaleX(mMenu, menuScale); ViewHelper.setScaleY(mMenu, menuScale); ViewHelper.setAlpha(mMenu, menuAlpha); }
/** * Place the TextView into the specified container. * * @param container The container in which to place the TextView. */ public void place(PortableContainer container) { ViewGroup parent = (ViewGroup) container.getPlatformContainer(); _textView = new TextView(parent.getContext()); container.add(_textView); _textView.setWidth(parent.getWidth()); _textView.setWidth(parent.getHeight()); }
@Override public void run() { final float centerX = vgContainer.getWidth() / 2.0f; final float centerY = vgContainer.getHeight() / 2.0f; Rotate3dAnimation rotation = null; AnimationSet animationSet = null; if (mPosition > -1) { vFront.setVisibility(View.GONE); vBack.setVisibility(View.VISIBLE); vBack.requestFocus(); rotation = new Rotate3dAnimation(-90, 0, centerX, centerY, 310.0f, false, axis); animationSet = new AnimationSet(true); animationSet.addAnimation(largerAnimation); animationSet.addAnimation(rotation); } else { vFront.setVisibility(View.VISIBLE); vBack.setVisibility(View.GONE); vFront.requestFocus(); rotation = new Rotate3dAnimation(90, 0, centerX, centerY, 310.0f, false, axis); animationSet = new AnimationSet(true); animationSet.addAnimation(rotation); } rotation.setDuration(500); rotation.setFillAfter(true); // 动画插入器 减速 rotation.setInterpolator(new DecelerateInterpolator()); vgContainer.startAnimation(animationSet); }
/** * 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); }
public View getView(int position, View convertView, ViewGroup parent) { // Log.d(TAG, "drawing offer # " + position + " of " // + mImageDrawables.length); ImageView i = new ImageView(mContext); // position = getPosition(position); i.setImageDrawable(mImageDrawables[position]); // i.setImageBitmap(mImageBitmaps[position]); // i.setImageResource(R.drawable.aase); int height = parent.getHeight(); i.setLayoutParams(new Gallery.LayoutParams(height, height)); i.setScaleType(ImageView.ScaleType.FIT_XY); i.setPadding(20, 20, 20, 20); // i.setBackgroundColor(R.color.actionbar_background_light); RelativeLayout rl = new RelativeLayout(mContext); rl.setPadding(10, 10, 10, 10); // TextView captionNotification= new TextView(mContext); // captionNotification.setText("This is user "+position); // captionNotification.setTextSize(30); // LinearLayout l = new LinearLayout(mContext); // l.setOrientation(LinearLayout.VERTICAL); // l.addView(i); // l.addView(captionNotification); // return i; rl.addView(i); return rl; }
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); int w = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight(); int h = parent.getHeight(); RelativeLayout itemlayout = (RelativeLayout) mInflater.inflate(R.layout.item_weather_weekly, parent, false); LayoutParams params = new LayoutParams(w / 5, LayoutParams.MATCH_PARENT); itemlayout.setLayoutParams(params); int wt = itemlayout.getMeasuredWidth(); holder.layout = (RelativeLayout) itemlayout.findViewById(R.id.week_item_rl); holder.textWeek = (TextView) itemlayout.findViewById(R.id.week_item_week); holder.textDate = (TextView) itemlayout.findViewById(R.id.week_item_date); holder.textNongli = (TextView) itemlayout.findViewById(R.id.week_item_nongli); holder.imgWeather = (ImageView) itemlayout.findViewById(R.id.weather_icon); holder.textTemperature = (TextView) itemlayout.findViewById(R.id.week_item_temperature); holder.textWeather = (TextView) itemlayout.findViewById(R.id.week_item_weather); convertView = itemlayout; convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } if (position < info.size()) { WeatherInfo weatherInfo = info.get(position); if (position == 0) holder.textWeek.setText(mContext.getString(R.string.today)); else holder.textWeek.setText( String.format(mContext.getString(R.string.week), weatherInfo.getWeek())); holder.textDate.setText(weatherInfo.getDate()); holder.textNongli.setText(weatherInfo.getNongli()); holder.textTemperature.setText( String.format(mContext.getString(R.string.temperature), weatherInfo.getTemperatureLow()) + "/" + String.format( mContext.getString(R.string.temperature), weatherInfo.getTemperatureHight())); // holder.textWeather.setText(w.weather); int length = weatherInfo.getWeather().length(); if (length > 15 && length <= 18) { holder.textWeather.setTextSize(12); } else if (length > 18 && length <= 21) { holder.textWeather.setTextSize(11); } else if (length > 21) { holder.textWeather.setTextSize(9); } holder.textWeather.setText(weatherInfo.getWeather()); holder.imgWeather.setImageDrawable( mContext.getResources().getDrawable(getDrawableID(weatherInfo.getWeatherID()))); } return convertView; }
/** * Opens the floating toolbar overflow. This method should not be called if menu items have not * been laid out with {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, * int)}. * * @throws IllegalStateException if called when menu items have not been laid out. */ private void closeOverflow() { Preconditions.checkState(mMainPanel != null); Preconditions.checkState(mOverflowPanel != null); mOverflowPanel.fadeOut(true); Size mainPanelSize = mMainPanel.measure(); final int targetWidth = mainPanelSize.getWidth(); final int targetHeight = mainPanelSize.getHeight(); final int startWidth = mContentContainer.getWidth(); final int startHeight = mContentContainer.getHeight(); final float right = mContentContainer.getX() + mContentContainer.getWidth(); final float bottom = mContentContainer.getY() + mContentContainer.getHeight(); final boolean morphedUpwards = (mOverflowDirection == OVERFLOW_DIRECTION_UP); Animation widthAnimation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); int deltaWidth = (int) (interpolatedTime * (targetWidth - startWidth)); params.width = startWidth + deltaWidth; mContentContainer.setLayoutParams(params); mContentContainer.setX(right - mContentContainer.getWidth()); } }; Animation heightAnimation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { ViewGroup.LayoutParams params = mContentContainer.getLayoutParams(); int deltaHeight = (int) (interpolatedTime * (targetHeight - startHeight)); params.height = startHeight + deltaHeight; mContentContainer.setLayoutParams(params); if (morphedUpwards) { mContentContainer.setY(bottom - mContentContainer.getHeight()); } } }; widthAnimation.setDuration(150); widthAnimation.setStartOffset(150); heightAnimation.setDuration(210); mCloseOverflowAnimation.getAnimations().clear(); mCloseOverflowAnimation.setAnimationListener(mOnOverflowClosed); mCloseOverflowAnimation.addAnimation(widthAnimation); mCloseOverflowAnimation.addAnimation(heightAnimation); mContentContainer.startAnimation(mCloseOverflowAnimation); }
private float getTargetHideValue(ViewGroup parent, View target) { if (target instanceof AppBarLayout) { return -target.getHeight(); } else if (target instanceof FloatingActionButton) { return parent.getHeight() - target.getTop(); } return 0f; }
private Animation buildFlipHorizonalAnimation(final boolean forward) { final float centerY = container.getHeight() / 2.0f; final float centerX = 0; long duration = getFlipDurationFromPreference(); Animation rotation = AnimationFactory.buildHorizontalFlipAnimation(forward, duration, centerX, centerY); rotation.setAnimationListener(flipAnimationListener); return rotation; }
@Override public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { mContentHolder.getLocationOnScreen(mTmpTwoArray); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.touchableRegion.set( mTmpTwoArray[0], mTmpTwoArray[1], mTmpTwoArray[0] + mContentHolder.getWidth(), mTmpTwoArray[1] + mContentHolder.getHeight()); }
private void reveal(View sourceView, int colorRes, final AnimatorListener listener) { // Make reveal cover the display final RevealView revealView = new RevealView(this); revealView.setLayoutParams(mLayoutParams); revealView.setRevealColor(getResources().getColor(colorRes)); mDisplayForeground.addView(revealView); final SupportAnimator revealAnimator; final int[] clearLocation = new int[2]; if (sourceView != null) { sourceView.getLocationInWindow(clearLocation); clearLocation[0] += sourceView.getWidth() / 2; clearLocation[1] += sourceView.getHeight() / 2; } else { clearLocation[0] = mDisplayForeground.getWidth() / 2; clearLocation[1] = mDisplayForeground.getHeight() / 2; } final int revealCenterX = clearLocation[0] - revealView.getLeft(); final int revealCenterY = clearLocation[1] - revealView.getTop(); final double x1_2 = Math.pow(revealView.getLeft() - revealCenterX, 2); final double x2_2 = Math.pow(revealView.getRight() - revealCenterX, 2); final double y_2 = Math.pow(revealView.getTop() - revealCenterY, 2); final float revealRadius = (float) Math.max(Math.sqrt(x1_2 + y_2), Math.sqrt(x2_2 + y_2)); revealAnimator = ViewAnimationUtils.createCircularReveal( revealView, revealCenterX, revealCenterY, 0.0f, revealRadius); revealAnimator.setDuration(getResources().getInteger(android.R.integer.config_longAnimTime)); revealAnimator.addListener(listener); final Animator alphaAnimator = ObjectAnimator.ofFloat(revealView, View.ALPHA, 0.0f); alphaAnimator.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime)); alphaAnimator.addListener( new AnimationFinishedListener() { @Override public void onAnimationFinished() { mDisplayForeground.removeView(revealView); } }); revealAnimator.addListener( new AnimationFinishedListener() { @Override public void onAnimationFinished() { play(alphaAnimator); } }); play(revealAnimator); }
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // We want the list to fill up the entire container. // FIXME This does not yet work perfectly. When you first show this View, the ListView does not fill the container. if (mList.getHeight() != getHeight()) { mList.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, getHeight())); mNeedScroll = true; } if (mContainer.getHeight() != (getHeight() + mHeaderContainer.getHeight())) { mContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, getHeight() + mHeaderContainer.getHeight())); mNeedScroll = true; } }
public void updateInfo() { ViewGroup parent = (ViewGroup) mAnchor; for (HighLight.ViewPosInfo viewPosInfo : mViewRects) { RectF rect = new RectF(ViewUtils.getLocationInView(parent, viewPosInfo.view)); // if (!rect.equals(viewPosInfo.rectF))//TODO bug dismissed...fc... { viewPosInfo.rectF = rect; viewPosInfo.onPosCallback.getPos( parent.getWidth() - rect.right, parent.getHeight() - rect.bottom, rect, viewPosInfo.marginInfo); } } }
/** * Setup a new 3D rotation on the container view. * * @param position the item that was clicked to show a picture, or -1 to show the list * @param start the start angle at which the rotation must begin * @param end the end angle of the rotation */ private void applyRotation(int position, float start, float end) { // Find the center of the container final float centerX = mContainer.getWidth() / 2.0f; final float centerY = mContainer.getHeight() / 2.0f; // Create a new 3D rotation with the supplied parameter // The animation listener is used to trigger the next animation final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true); rotation.setDuration(500); rotation.setFillAfter(true); rotation.setInterpolator(new AccelerateInterpolator()); rotation.setAnimationListener(new DisplayNextView(position)); mContainer.startAnimation(rotation); }
private void invalidateDividersForScrollingView( ViewGroup view, final boolean setForTop, boolean setForBottom, boolean hasButtons) { if (setForTop && view.getChildCount() > 0) { mDrawTopDivider = mTitleBar != null && mTitleBar.getVisibility() != View.GONE && // Not scrolled to the top. view.getScrollY() + view.getPaddingTop() > view.getChildAt(0).getTop(); } if (setForBottom && view.getChildCount() > 0) { mDrawBottomDivider = hasButtons && view.getScrollY() + view.getHeight() - view.getPaddingBottom() < view.getChildAt(view.getChildCount() - 1).getBottom(); } }
/** Stop sliding the card. Called when we get an UP touch event while sliding. */ /* package */ void stopSliding(int y) { int totalSlideAmount = y - mTouchDownY; if (DBG) log("stopSliding: Total slide delta: " + totalSlideAmount); // When not sliding, the card is pegged to either the very top // or very bottom of the in-call main frame. // So the precise slide amount that *should* be required to "complete // the slide" is the amount of vertical space in the in-call frame NOT // taken up by the CallCard: int slideDistanceRequired = mMainFrame.getHeight() - height; // if (DBG) log(" -> main frame height: " + mMainFrame.getHeight()); // if (DBG) log(" -> PopupWindow height: " + mPopup.getHeight()); // if (DBG) log(" -> DIFFERENCE = " + slideDistanceRequired); // But fudge slideDistanceRequired a little, in case you slid // "just far enough" but the card jittered a bit when you let go. slideDistanceRequired -= 30; // Modify totalSlideAmount so that a positive value means "a slide // in the correct direction". (Thus if the card started at the // bottom of the screen, meaning that the user needs to slide // *up*, we need to flip the sign of totalSlideAmount.) if (!mCardAtTop) totalSlideAmount = -totalSlideAmount; if (totalSlideAmount >= slideDistanceRequired) { if (DBG) log( "==> Slide was far enough! slid " + totalSlideAmount + ", needed >= " + slideDistanceRequired); finishSuccessfulSlide(); } else { if (DBG) log( "==> Didn't slide enough to take action: slid " + totalSlideAmount + ", needed >= " + slideDistanceRequired); abortSlide(); } }
public HighLight addHighLight(View view, int decorLayoutId, OnPosCallback onPosCallback) { ViewGroup parent = (ViewGroup) mAnchor; RectF rect = new RectF(ViewUtils.getLocationInView(parent, view)); ViewPosInfo viewPosInfo = new ViewPosInfo(); viewPosInfo.layoutId = decorLayoutId; viewPosInfo.rectF = rect; viewPosInfo.view = view; if (onPosCallback == null && decorLayoutId != -1) { throw new IllegalArgumentException("onPosCallback can not be null."); } MarginInfo marginInfo = new MarginInfo(); onPosCallback.getPos( parent.getWidth() - rect.right, parent.getHeight() - rect.bottom, rect, marginInfo); viewPosInfo.marginInfo = marginInfo; viewPosInfo.onPosCallback = onPosCallback; mViewRects.add(viewPosInfo); return this; }
/** * 应用旋转动画 * * @param position * @param start * @param end * @param ivFront * @param ivBack * @param container * @param axis */ private void applyRotation( int position, int start, int end, ImageView ivFront, ImageView ivBack, ViewGroup container, String axis) { final float centerX = container.getWidth() / 2.0f; final float centerY = container.getHeight() / 2.0f; final Rotate3dAnimation rotate3dAnimation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true, Rotate3dAnimation.Y); rotate3dAnimation.setDuration(100); rotate3dAnimation.setFillAfter(true); // 动画插入器,加速 rotate3dAnimation.setInterpolator(new AccelerateInterpolator()); rotate3dAnimation.setAnimationListener( new DisplayNextView(position, ivFront, ivBack, container, axis)); container.startAnimation(rotate3dAnimation); }
@SuppressLint("NewApi") private static void actionStarActivity( final int finishType, final Activity thisActivity, final Intent intent, final Integer requestCode, final Bundle bundle, final View triggerView, int colorOrImageRes, long durationMills) { // 版本判断,小于5.0则无动画. if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) { startActivityOrFinish(finishType, thisActivity, intent, requestCode, bundle); return; } int[] location = new int[2]; triggerView.getLocationInWindow(location); final int cx = location[0] + triggerView.getWidth() / 2; final int cy = location[1] + triggerView.getHeight() / 2; final ImageView view = new ImageView(thisActivity); view.setScaleType(ImageView.ScaleType.CENTER_CROP); view.setImageResource(colorOrImageRes); final ViewGroup decorView = (ViewGroup) thisActivity.getWindow().getDecorView(); int w = decorView.getWidth(); int h = decorView.getHeight(); decorView.addView(view, w, h); // 计算中心点至view边界的最大距离 int maxW = Math.max(cx, w - cx); int maxH = Math.max(cy, h - cy); final int finalRadius = (int) Math.sqrt(maxW * maxW + maxH * maxH) + 1; Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius); int maxRadius = (int) Math.sqrt(w * w + h * h) + 1; // 若使用默认时长,则需要根据水波扩散的距离来计算实际时间 if (durationMills == PERFECT_MILLS) { // 算出实际边距与最大边距的比率 double rate = 1d * finalRadius / maxRadius; // 为了让用户便于感触到水波,速度应随最大边距的变小而越慢,扩散时间应随最大边距的变小而变小,因此比率应在 @rate 与 1 之间。 durationMills = (long) (PERFECT_MILLS * Math.sqrt(rate)); } final long finalDuration = durationMills; // 由于thisActivity.startActivity()会有所停顿,所以进入的水波动画应比退出的水波动画时间短才能保持视觉上的一致。 anim.setDuration((long) (finalDuration * 0.9)); anim.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (requestCode == null) thisActivity.startActivity(intent); else if (bundle == null) thisActivity.startActivityForResult(intent, requestCode); else thisActivity.startActivityForResult(intent, requestCode, bundle); // 默认渐隐过渡动画. thisActivity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); switch (finishType) { case FINISH_NONE: // 默认显示返回至当前Activity的动画. triggerView.postDelayed( new Runnable() { @Override public void run() { Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, finalRadius, 0); anim.setDuration(finalDuration); anim.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); try { decorView.removeView(view); } catch (Exception e) { e.printStackTrace(); } } }); anim.start(); } }, 1000); break; case FINISH_SINGLE: // finish当前activity thisActivity.finish(); break; case FINISH_ALL: // finish目标activity外的所有activity thisActivity.finishAffinity(); break; } } }); anim.start(); }
@SuppressLint("ResourceAsColor") @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override public boolean onTouch(final View view, MotionEvent event) { if (mViewWidth < 2) { mViewWidth = mListView.getWidth(); smallWidth = mViewWidth / 7; textwidth2 = mViewWidth / 3; textwidth = textwidth2; // 原版 // largewidth = textwidth+textwidth2; // 自己修改 largewidth = textwidth; } int tempwidth = 0; if (SwipeType == 1) tempwidth = smallWidth; else tempwidth = textwidth2 / 2; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: { if (mPaused) { return false; } Rect rect = new Rect(); int childCount = mListView.getChildCount(); int[] listViewCoords = new int[2]; mListView.getLocationOnScreen(listViewCoords); int x = (int) event.getRawX() - listViewCoords[0]; int y = (int) event.getRawY() - listViewCoords[1]; ViewGroup child; for (int i = 0; i < childCount; i++) { child = (ViewGroup) mListView.getChildAt(i); child.getHitRect(rect); if (rect.contains(x, y)) { mDownView_parent = child; mDownView = (ViewGroup) child.findViewById(R.id.list_display_view_container); if (mDownView_parent.getChildCount() == 1) { textheight = mDownView_parent.getHeight(); if (SwipeType == Dismiss) { HalfColor = singleColor; // HalfDrawable = // activity.getResources().getDrawable(R.drawable.content_discard); } SetBackGroundforList(); } if (old_mDownView != null && mDownView != old_mDownView) { ResetListItem(old_mDownView); old_mDownView = null; return false; } break; } } if (mDownView != null) { mDownX = event.getRawX(); mDownY = event.getRawY(); mDownPosition = mListView.getPositionForView(mDownView); mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(event); } else { mDownView = null; } // mSwipeDetected = false; temp_position = mListView.pointToPosition((int) event.getX(), (int) event.getY()); view.onTouchEvent(event); return true; } case MotionEvent.ACTION_UP: { if (mVelocityTracker == null) { break; } float deltaX = event.getRawX() - mDownX; // 在OnItemClick事件中判断如果Deltax!=0则表示不是点击事件 DeltaX = deltaX; mVelocityTracker.addMovement(event); mVelocityTracker.computeCurrentVelocity(1000); // 1000 by defaut but float velocityX = mVelocityTracker.getXVelocity(); // it was too much float absVelocityX = Math.abs(velocityX); float absVelocityY = Math.abs(mVelocityTracker.getYVelocity()); boolean swipe = false; boolean swipeRight = false; if (Math.abs(deltaX) > tempwidth) { swipe = true; swipeRight = deltaX > 0; } else if (mMinFlingVelocity <= absVelocityX && absVelocityX <= mMaxFlingVelocity && absVelocityY < absVelocityX) { // dismiss only if flinging in the same direction as dragging swipe = (velocityX < 0) == (deltaX < 0); swipeRight = mVelocityTracker.getXVelocity() > 0; } if (deltaX < 0 && swipe) { mListView.setDrawSelectorOnTop(false); // && Math.abs(DeltaY)<30 if (swipe && !swipeRight && deltaX <= -tempwidth && Math.abs(DeltaY) < 100) { FullSwipeTrigger(); } else if (deltaX >= -textwidth && SwipeType == Double) { ResetListItem(mDownView); } else { ResetListItem(mDownView); } } else if (deltaX != 0) { ResetListItem(mDownView); } mVelocityTracker.recycle(); mVelocityTracker = null; mDownX = 0; mDownView = null; mDownPosition = ListView.INVALID_POSITION; mSwiping = false; break; } // 根据手势滑动方向滑出滑入 case MotionEvent.ACTION_MOVE: { float deltaX = event.getRawX() - mDownX; float deltaY = event.getRawY() - mDownY; DeltaY = deltaY; if (mVelocityTracker == null || mPaused || deltaX > 0) { break; } mVelocityTracker.addMovement(event); // && Math.abs(deltaY)<30 if (Math.abs(deltaX) > (mSlop * 5) && Math.abs(deltaY) < 50) { mSwiping = true; mListView.requestDisallowInterceptTouchEvent(true); // Cancel ListView's touch (un-highlighting the item) MotionEvent cancelEvent = MotionEvent.obtain(event); cancelEvent.setAction( MotionEvent.ACTION_CANCEL | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); mListView.onTouchEvent(cancelEvent); cancelEvent.recycle(); } else if (Math.abs(deltaY) > 50) { mSwiping = false; // ResetListItem(mDownView); } System.out.println( "<<<<<<<<<" + deltaY + "<<<<<<" + deltaX + "<<<<" + mSwiping + "<<<<<" + mSlop * 10); if (mSwiping && deltaX < 0) { int width; // if(SwipeType==1){ width = textwidth2; // } // else{ // width = largewidth; // } if (-deltaX < width) { mDownView.setTranslationX(deltaX); return false; } return false; } else if (mSwiping) { ResetListItem(mDownView); } break; } } return false; }
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mRemoveListener != null && mGestureDetector == null) { if (mRemoveMode == FLING) { mGestureDetector = new GestureDetector( getContext(), new SimpleOnGestureListener() { @Override public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (mFloatView != null) { if (velocityX > 1000) { Rect r = mTempRect; mFloatView.getDrawingRect(r); if (e2.getX() > r.right * 2 / 3) { // fast fling right with release near the // right edge of the screen dropFloatView(true); } } // flinging while dragging should have no effect // i.e. the gesture should not pass on to other // onTouch handlers. Gobble... return true; } return false; } }); } } if (mDragListener != null || mDropListener != null) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // Log.d("mobeta", "action down!"); int x = (int) ev.getX(); int y = (int) ev.getY(); mLastX = x; mLastY = y; mDownY = y; int itemnum = pointToPosition(x, y); // includes // headers/footers final int numHeaders = getHeaderViewsCount(); final int numFooters = getFooterViewsCount(); // Log.d("mobeta", "touch down on position " + itemnum); if (itemnum == AdapterView.INVALID_POSITION || itemnum < numHeaders || itemnum >= getCount() - numFooters) { break; } ViewGroup item = (ViewGroup) getChildAt(itemnum - getFirstVisiblePosition()); mDragPointX = x - item.getLeft(); mDragPointY = y - item.getTop(); final int rawX = (int) ev.getRawX(); final int rawY = (int) ev.getRawY(); mXOffset = rawX - x; mYOffset = rawY - y; View dragBox = (View) item.getTag(); boolean dragHit = false; if (dragBox != null) { dragBox.getLocationOnScreen(mTempLoc); dragHit = rawX > mTempLoc[0] && rawY > mTempLoc[1] && rawX < mTempLoc[0] + dragBox.getWidth() && rawY < mTempLoc[1] + dragBox.getHeight(); } if (dragHit) { // item.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH); item.setDrawingCacheEnabled(true); // Create a copy of the drawing cache so that it does // not get recycled // by the framework when the list tries to clean up // memory Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache()); item.setDrawingCacheEnabled(false); mFloatViewHeight = item.getHeight(); mFloatViewHeightHalf = mFloatViewHeight / 2; mExpDragPos = itemnum; mSrcDragPos = itemnum; // Log.d("mobeta", "getCount() = " + getCount()); // Log.d("mobeta", "headers = " + // getHeaderViewsCount()); startDragging(bitmap, x, y); // cancel ListView fling MotionEvent ev2 = MotionEvent.obtain(ev); ev2.setAction(MotionEvent.ACTION_CANCEL); super.onInterceptTouchEvent(ev2); // return false; return true; } removeFloatView(); break; } } return super.onInterceptTouchEvent(ev); }
/** Override {@link #getChildView(int, int, boolean, View, ViewGroup)} instead. */ @Override public final View getChildView( final int groupPosition, int childPosition, boolean isLastChild, View convertView, final ViewGroup parent) { final GroupInfo info = getGroupInfo(groupPosition); if (info.animating) { // If this group is animating, return the a DummyView... if (convertView instanceof DummyView == false) { convertView = new DummyView(parent.getContext()); convertView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 0)); } if (childPosition < info.firstChildPosition) { // The reason why we do this is to support the collapse // this group when the group view is not visible but the // children of this group are. When notifyDataSetChanged // is called, the ExpandableListView tries to keep the // list position the same by saving the first visible item // and jumping back to that item after the views have been // refreshed. Now the problem is, if a group has 2 items // and the first visible item is the 2nd child of the group // and this group is collapsed, then the dummy view will be // used for the group. But now the group only has 1 item // which is the dummy view, thus when the ListView is trying // to restore the scroll position, it will try to jump to // the second item of the group. But this group no longer // has a second item, so it is forced to jump to the next // group. This will cause a very ugly visual glitch. So // the way that we counteract this is by creating as many // dummy views as we need to maintain the scroll position // of the ListView after notifyDataSetChanged has been // called. convertView.getLayoutParams().height = 0; return convertView; } final ExpandableListView listView = (ExpandableListView) parent; final DummyView dummyView = (DummyView) convertView; // Clear the views that the dummy view draws. dummyView.clearViews(); // Set the style of the divider dummyView.setDivider( listView.getDivider(), parent.getMeasuredWidth(), listView.getDividerHeight()); // Make measure specs to measure child views final int measureSpecW = MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.EXACTLY); final int measureSpecH = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); int totalHeight = 0; int clipHeight = parent.getHeight(); final int len = getRealChildrenCount(groupPosition); for (int i = info.firstChildPosition; i < len; i++) { View childView = getRealChildView(groupPosition, i, (i == len - 1), null, parent); LayoutParams p = (LayoutParams) childView.getLayoutParams(); if (p == null) { p = (LayoutParams) generateDefaultLayoutParams(); childView.setLayoutParams(p); } int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = measureSpecH; } childView.measure(measureSpecW, childHeightSpec); totalHeight += childView.getMeasuredHeight(); if (totalHeight < clipHeight) { // we only need to draw enough views to fool the user... dummyView.addFakeView(childView); } else { dummyView.addFakeView(childView); // if this group has too many views, we don't want to // calculate the height of everything... just do a light // approximation and break int averageHeight = totalHeight / (i + 1); totalHeight += (len - i - 1) * averageHeight; break; } } Object o; int state = (o = dummyView.getTag()) == null ? STATE_IDLE : (Integer) o; if (info.expanding && state != STATE_EXPANDING) { ExpandAnimation ani = new ExpandAnimation(dummyView, 0, totalHeight, info); ani.setDuration(this.parent.getAnimationDuration()); ani.setAnimationListener( new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { stopAnimation(groupPosition); notifyDataSetChanged(); dummyView.setTag(STATE_IDLE); } @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationStart(Animation animation) {} }); dummyView.startAnimation(ani); dummyView.setTag(STATE_EXPANDING); } else if (!info.expanding && state != STATE_COLLAPSING) { if (info.dummyHeight == -1) { info.dummyHeight = totalHeight; } ExpandAnimation ani = new ExpandAnimation(dummyView, info.dummyHeight, 0, info); ani.setDuration(this.parent.getAnimationDuration()); ani.setAnimationListener( new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { stopAnimation(groupPosition); listView.collapseGroup(groupPosition); notifyDataSetChanged(); info.dummyHeight = -1; dummyView.setTag(STATE_IDLE); } @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationStart(Animation animation) {} }); dummyView.startAnimation(ani); dummyView.setTag(STATE_COLLAPSING); } return convertView; } else { return getRealChildView(groupPosition, childPosition, isLastChild, convertView, parent); } }
private void setMovableGone() { mMovableVisible = false; Log.d(TAG, "setMovableGone height = " + (-mMovableLayout.getHeight())); mMovableLayout.setVisibility(View.INVISIBLE); }
/** * 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); }