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.content.res.TypedArray; 22import android.graphics.Bitmap; 23import android.graphics.Canvas; 24import android.graphics.Matrix; 25import android.graphics.Paint; 26import android.graphics.PixelFormat; 27import android.graphics.Point; 28import android.os.IBinder; 29import android.util.AttributeSet; 30import android.util.Log; 31import android.view.Gravity; 32import android.view.View; 33import android.view.ViewGroup; 34import android.view.KeyEvent; 35import android.view.WindowManager; 36import android.view.WindowManagerImpl; 37 38public class DragView extends View implements TweenCallback { 39 // Number of pixels to add to the dragged item for scaling. Should be even for pixel alignment. 40 private static final int DRAG_SCALE = 40; 41 42 private Bitmap mBitmap; 43 private Paint mPaint; 44 private int mRegistrationX; 45 private int mRegistrationY; 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 80 // The point in our scaled bitmap that the touch events are located 81 mRegistrationX = registrationX + (DRAG_SCALE / 2); 82 mRegistrationY = registrationY + (DRAG_SCALE / 2); 83 } 84 85 @Override 86 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 87 setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); 88 } 89 90 @Override 91 protected void onDraw(Canvas canvas) { 92 if (false) { 93 // for debugging 94 Paint p = new Paint(); 95 p.setStyle(Paint.Style.FILL); 96 p.setColor(0xaaffffff); 97 canvas.drawRect(0, 0, getWidth(), getHeight(), p); 98 } 99 float scale = mAnimationScale; 100 if (scale < 0.999f) { // allow for some float error 101 float width = mBitmap.getWidth(); 102 float offset = (width-(width*scale))/2; 103 canvas.translate(offset, offset); 104 canvas.scale(scale, scale); 105 } 106 canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint); 107 } 108 109 @Override 110 protected void onDetachedFromWindow() { 111 super.onDetachedFromWindow(); 112 mBitmap.recycle(); 113 } 114 115 public void onTweenValueChanged(float value, float oldValue) { 116 mAnimationScale = (1.0f+((mScale-1.0f)*value))/mScale; 117 invalidate(); 118 } 119 120 public void onTweenStarted() { 121 } 122 123 public void onTweenFinished() { 124 } 125 126 public void setPaint(Paint paint) { 127 mPaint = paint; 128 invalidate(); 129 } 130 131 /** 132 * Create a window containing this view and show it. 133 * 134 * @param windowToken obtained from v.getWindowToken() from one of your views 135 * @param touchX the x coordinate the user touched in screen coordinates 136 * @param touchY the y coordinate the user touched in screen coordinates 137 */ 138 public void show(IBinder windowToken, int touchX, int touchY) { 139 WindowManager.LayoutParams lp; 140 int pixelFormat; 141 142 pixelFormat = PixelFormat.TRANSLUCENT; 143 144 lp = new WindowManager.LayoutParams( 145 ViewGroup.LayoutParams.WRAP_CONTENT, 146 ViewGroup.LayoutParams.WRAP_CONTENT, 147 touchX-mRegistrationX, touchY-mRegistrationY, 148 WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, 149 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 150 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 151 /*| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM*/, 152 pixelFormat); 153// lp.token = mStatusBarView.getWindowToken(); 154 lp.gravity = Gravity.LEFT | Gravity.TOP; 155 lp.token = windowToken; 156 lp.setTitle("DragView"); 157 mLayoutParams = lp; 158 159 mWindowManager.addView(this, lp); 160 161 mAnimationScale = 1.0f/mScale; 162 mTween.start(true); 163 } 164 165 /** 166 * Move the window containing this view. 167 * 168 * @param touchX the x coordinate the user touched in screen coordinates 169 * @param touchY the y coordinate the user touched in screen coordinates 170 */ 171 void move(int touchX, int touchY) { 172 WindowManager.LayoutParams lp = mLayoutParams; 173 lp.x = touchX - mRegistrationX; 174 lp.y = touchY - mRegistrationY; 175 mWindowManager.updateViewLayout(this, lp); 176 } 177 178 void remove() { 179 mWindowManager.removeView(this); 180 } 181} 182 183