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 18 package com.android.launcher2; 19 20 import android.animation.ValueAnimator; 21 import android.animation.ValueAnimator.AnimatorUpdateListener; 22 import android.content.res.Resources; 23 import android.graphics.Bitmap; 24 import android.graphics.Canvas; 25 import android.graphics.Matrix; 26 import android.graphics.Paint; 27 import android.graphics.Point; 28 import android.graphics.Rect; 29 import android.view.View; 30 import android.view.animation.DecelerateInterpolator; 31 32 import com.android.launcher.R; 33 34 public class DragView extends View { 35 private Bitmap mBitmap; 36 private Paint mPaint; 37 private int mRegistrationX; 38 private int mRegistrationY; 39 40 private Point mDragVisualizeOffset = null; 41 private Rect mDragRegion = null; 42 private DragLayer mDragLayer = null; 43 private boolean mHasDrawn = false; 44 45 ValueAnimator mAnim; 46 private float mOffsetX = 0.0f; 47 private float mOffsetY = 0.0f; 48 49 private DragLayer.LayoutParams mLayoutParams; 50 51 /** 52 * Construct the drag view. 53 * <p> 54 * The registration point is the point inside our view that the touch events should 55 * be centered upon. 56 * 57 * @param launcher The Launcher instance 58 * @param bitmap The view that we're dragging around. We scale it up when we draw it. 59 * @param registrationX The x coordinate of the registration point. 60 * @param registrationY The y coordinate of the registration point. 61 */ 62 public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY, 63 int left, int top, int width, int height) { 64 super(launcher); 65 mDragLayer = launcher.getDragLayer(); 66 67 final Resources res = getResources(); 68 final int dragScale = res.getInteger(R.integer.config_dragViewExtraPixels); 69 70 Matrix scale = new Matrix(); 71 final float scaleFactor = (width + dragScale) / width; 72 if (scaleFactor != 1.0f) { 73 scale.setScale(scaleFactor, scaleFactor); 74 } 75 76 final int offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX); 77 final int offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY); 78 79 // Animate the view into the correct position 80 mAnim = ValueAnimator.ofFloat(0.0f, 1.0f); 81 mAnim.setDuration(110); 82 mAnim.setInterpolator(new DecelerateInterpolator(2.5f)); 83 mAnim.addUpdateListener(new AnimatorUpdateListener() { 84 @Override 85 public void onAnimationUpdate(ValueAnimator animation) { 86 final float value = (Float) animation.getAnimatedValue(); 87 88 final int deltaX = (int) ((value * offsetX) - mOffsetX); 89 final int deltaY = (int) ((value * offsetY) - mOffsetY); 90 91 mOffsetX += deltaX; 92 mOffsetY += deltaY; 93 94 if (getParent() == null) { 95 animation.cancel(); 96 } else { 97 DragLayer.LayoutParams lp = mLayoutParams; 98 lp.x += deltaX; 99 lp.y += deltaY; 100 mDragLayer.requestLayout(); 101 } 102 } 103 }); 104 105 mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true); 106 setDragRegion(new Rect(0, 0, width, height)); 107 108 // The point in our scaled bitmap that the touch events are located 109 mRegistrationX = registrationX; 110 mRegistrationY = registrationY; 111 112 // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass 113 int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 114 measure(ms, ms); 115 } 116 117 public float getOffsetY() { 118 return mOffsetY; 119 } 120 121 public int getDragRegionLeft() { 122 return mDragRegion.left; 123 } 124 125 public int getDragRegionTop() { 126 return mDragRegion.top; 127 } 128 129 public int getDragRegionWidth() { 130 return mDragRegion.width(); 131 } 132 133 public int getDragRegionHeight() { 134 return mDragRegion.height(); 135 } 136 137 public void setDragVisualizeOffset(Point p) { 138 mDragVisualizeOffset = p; 139 } 140 141 public Point getDragVisualizeOffset() { 142 return mDragVisualizeOffset; 143 } 144 145 public void setDragRegion(Rect r) { 146 mDragRegion = r; 147 } 148 149 public Rect getDragRegion() { 150 return mDragRegion; 151 } 152 153 @Override 154 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 155 setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); 156 } 157 158 @Override 159 protected void onDraw(Canvas canvas) { 160 if (false) { 161 // for debugging 162 Paint p = new Paint(); 163 p.setStyle(Paint.Style.FILL); 164 p.setColor(0xaaffffff); 165 canvas.drawRect(0, 0, getWidth(), getHeight(), p); 166 } 167 168 mHasDrawn = true; 169 canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint); 170 } 171 172 public void setPaint(Paint paint) { 173 mPaint = paint; 174 invalidate(); 175 } 176 177 public boolean hasDrawn() { 178 return mHasDrawn; 179 } 180 181 @Override 182 public void setAlpha(float alpha) { 183 super.setAlpha(alpha); 184 if (mPaint == null) { 185 mPaint = new Paint(); 186 } 187 mPaint.setAlpha((int) (255 * alpha)); 188 invalidate(); 189 } 190 191 /** 192 * Create a window containing this view and show it. 193 * 194 * @param windowToken obtained from v.getWindowToken() from one of your views 195 * @param touchX the x coordinate the user touched in DragLayer coordinates 196 * @param touchY the y coordinate the user touched in DragLayer coordinates 197 */ 198 public void show(int touchX, int touchY) { 199 mDragLayer.addView(this); 200 DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0); 201 lp.width = mBitmap.getWidth(); 202 lp.height = mBitmap.getHeight(); 203 lp.x = touchX - mRegistrationX; 204 lp.y = touchY - mRegistrationY; 205 lp.customPosition = true; 206 setLayoutParams(lp); 207 mLayoutParams = lp; 208 mAnim.start(); 209 } 210 211 /** 212 * Move the window containing this view. 213 * 214 * @param touchX the x coordinate the user touched in DragLayer coordinates 215 * @param touchY the y coordinate the user touched in DragLayer coordinates 216 */ 217 void move(int touchX, int touchY) { 218 DragLayer.LayoutParams lp = mLayoutParams; 219 lp.x = touchX - mRegistrationX + (int) mOffsetX; 220 lp.y = touchY - mRegistrationY + (int) mOffsetY; 221 mDragLayer.requestLayout(); 222 } 223 224 void remove() { 225 post(new Runnable() { 226 public void run() { 227 mDragLayer.removeView(DragView.this); 228 } 229 }); 230 } 231 232 int[] getPosition(int[] result) { 233 DragLayer.LayoutParams lp = mLayoutParams; 234 if (result == null) result = new int[2]; 235 result[0] = lp.x; 236 result[1] = lp.y; 237 return result; 238 } 239 } 240 241