/** Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}. */ public static float mapCoordInSelfToDescendent(View descendant, View root, int[] coord) { ArrayList<View> ancestorChain = new ArrayList<View>(); float[] pt = {coord[0], coord[1]}; View v = descendant; while (v != root) { ancestorChain.add(v); v = (View) v.getParent(); } ancestorChain.add(root); float scale = 1.0f; Matrix inverse = new Matrix(); int count = ancestorChain.size(); for (int i = count - 1; i >= 0; i--) { View ancestor = ancestorChain.get(i); View next = i > 0 ? ancestorChain.get(i - 1) : null; pt[0] += ancestor.getScrollX(); pt[1] += ancestor.getScrollY(); if (next != null) { pt[0] -= next.getLeft(); pt[1] -= next.getTop(); next.getMatrix().invert(inverse); inverse.mapPoints(pt); scale *= next.getScaleX(); } } coord[0] = (int) Math.round(pt[0]); coord[1] = (int) Math.round(pt[1]); return scale; }
/** * Given a coordinate relative to the descendant, find the coordinate in a parent view's * coordinates. * * @param descendant The descendant to which the passed coordinate is relative. * @param root The root view to make the coordinates relative to. * @param coord The coordinate that we want mapped. * @param includeRootScroll Whether or not to account for the scroll of the descendant: sometimes * this is relevant as in a child's coordinates within the descendant. * @return The factor by which this descendant is scaled relative to this DragLayer. Caution this * scale factor is assumed to be equal in X and Y, and so if at any point this assumption * fails, we will need to return a pair of scale factors. */ public static float getDescendantCoordRelativeToParent( View descendant, View root, int[] coord, boolean includeRootScroll) { ArrayList<View> ancestorChain = new ArrayList<View>(); float[] pt = {coord[0], coord[1]}; View v = descendant; while (v != root && v != null) { ancestorChain.add(v); v = (View) v.getParent(); } ancestorChain.add(root); float scale = 1.0f; int count = ancestorChain.size(); for (int i = 0; i < count; i++) { View v0 = ancestorChain.get(i); // For TextViews, scroll has a meaning which relates to the text position // which is very strange... ignore the scroll. if (v0 != descendant || includeRootScroll) { pt[0] -= v0.getScrollX(); pt[1] -= v0.getScrollY(); } v0.getMatrix().mapPoints(pt); pt[0] += v0.getLeft(); pt[1] += v0.getTop(); scale *= v0.getScaleX(); } coord[0] = (int) Math.round(pt[0]); coord[1] = (int) Math.round(pt[1]); return scale; }
@Override public boolean tryCaptureView(View child, int pointerId) { // 如果数据List为空,或者子View不可见,则不予处理 if (child == bottomLayout || dataList == null || dataList.size() == 0 || child.getVisibility() != View.VISIBLE || child.getScaleX() <= 1.0f - SCALE_STEP) { // 一般来讲,如果拖动的是第三层、或者第四层的View,则直接禁止 // 此处用getScale的用法来巧妙回避 return false; } if (btnLock) { return false; } // 只捕获顶部view(rotation=0) int childIndex = viewList.indexOf(child); if (childIndex > 0) { return false; } return true; }
public static int[] getCenterDeltaInScreenSpace(View v0, View v1, int[] delta) { v0.getLocationInWindow(sLoc0); v1.getLocationInWindow(sLoc1); sLoc0[0] += (v0.getMeasuredWidth() * v0.getScaleX()) / 2; sLoc0[1] += (v0.getMeasuredHeight() * v0.getScaleY()) / 2; sLoc1[0] += (v1.getMeasuredWidth() * v1.getScaleX()) / 2; sLoc1[1] += (v1.getMeasuredHeight() * v1.getScaleY()) / 2; if (delta == null) { delta = new int[2]; } delta[0] = sLoc1[0] - sLoc0[0]; delta[1] = sLoc1[1] - sLoc0[1]; return delta; }
/** * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's * coordinates. * * @param descendant The descendant to which the passed coordinate is relative. * @param coord The coordinate that we want mapped. * @return The factor by which this descendant is scaled relative to this DragLayer. Caution this * scale factor is assumed to be equal in X and Y, and so if at any point this assumption * fails, we will need to return a pair of scale factors. */ public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) { float scale = 1.0f; float[] pt = {coord[0], coord[1]}; descendant.getMatrix().mapPoints(pt); scale *= descendant.getScaleX(); pt[0] += descendant.getLeft(); pt[1] += descendant.getTop(); ViewParent viewParent = descendant.getParent(); while (viewParent instanceof View && viewParent != this) { final View view = (View) viewParent; view.getMatrix().mapPoints(pt); scale *= view.getScaleX(); pt[0] += view.getLeft() - view.getScrollX(); pt[1] += view.getTop() - view.getScrollY(); viewParent = view.getParent(); } coord[0] = (int) Math.round(pt[0]); coord[1] = (int) Math.round(pt[1]); return scale; }
/** * Snapshot a view into a Bitmap with the indicated background color. * * @param view The target {@link android.view.View}. * @param backgroundColor The background color of the Bitmap. If the view has transparency areas, * these areas will be erased using this color. * @return Returns a Bitmap containing the view content, or {@code null} if any error occurs. Make * sure to call {@link android.graphics.Bitmap#recycle()} as soon as possible, once its * content is not needed anymore. */ public Bitmap snapshotView(View view, int backgroundColor) { if (view == null) { return null; } int viewWidth = view.getRight() - view.getLeft(); int viewHeight = view.getBottom() - view.getTop(); int sampleWidth = viewWidth / mSampleSize; int sampleHeight = viewHeight / mSampleSize; float canvasScale = 1.f / mSampleSize; sampleWidth = sampleWidth > 0 ? sampleWidth : 1; sampleHeight = sampleHeight > 0 ? sampleHeight : 1; performanceTickBegin( "snapshotView " + view + " sampleSize = " + mSampleSize + " (" + sampleWidth + ", " + sampleHeight + "): "); Bitmap bitmap = Bitmap.createBitmap(sampleWidth, sampleHeight, Bitmap.Config.ARGB_8888); if (bitmap == null) { throw new OutOfMemoryError(); } if ((backgroundColor & 0xff000000) != 0) { bitmap.eraseColor(backgroundColor); } bitmap.setDensity(mDisplayMetrics.densityDpi); Canvas canvas = new Canvas(bitmap); canvas.scale(view.getScaleX() * canvasScale, view.getScaleY() * canvasScale); canvas.translate(-view.getScrollX(), -view.getScrollY()); view.computeScroll(); view.draw(canvas); canvas.setBitmap(null); performanceTickEnd(); return bitmap; }
public static boolean isChildInCenterX(RecyclerView recyclerView, View view) { int childCount = recyclerView.getChildCount(); int[] lvLocationOnScreen = new int[2]; int[] vLocationOnScreen = new int[2]; recyclerView.getLocationOnScreen(lvLocationOnScreen); int middleX = (int) (lvLocationOnScreen[0] + recyclerView.getWidth() * recyclerView.getScaleX() / 2); if (childCount > 0) { view.getLocationOnScreen(vLocationOnScreen); if (vLocationOnScreen[0] <= middleX && vLocationOnScreen[0] + view.getWidth() * view.getScaleX() >= middleX) { return true; } } return false; }
public static boolean isItemAtPoint(View view, float x, float y) { return (view.getLeft() < x) && (view.getLeft() + view.getWidth() * view.getScaleX() > x) && (view.getTop() < y) && (view.getTop() + view.getHeight() * view.getScaleY() > y); }
public void animateViewIntoPosition( DragView dragView, final View child, int duration, final Runnable onFinishAnimationRunnable, View anchorView) { ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent(); CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); parentChildren.measureChild(child); Rect r = new Rect(); getViewRectRelativeToSelf(dragView, r); int coord[] = new int[2]; float childScale = child.getScaleX(); coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2); coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2); // Since the child hasn't necessarily been laid out, we force the lp to be updated with // the correct coordinates (above) and use these to determine the final location float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord); // We need to account for the scale of the child itself, as the above only accounts for // for the scale in parents. scale *= childScale; int toX = coord[0]; int toY = coord[1]; if (child instanceof TextView) { TextView tv = (TextView) child; // The child may be scaled (always about the center of the view) so to account for it, // we have to offset the position by the scaled size. Once we do that, we can center // the drag view about the scaled child view. toY += Math.round(scale * tv.getPaddingTop()); toY -= dragView.getMeasuredHeight() * (1 - scale) / 2; toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; } else if (child instanceof FolderIcon) { // Account for holographic blur padding on the drag view toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2; toY -= (1 - scale) * dragView.getMeasuredHeight() / 2; // Center in the x coordinate about the target's drawable toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; } else { toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2; toX -= (Math.round(scale * (dragView.getMeasuredWidth() - child.getMeasuredWidth()))) / 2; } final int fromX = r.left; final int fromY = r.top; child.setVisibility(INVISIBLE); Runnable onCompleteRunnable = new Runnable() { public void run() { child.setVisibility(VISIBLE); if (onFinishAnimationRunnable != null) { onFinishAnimationRunnable.run(); } } }; animateViewIntoPosition( dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale, onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView); }
public static float getScaleX(View view) { return view.getScaleX(); }
public static float g(View paramView) { return paramView.getScaleX(); }
@Override public float getScaleX(View view) { return view.getScaleX(); }