Android_launcher的源码详细分析
http://www.cnblogs.com/playing/archive/2011/04/22/2024980.html

/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.android.launcher;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.Paint;import android.graphics.PorterDuffColorFilter;源码import android.graphics.PorterDuff;import android.os.Vibrator;import android.os.SystemClock;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.KeyEvent;import android.widget.FrameLayout;/** * A ViewGroup that coordinated dragging across its dscendants */public class DragLayer extends FrameLayout implements DragController {    private static final int SCROLL_DELAY = 600;    private static final int SCROLL_ZONE = 20;    private static final int VIBRATE_DURATION = 35;    private static final int ANIMATION_SCALE_UP_DURATION = 110;    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;    // Number of pixels to add to the dragged item for scaling    private static final float DRAG_SCALE = 24.0f;    private boolean mDragging = false;    private boolean mShouldDrop;    private float mLastMotionX;    private float mLastMotionY;        /**     * The bitmap that is currently being dragged     */    private Bitmap mDragBitmap = null;    private View mOriginator;    private int mBitmapOffsetX;    private int mBitmapOffsetY;    /**     * X offset from where we touched on the cell to its upper-left corner     */    private float mTouchOffsetX;        /**     * Y offset from where we touched on the cell to its upper-left corner     */    private float mTouchOffsetY;        /**     * Utility rectangle     */    private Rect mDragRect = new Rect();        /**     * Where the drag originated     */    private DragSource mDragSource;        /**     * The data associated with the object being dragged     */    private Object mDragInfo;    private final Rect mRect = new Rect();        private final int[] mDropCoordinates = new int[2];    private final Vibrator mVibrator = new Vibrator();        private DragListener mListener;    private DragScroller mDragScroller;        private static final int SCROLL_OUTSIDE_ZONE = 0;    private static final int SCROLL_WAITING_IN_ZONE = 1;    private static final int SCROLL_LEFT = 0;    private static final int SCROLL_RIGHT = 1;        private int mScrollState = SCROLL_OUTSIDE_ZONE;    private ScrollRunnable mScrollRunnable = new ScrollRunnable();    private View mIgnoredDropTarget;    private RectF mDragRegion;    private boolean mEnteredRegion;    private DropTarget mLastDropTarget;    private final Paint mTrashPaint = new Paint();    private Paint mDragPaint;    private static final int ANIMATION_STATE_STARTING = 1;    private static final int ANIMATION_STATE_RUNNING = 2;    private static final int ANIMATION_STATE_DONE = 3;    private static final int ANIMATION_TYPE_SCALE = 1;    private float mAnimationFrom;    private float mAnimationTo;    private int mAnimationDuration;    private long mAnimationStartTime;    private int mAnimationType;    private int mAnimationState = ANIMATION_STATE_DONE;    /**     * Used to create a new DragLayer from XML.     *     * @param context The application's context.     * @param attrs The attribtues set containing the Workspace's customization values.     */    public DragLayer(Context context, AttributeSet attrs) {        super(context, attrs);        final int srcColor = context.getResources().getColor(R.color.delete_color_filter);        mTrashPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));    }    public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) {        if (PROFILE_DRAWING_DURING_DRAG) {            android.os.Debug.startMethodTracing("Launcher");        }                if (mListener != null) {            mListener.onDragStart(v, source, dragInfo, dragAction);        }        Rect r = mDragRect;        r.set(v.getScrollX(), v.getScrollY(), 0, 0);        offsetDescendantRectToMyCoords(v, r);        mTouchOffsetX = mLastMotionX - r.left;        mTouchOffsetY = mLastMotionY - r.top;        v.clearFocus();        v.setPressed(false);        boolean willNotCache = v.willNotCacheDrawing();        v.setWillNotCacheDrawing(false);        v.buildDrawingCache();        Bitmap viewBitmap = v.getDrawingCache();        int width = viewBitmap.getWidth();        int height = viewBitmap.getHeight();        Matrix scale = new Matrix();        float scaleFactor = v.getWidth();        scaleFactor = (scaleFactor + DRAG_SCALE) /scaleFactor;        scale.setScale(scaleFactor, scaleFactor);        mAnimationTo = 1.0f;        mAnimationFrom = 1.0f / scaleFactor;        mAnimationDuration = ANIMATION_SCALE_UP_DURATION;        mAnimationState = ANIMATION_STATE_STARTING;        mAnimationType = ANIMATION_TYPE_SCALE;        mDragBitmap = Bitmap.createBitmap(viewBitmap, 0, 0, width, height, scale, true);        v.destroyDrawingCache();        v.setWillNotCacheDrawing(willNotCache);        final Bitmap dragBitmap = mDragBitmap;        mBitmapOffsetX = (dragBitmap.getWidth() - width) / 2;        mBitmapOffsetY = (dragBitmap.getHeight() - height) / 2;        if (dragAction == DRAG_ACTION_MOVE) {            v.setVisibility(GONE);        }        mDragPaint = null;        mDragging = true;        mShouldDrop = true;        mOriginator = v;        mDragSource = source;        mDragInfo = dragInfo;        mVibrator.vibrate(VIBRATE_DURATION);        mEnteredRegion = false;        invalidate();    }    @Override    public boolean dispatchKeyEvent(KeyEvent event) {        return mDragging || super.dispatchKeyEvent(event);    }    @Override    protected void dispatchDraw(Canvas canvas) {        super.dispatchDraw(canvas);        if (mDragging && mDragBitmap != null) {            if (mAnimationState == ANIMATION_STATE_STARTING) {                mAnimationStartTime = SystemClock.uptimeMillis();                mAnimationState = ANIMATION_STATE_RUNNING;            }            if (mAnimationState == ANIMATION_STATE_RUNNING) {                float normalized = (float) (SystemClock.uptimeMillis() - mAnimationStartTime) /                        mAnimationDuration;                if (normalized >= 1.0f) {                    mAnimationState = ANIMATION_STATE_DONE;                }                normalized = Math.min(normalized, 1.0f);                final float value = mAnimationFrom  + (mAnimationTo - mAnimationFrom) * normalized;                switch (mAnimationType) {                    case ANIMATION_TYPE_SCALE:                        final Bitmap dragBitmap = mDragBitmap;                        canvas.save();                        canvas.translate(mScrollX + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,                                mScrollY + mLastMotionY - mTouchOffsetY - mBitmapOffsetY);                        canvas.translate((dragBitmap.getWidth() * (1.0f - value)) / 2,                                (dragBitmap.getHeight() * (1.0f - value)) / 2);                        canvas.scale(value, value);                        canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint);                        canvas.restore();                        break;                }            } else {                canvas.drawBitmap(mDragBitmap,                        mScrollX + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,                        mScrollY + mLastMotionY - mTouchOffsetY - mBitmapOffsetY, mDragPaint);            }        }    }    private void endDrag() {        if (mDragging) {            mDragging = false;            if (mDragBitmap != null) {                mDragBitmap.recycle();            }            if (mOriginator != null) {                mOriginator.setVisibility(VISIBLE);            }            if (mListener != null) {                mListener.onDragEnd();            }        }    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        final int action = ev.getAction();        final float x = ev.getX();        final float y = ev.getY();        switch (action) {            case MotionEvent.ACTION_MOVE:                break;            case MotionEvent.ACTION_DOWN:                // Remember location of down touch                mLastMotionX = x;                mLastMotionY = y;                mLastDropTarget = null;                break;            case MotionEvent.ACTION_CANCEL:            case MotionEvent.ACTION_UP:                if (mShouldDrop && drop(x, y)) {                    mShouldDrop = false;                }                endDrag();                break;        }        return mDragging;    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        if (!mDragging) {            return false;        }        final int action = ev.getAction();        final float x = ev.getX();        final float y = ev.getY();        switch (action) {        case MotionEvent.ACTION_DOWN:            // Remember where the motion event started            mLastMotionX = x;            mLastMotionY = y;            if ((x < SCROLL_ZONE) || (x > getWidth() - SCROLL_ZONE)) {                mScrollState = SCROLL_WAITING_IN_ZONE;                postDelayed(mScrollRunnable, SCROLL_DELAY);            } else {                mScrollState = SCROLL_OUTSIDE_ZONE;            }            break;        case MotionEvent.ACTION_MOVE:            if (Launcher.sOpenGlEnabled) {                mLastMotionX = x;                mLastMotionY = y;                invalidate();            } else {                final int scrollX = mScrollX;                final int scrollY = mScrollY;                final float touchX = mTouchOffsetX;                final float touchY = mTouchOffsetY;                final int offsetX = mBitmapOffsetX;                final int offsetY = mBitmapOffsetY;                int left = (int) (scrollX + mLastMotionX - touchX - offsetX);                int top = (int) (scrollY + mLastMotionY - touchY - offsetY);                final Bitmap dragBitmap = mDragBitmap;                final int width = dragBitmap.getWidth();                final int height = dragBitmap.getHeight();                final Rect rect = mRect;                rect.set(left - 1, top - 1, left + width + 1, top + height + 1);                mLastMotionX = x;                mLastMotionY = y;                left = (int) (scrollX + x - touchX - offsetX);                top = (int) (scrollY + y - touchY - offsetY);                rect.union(left - 1, top - 1, left + width + 1, top + height + 1);                invalidate(rect);            }            final int[] coordinates = mDropCoordinates;            DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);            if (dropTarget != null) {                if (mLastDropTarget == dropTarget) {                    dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);                } else {                    if (mLastDropTarget != null) {                        mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],                            (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);                    }                    dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1],                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);                }            } else {                if (mLastDropTarget != null) {                    mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);                }            }            mLastDropTarget = dropTarget;            boolean inDragRegion = false;            if (mDragRegion != null) {                final RectF region = mDragRegion;                final boolean inRegion = region.contains(ev.getRawX(), ev.getRawY());                if (!mEnteredRegion && inRegion) {                    mDragPaint = mTrashPaint;                    mEnteredRegion = true;                    inDragRegion = true;                } else if (mEnteredRegion && !inRegion) {                    mDragPaint = null;                    mEnteredRegion = false;                }            }            if (!inDragRegion && x < SCROLL_ZONE) {                if (mScrollState == SCROLL_OUTSIDE_ZONE) {                    mScrollState = SCROLL_WAITING_IN_ZONE;                    mScrollRunnable.setDirection(SCROLL_LEFT);                    postDelayed(mScrollRunnable, SCROLL_DELAY);                }            } else if (!inDragRegion && x > getWidth() - SCROLL_ZONE) {                if (mScrollState == SCROLL_OUTSIDE_ZONE) {                    mScrollState = SCROLL_WAITING_IN_ZONE;                    mScrollRunnable.setDirection(SCROLL_RIGHT);                    postDelayed(mScrollRunnable, SCROLL_DELAY);                }            } else {                if (mScrollState == SCROLL_WAITING_IN_ZONE) {                    mScrollState = SCROLL_OUTSIDE_ZONE;                    mScrollRunnable.setDirection(SCROLL_RIGHT);                    removeCallbacks(mScrollRunnable);                }            }            break;        case MotionEvent.ACTION_UP:            removeCallbacks(mScrollRunnable);            if (mShouldDrop) {                drop(x, y);                mShouldDrop = false;            }            endDrag();            break;        case MotionEvent.ACTION_CANCEL:            endDrag();        }        return true;    }    private boolean drop(float x, float y) {        invalidate();        final int[] coordinates = mDropCoordinates;        DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);        if (dropTarget != null) {            dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);            if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1],                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo)) {                dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);                mDragSource.onDropCompleted((View) dropTarget, true);                return true;            } else {                mDragSource.onDropCompleted((View) dropTarget, false);                return true;            }        }        return false;    }    DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {        return findDropTarget(this, x, y, dropCoordinates);    }    private DropTarget findDropTarget(ViewGroup container, int x, int y, int[] dropCoordinates) {        final Rect r = mDragRect;        final int count = container.getChildCount();        final int scrolledX = x + container.getScrollX();        final int scrolledY = y + container.getScrollY();        final View ignoredDropTarget = mIgnoredDropTarget;        for (int i = count - 1; i >= 0; i--) {            final View child = container.getChildAt(i);            if (child.getVisibility() == VISIBLE && child != ignoredDropTarget) {                child.getHitRect(r);                if (r.contains(scrolledX, scrolledY)) {                    DropTarget target = null;                    if (child instanceof ViewGroup) {                        x = scrolledX - child.getLeft();                        y = scrolledY - child.getTop();                        target = findDropTarget((ViewGroup) child, x, y, dropCoordinates);                    }                    if (target == null) {                        if (child instanceof DropTarget) {                            dropCoordinates[0] = x;                            dropCoordinates[1] = y;                            return (DropTarget) child;                        }                    } else {                        return target;                    }                }            }        }        return null;    }    public void setDragScoller(DragScroller scroller) {        mDragScroller = scroller;    }    public void setDragListener(DragListener l) {        mListener = l;    }    public void removeDragListener(DragListener l) {        mListener = null;       }    /**     * Specifies the view that must be ignored when looking for a drop target.     *     * @param view The view that will not be taken into account while looking     *        for a drop target.     */    void setIgnoredDropTarget(View view) {        mIgnoredDropTarget = view;    }    /**     * Specifies the delete region.     *     * @param region The rectangle in screen coordinates of the delete region.     */    void setDeleteRegion(RectF region) {        mDragRegion = region;    }    private class ScrollRunnable implements Runnable {        private int mDirection;        ScrollRunnable() {        }        public void run() {            if (mDragScroller != null) {                if (mDirection == SCROLL_LEFT) {                    mDragScroller.scrollLeft();                } else {                    mDragScroller.scrollRight();                }                mScrollState = SCROLL_OUTSIDE_ZONE;            }        }        void setDirection(int direction) {            mDirection = direction;        }    }    }

更多相关文章

  1. android DragLayer源码
  2. Android(安卓)Scroller类介绍
  3. Android应用程序绑定服务(bindService)的过程源代码分析(3)
  4. Android应用程序组件Content Provider的启动过程源代码分析(3)
  5. Android应用程序组件Content Provider的启动过程源代码分析(5)
  6. ANDROID PAD版本 PHONE版本 源码有什么 区别?
  7. android 9.0 startService启动Servcie的过程分析
  8. Android(安卓)SparseArray源码阅读
  9. Adnroid LearningNotes

随机推荐

  1. # bluedroid stack巧谈
  2. SurfaceView应用浅析
  3. 动态绘制图形的基本思路
  4. Android(安卓)HTTP网络通信(一):使用HttpURL
  5. Google I/O 2014 - Keynote for Android
  6. Android(安卓)View 的工作原理(包含对 Dec
  7. ScrollView 嵌套 RecyclerVeiw, 轻松解决
  8. Android(安卓)Studio打包全攻略---从入门
  9. 我的第一个应用程序:如何逐步创建第一个An
  10. Qt on Android:图文详解QT开发Andriod入门