DragView.java revision a63c452f5bd491ba9b28c332ccedc6c6c7e2f3cc
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package com.android.launcher2;
19
20import android.content.Context;
21import android.graphics.Bitmap;
22import android.graphics.Canvas;
23import android.graphics.Matrix;
24import android.graphics.Paint;
25import android.graphics.PixelFormat;
26import android.os.IBinder;
27import android.view.Gravity;
28import android.view.View;
29import android.view.ViewGroup;
30import android.view.WindowManager;
31import android.view.WindowManagerImpl;
32
33public class DragView extends View implements TweenCallback {
34    // Number of pixels to add to the dragged item for scaling.  Should be even for pixel alignment.
35    private static final int DRAG_SCALE = 40;
36
37    private Bitmap mBitmap;
38    private Paint mPaint;
39    private int mRegistrationX;
40    private int mRegistrationY;
41
42    private int mDragRegionLeft = 0;
43    private int mDragRegionTop = 0;
44    private int mDragRegionWidth;
45    private int mDragRegionHeight;
46
47    SymmetricalLinearTween mTween;
48    private float mScale;
49    private float mAnimationScale = 1.0f;
50
51    private WindowManager.LayoutParams mLayoutParams;
52    private WindowManager mWindowManager;
53
54    /**
55     * Construct the drag view.
56     * <p>
57     * The registration point is the point inside our view that the touch events should
58     * be centered upon.
59     *
60     * @param context A context
61     * @param bitmap The view that we're dragging around.  We scale it up when we draw it.
62     * @param registrationX The x coordinate of the registration point.
63     * @param registrationY The y coordinate of the registration point.
64     */
65    public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY,
66            int left, int top, int width, int height) {
67        super(context);
68
69        mWindowManager = WindowManagerImpl.getDefault();
70
71        mTween = new SymmetricalLinearTween(false, 110 /*ms duration*/, this);
72
73        Matrix scale = new Matrix();
74        float scaleFactor = width;
75        scaleFactor = mScale = (scaleFactor + DRAG_SCALE) / scaleFactor;
76        scale.setScale(scaleFactor, scaleFactor);
77
78        mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
79        mDragRegionWidth = width;
80        mDragRegionHeight = height;
81
82        // The point in our scaled bitmap that the touch events are located
83        mRegistrationX = registrationX + (DRAG_SCALE / 2);
84        mRegistrationY = registrationY + (DRAG_SCALE / 2);
85    }
86
87    public void setDragRegion(int left, int top, int width, int height) {
88        mDragRegionLeft = left;
89        mDragRegionTop = top;
90        mDragRegionWidth = width;
91        mDragRegionHeight = height;
92    }
93
94    public int getDragRegionLeft() {
95        return mDragRegionLeft;
96    }
97
98    public int getDragRegionTop() {
99        return mDragRegionTop;
100    }
101
102    public int getDragRegionWidth() {
103        return mDragRegionWidth;
104    }
105
106    public int getDragRegionHeight() {
107        return mDragRegionHeight;
108    }
109
110    @Override
111    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
112        setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight());
113    }
114
115    @Override
116    protected void onDraw(Canvas canvas) {
117        if (false) {
118            // for debugging
119            Paint p = new Paint();
120            p.setStyle(Paint.Style.FILL);
121            p.setColor(0xaaffffff);
122            canvas.drawRect(0, 0, getWidth(), getHeight(), p);
123        }
124        float scale = mAnimationScale;
125        if (scale < 0.999f) { // allow for some float error
126            float width = mBitmap.getWidth();
127            float offset = (width-(width*scale))/2;
128            canvas.translate(offset, offset);
129            canvas.scale(scale, scale);
130        }
131        canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
132    }
133
134    @Override
135    protected void onDetachedFromWindow() {
136        super.onDetachedFromWindow();
137        mBitmap.recycle();
138    }
139
140    public void onTweenValueChanged(float value, float oldValue) {
141        mAnimationScale = (1.0f+((mScale-1.0f)*value))/mScale;
142        invalidate();
143    }
144
145    public void onTweenStarted() {
146    }
147
148    public void onTweenFinished() {
149    }
150
151    public void setPaint(Paint paint) {
152        mPaint = paint;
153        invalidate();
154    }
155
156    /**
157     * Create a window containing this view and show it.
158     *
159     * @param windowToken obtained from v.getWindowToken() from one of your views
160     * @param touchX the x coordinate the user touched in screen coordinates
161     * @param touchY the y coordinate the user touched in screen coordinates
162     */
163    public void show(IBinder windowToken, int touchX, int touchY) {
164        WindowManager.LayoutParams lp;
165        int pixelFormat;
166
167        pixelFormat = PixelFormat.TRANSLUCENT;
168
169        lp = new WindowManager.LayoutParams(
170                ViewGroup.LayoutParams.WRAP_CONTENT,
171                ViewGroup.LayoutParams.WRAP_CONTENT,
172                touchX-mRegistrationX, touchY-mRegistrationY,
173                WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
174                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
175                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
176                    /*| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM*/,
177                pixelFormat);
178//        lp.token = mStatusBarView.getWindowToken();
179        lp.gravity = Gravity.LEFT | Gravity.TOP;
180        lp.token = windowToken;
181        lp.setTitle("DragView");
182        mLayoutParams = lp;
183
184        mWindowManager.addView(this, lp);
185
186        mAnimationScale = 1.0f/mScale;
187        mTween.start(true);
188    }
189
190    /**
191     * Move the window containing this view.
192     *
193     * @param touchX the x coordinate the user touched in screen coordinates
194     * @param touchY the y coordinate the user touched in screen coordinates
195     */
196    void move(int touchX, int touchY) {
197        WindowManager.LayoutParams lp = mLayoutParams;
198        lp.x = touchX - mRegistrationX;
199        lp.y = touchY - mRegistrationY;
200        mWindowManager.updateViewLayout(this, lp);
201    }
202
203    void remove() {
204        mWindowManager.removeView(this);
205    }
206}
207
208