/** * Measure specification mode: The parent has not imposed any constraint * on the child. It can be whatever size it wants. */ publicstaticfinalintUNSPECIFIED=0 << MODE_SHIFT;
/** * Measure specification mode: The parent has determined an exact size * for the child. The child is going to be given those bounds regardless * of how big it wants to be. */ publicstaticfinalintEXACTLY=1 << MODE_SHIFT;
/** * Measure specification mode: The child can be as large as it wants up * to the specified size. */ publicstaticfinalintAT_MOST=2 << MODE_SHIFT;
/** * Extracts the mode from the supplied measure specification. * * @param measureSpec the measure specification to extract the mode from * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, * {@link android.view.View.MeasureSpec#AT_MOST} or * {@link android.view.View.MeasureSpec#EXACTLY} */ @MeasureSpecMode publicstaticintgetMode(int measureSpec) { //noinspection ResourceType return (measureSpec & MODE_MASK); }
/** * Extracts the size from the supplied measure specification. * * @param measureSpec the measure specification to extract the size from * @return the size in pixels defined in the supplied measure specification */ publicstaticintgetSize(int measureSpec) { return (measureSpec & ~MODE_MASK); } ... ... }
privatestaticintgetRootMeasureSpec(int windowSize, int rootDimension) { int measureSpec; switch (rootDimension){ case ViewGroup.LayoutParams.MATCH_PARENT: // Window can't resize. Force root view to be windowSize. mesureSpec = MeasureSpec.makeMeasureSpec(windowSize,MeasureSpec.EXACTLY); break; case ViewGroup.LayoutParams.WRAP_CONTENT: // Window can resize. Set max size for root view. measureSpec = MeasureSpec.makeMeasureSpec(windowSize,MeasureSpec.AT_MOST); break; default: // Window wants to be an exact size. Force root view to be that size. measureSpec = MeasureSpec.makeMeasureSpec(rootDimension,MeasureSpec.EXACTLY); break; } return measureSpec; }
/** * Ask one of the children of this view to measure itself, taking into * account both the MeasureSpec requirements for this view and its padding * and margins. The child must have MarginLayoutParams The heavy lifting is * done in getChildMeasureSpec. * * @param child The child to measure * @param parentWidthMeasureSpec The width requirements for this view * @param widthUsed Extra space that has been used up by the parent * horizontally (possibly by other children of the parent) * @param parentHeightMeasureSpec The height requirements for this view * @param heightUsed Extra space that has been used up by the parent * vertically (possibly by other children of the parent) */ protectedvoidmeasureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { finalMarginLayoutParamslp= (MarginLayoutParams) child.getLayoutParams();
/** * Does the hard part of measureChildren: figuring out the MeasureSpec to * pass to a particular child. This method figures out the right MeasureSpec * for one dimension (height or width) of one child view. * * The goal is to combine information from our MeasureSpec with the * LayoutParams of the child to get the best possible results. For example, * if the this view knows its size (because its MeasureSpec has a mode of * EXACTLY), and the child has indicated in its LayoutParams that it wants * to be the same size as the parent, the parent should ask the child to * layout given an exact size. * * @param spec The requirements for this view * @param padding The padding of this view for the current dimension and * margins, if applicable (父容器中已占用的空间大小) * @param childDimension How big the child wants to be in the current * dimension * @return a MeasureSpec integer for the child */ publicstaticintgetChildMeasureSpec(int spec, int padding, int childDimension) { intspecMode= MeasureSpec.getMode(spec); intspecSize= MeasureSpec.getSize(spec);
switch (specMode) { // Parent has imposed an exact size on us case MeasureSpec.EXACTLY: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent has imposed a maximum size on us case MeasureSpec.AT_MOST: if (childDimension >= 0) { // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } elseif (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } elseif (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break; } //noinspection ResourceType return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
<!-- Base "touch slop" value used by ViewConfiguration as a movement threshold where scrolling should begin .--> <dimenname ="config_viewConfigurationTouchSlop">8dp</dimen>
/** * Set the scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * * @param x the x position to scroll to * @param y the y position to scroll to */ publicvoidscrollTo(int x, int y) { if (mScrollX != x || mScrollY != y) { intoldX= mScrollX; intoldY= mScrollY; mScrollX = x; mScrollY = y; invalidateParentCaches(); onScrollChanged(mScrollX, mScrollY, oldX, oldY); if (!awakenScrollBars()) { postInvalidateOnAnimation(); } } }
/** * Move the scrolled position of your view. This will cause a call to * {@link #onScrollChanged(int, int, int, int)} and the view will be * invalidated. * * @param x the amount of pixels to scroll by horizontally * @param y the amount of pixels to scroll by vertically */ publicvoidscrollBy(int x, int y) { scrollTo(mScrollX + x, mScrollY + y); }
/** * Start scrolling by providing a starting point, the distance to travel, * and the duration of the scroll. * * @param startX Starting horizontal scroll offset in pixels. Positive * numbers will scroll the content to the left. * @param startY Starting vertical scroll offset in pixels. Positive numbers * will scroll the content up. * @param dx Horizontal distance to travel. Positive numbers will scroll the * content to the left. * @param dy Vertical distance to travel. Positive numbers will scroll the * content up. * @param duration Duration of the scroll in milliseconds. */ public void startScroll(int startX, int startY, int dx, int dy, int duration) { mMode = SCROLL_MODE; mFinished = false; mDuration = duration; mStartTime = AnimationUtils.currentAnimationTimeMillis(); mStartX = startX; mStartY = startY; mFinalX = startX + dx; mFinalY = startY + dy; mDeltaX = dx; mDeltaY = dy; mDurationReciprocal = 1.0f / (float) mDuration; }
/** * Call this when you want to know the new location. If it returns true, * the animation is not yet finished. */ publicbooleancomputeScrollOffset() { ... inttimePassed= (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
switch (event.getAction()){ case MotionEvent.ACTION_DOWN:{ parent.requestDisallowInterceptTouchEvent(true); break; } case MotionEvent.ACTION_MOVE:{ intdeltaX= x - mLastX; intdeltaY= y - mLastY; if(父容器需要此类点击事件){ parent.requestDisallowInterceptTouchEvent(false) }
break; } case MotionEvent.ACTION_UP:{ break; } default: break;