Merge branch 'master' into honeycomb-release
@@ -30,7 +30,7 @@ LOCAL_CERTIFICATE := shared
|
||||
|
||||
LOCAL_OVERRIDES_PACKAGES := Home
|
||||
|
||||
LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags
|
||||
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python2.5
|
||||
|
||||
import cgi
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import sqlite3
|
||||
|
||||
SCREENS = 5
|
||||
COLUMNS = 4
|
||||
ROWS = 4
|
||||
CELL_SIZE = 110
|
||||
|
||||
DIR = "db_files"
|
||||
AUTO_FILE = DIR + "/launcher.db"
|
||||
INDEX_FILE = DIR + "/index.html"
|
||||
|
||||
def usage():
|
||||
print "usage: print_db.py launcher.db -- prints a launcher.db"
|
||||
print "usage: print_db.py -- adb pulls a launcher.db from a device"
|
||||
print " and prints it"
|
||||
print
|
||||
print "The dump will be created in a directory called db_files in cwd."
|
||||
print "This script will delete any db_files directory you have now"
|
||||
|
||||
|
||||
def make_dir():
|
||||
shutil.rmtree(DIR, True)
|
||||
os.makedirs(DIR)
|
||||
|
||||
def pull_file(fn):
|
||||
print "pull_file: " + fn
|
||||
rv = os.system("adb pull"
|
||||
+ " /data/data/com.android.launcher/databases/launcher.db"
|
||||
+ " " + fn);
|
||||
if rv != 0:
|
||||
print "adb pull failed"
|
||||
sys.exit(1)
|
||||
|
||||
def get_favorites(conn):
|
||||
c = conn.cursor()
|
||||
c.execute("SELECT * FROM favorites")
|
||||
columns = [d[0] for d in c.description]
|
||||
rows = []
|
||||
for row in c:
|
||||
rows.append(row)
|
||||
return columns,rows
|
||||
|
||||
def print_intent(out, id, i, cell):
|
||||
if cell:
|
||||
out.write("""<span class="intent" title="%s">shortcut</span>""" % (
|
||||
cgi.escape(cell, True)
|
||||
))
|
||||
|
||||
|
||||
def print_icon(out, id, i, cell):
|
||||
if cell:
|
||||
icon_fn = "icon_%d.png" % id
|
||||
out.write("""<img src="%s">""" % ( icon_fn ))
|
||||
f = file(DIR + "/" + icon_fn, "w")
|
||||
f.write(cell)
|
||||
f.close()
|
||||
|
||||
def print_cell(out, id, i, cell):
|
||||
if not cell is None:
|
||||
out.write(cgi.escape(str(cell)))
|
||||
|
||||
FUNCTIONS = {
|
||||
"intent": print_intent,
|
||||
"icon": print_icon
|
||||
}
|
||||
|
||||
def process_file(fn):
|
||||
print "process_file: " + fn
|
||||
conn = sqlite3.connect(fn)
|
||||
columns,rows = get_favorites(conn)
|
||||
data = [dict(zip(columns,row)) for row in rows]
|
||||
|
||||
out = file(INDEX_FILE, "w")
|
||||
out.write("""<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
.intent {
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
""")
|
||||
|
||||
# Data table
|
||||
out.write("<b>Favorites table</b><br/>\n")
|
||||
out.write("""<html>
|
||||
<table border=1 cellspacing=0 cellpadding=4>
|
||||
<tr>
|
||||
""")
|
||||
print_functions = []
|
||||
for col in columns:
|
||||
print_functions.append(FUNCTIONS.get(col, print_cell))
|
||||
for i in range(0,len(columns)):
|
||||
col = columns[i]
|
||||
out.write(""" <th>%s</th>
|
||||
""" % ( col ))
|
||||
out.write("""
|
||||
</tr>
|
||||
""")
|
||||
for row in rows:
|
||||
out.write("""<tr>
|
||||
""")
|
||||
for i in range(0,len(row)):
|
||||
cell = row[i]
|
||||
# row[0] is always _id
|
||||
out.write(""" <td>""")
|
||||
print_functions[i](out, row[0], row, cell)
|
||||
out.write("""</td>
|
||||
""")
|
||||
out.write("""</tr>
|
||||
""")
|
||||
out.write("""</table>
|
||||
""")
|
||||
|
||||
# Pages
|
||||
screens = []
|
||||
for i in range(0,SCREENS):
|
||||
screen = []
|
||||
for j in range(0,ROWS):
|
||||
m = []
|
||||
for k in range(0,COLUMNS):
|
||||
m.append(None)
|
||||
screen.append(m)
|
||||
screens.append(screen)
|
||||
occupied = "occupied"
|
||||
for row in data:
|
||||
screen = screens[row["screen"]]
|
||||
# desktop
|
||||
if row["container"] != -100:
|
||||
continue
|
||||
cellX = row["cellX"]
|
||||
cellY = row["cellY"]
|
||||
spanX = row["spanX"]
|
||||
spanY = row["spanY"]
|
||||
for j in range(cellY, cellY+spanY):
|
||||
for k in range(cellX, cellX+spanX):
|
||||
screen[j][k] = occupied
|
||||
screen[cellY][cellX] = row
|
||||
i=0
|
||||
for screen in screens:
|
||||
out.write("<br/><b>Screen %d</b><br/>\n" % i)
|
||||
out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
|
||||
for m in screen:
|
||||
out.write(" <tr>\n")
|
||||
for cell in m:
|
||||
if cell is None:
|
||||
out.write(" <td width=%d height=%d></td>\n" %
|
||||
(CELL_SIZE, CELL_SIZE))
|
||||
elif cell == occupied:
|
||||
pass
|
||||
else:
|
||||
cellX = cell["cellX"]
|
||||
cellY = cell["cellY"]
|
||||
spanX = cell["spanX"]
|
||||
spanY = cell["spanY"]
|
||||
intent = cell["intent"]
|
||||
if intent:
|
||||
title = "title=\"%s\"" % cgi.escape(cell["intent"], True)
|
||||
else:
|
||||
title = ""
|
||||
out.write((" <td colspan=%d rowspan=%d width=%d height=%d"
|
||||
+ " bgcolor=#dddddd align=center valign=middle %s>") % (
|
||||
spanX, spanY,
|
||||
(CELL_SIZE*spanX), (CELL_SIZE*spanY),
|
||||
title))
|
||||
itemType = cell["itemType"]
|
||||
if itemType == 0:
|
||||
out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
|
||||
out.write("<br/>\n")
|
||||
out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
|
||||
elif itemType == 1:
|
||||
out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
|
||||
out.write("<br/>\n")
|
||||
out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
|
||||
elif itemType == 2:
|
||||
out.write("""<i>folder</i>""")
|
||||
elif itemType == 3:
|
||||
out.write("""<i>live folder</i>""")
|
||||
elif itemType == 4:
|
||||
out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
|
||||
elif itemType == 1000:
|
||||
out.write("""<i>clock</i>""")
|
||||
elif itemType == 1001:
|
||||
out.write("""<i>search</i>""")
|
||||
elif itemType == 1002:
|
||||
out.write("""<i>photo frame</i>""")
|
||||
else:
|
||||
out.write("<b>unknown type: %d</b>" % itemType)
|
||||
out.write("</td>\n")
|
||||
out.write("</tr>\n")
|
||||
out.write("</table>\n")
|
||||
i=i+1
|
||||
|
||||
out.write("""
|
||||
</body>
|
||||
</html>
|
||||
""")
|
||||
|
||||
out.close()
|
||||
|
||||
def main(argv):
|
||||
if len(argv) == 1:
|
||||
make_dir()
|
||||
pull_file(AUTO_FILE)
|
||||
process_file(AUTO_FILE)
|
||||
elif len(argv) == 2:
|
||||
make_dir()
|
||||
process_file(argv[1])
|
||||
else:
|
||||
usage()
|
||||
|
||||
if __name__=="__main__":
|
||||
main(sys.argv)
|
||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 620 B After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 898 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 557 B |
@@ -38,4 +38,11 @@
|
||||
the drag view should be offset from the position of the original view. -->
|
||||
<integer name="config_dragViewOffsetX">0</integer>
|
||||
<integer name="config_dragViewOffsetY">12</integer>
|
||||
|
||||
<!-- The duration (in ms) of the fade animation on the object outlines, used when
|
||||
we are dragging objects around on the home screen. -->
|
||||
<integer name="config_dragOutlineFadeTime">900</integer>
|
||||
|
||||
<!-- The alpha value at which to show the most recent drop visualization outline. -->
|
||||
<integer name="config_dragOutlineMaxAlpha">180</integer>
|
||||
</resources>
|
||||
|
||||
@@ -37,4 +37,8 @@
|
||||
|
||||
<!-- delete_zone_size_full - button_bar_height_portrait -->
|
||||
<dimen name="delete_zone_padding">14dip</dimen>
|
||||
|
||||
<!-- the area at the edge of the screen that makes the workspace go left
|
||||
or right while you're dragging. -->
|
||||
<dimen name="scroll_zone">20dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -31,18 +31,19 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LayoutAnimationController;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class CellLayout extends ViewGroup {
|
||||
public class CellLayout extends ViewGroup implements Dimmable {
|
||||
static final String TAG = "CellLayout";
|
||||
|
||||
private int mCellWidth;
|
||||
@@ -75,17 +76,27 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
private float mBackgroundAlpha;
|
||||
private final Rect mBackgroundLayoutRect = new Rect();
|
||||
|
||||
private Drawable mBackground;
|
||||
private Drawable mBackgroundHover;
|
||||
// If we're actively dragging something over this screen and it's small,
|
||||
// mHover is true
|
||||
private Drawable mBackgroundMini;
|
||||
private Drawable mBackgroundMiniHover;
|
||||
// If we're actively dragging something over this screen and it's small, mHover is true
|
||||
private boolean mHover = false;
|
||||
|
||||
private final RectF mDragRect = new RectF();
|
||||
private final Point mDragCenter = new Point();
|
||||
|
||||
private Drawable mDragRectDrawable;
|
||||
|
||||
// These arrays are used to implement the drag visualization on x-large screens.
|
||||
// They are used as circular arrays, indexed by mDragRectCurrent.
|
||||
private Rect[] mDragRects = new Rect[8];
|
||||
private int[] mDragRectAlphas = new int[mDragRects.length];
|
||||
private InterruptibleInOutAnimator[] mDragRectAnims =
|
||||
new InterruptibleInOutAnimator[mDragRects.length];
|
||||
|
||||
// Used as an index into the above 3 arrays; indicates which is the most current value.
|
||||
private int mDragRectCurrent = 0;
|
||||
|
||||
private Drawable mCrosshairsDrawable = null;
|
||||
private ValueAnimator mCrosshairsAnimator = null;
|
||||
private float mCrosshairsVisibility = 0.0f;
|
||||
@@ -137,13 +148,18 @@ public class CellLayout extends ViewGroup {
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
final Resources res = getResources();
|
||||
|
||||
mBackground = res.getDrawable(R.drawable.mini_home_screen_bg);
|
||||
mBackgroundMini = res.getDrawable(R.drawable.mini_home_screen_bg);
|
||||
mBackgroundMini.setFilterBitmap(true);
|
||||
mBackground = res.getDrawable(R.drawable.home_screen_bg);
|
||||
mBackground.setFilterBitmap(true);
|
||||
mBackgroundHover = res.getDrawable(R.drawable.mini_home_screen_bg_hover);
|
||||
mBackgroundHover.setFilterBitmap(true);
|
||||
mBackgroundMiniHover = res.getDrawable(R.drawable.mini_home_screen_bg_hover);
|
||||
mBackgroundMiniHover.setFilterBitmap(true);
|
||||
|
||||
// Initialize the data structures used for the drag visualization.
|
||||
|
||||
mDragRectDrawable = res.getDrawable(R.drawable.rounded_rect_green);
|
||||
mCrosshairsDrawable = res.getDrawable(R.drawable.gardening_crosshairs);
|
||||
Interpolator interp = new DecelerateInterpolator(2.5f); // Quint ease out
|
||||
|
||||
// Set up the animation for fading the crosshairs in and out
|
||||
int animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);
|
||||
@@ -154,6 +170,32 @@ public class CellLayout extends ViewGroup {
|
||||
CellLayout.this.invalidate();
|
||||
}
|
||||
});
|
||||
mCrosshairsAnimator.setInterpolator(interp);
|
||||
|
||||
for (int i = 0; i < mDragRects.length; i++) {
|
||||
mDragRects[i] = new Rect();
|
||||
}
|
||||
|
||||
// When dragging things around the home screens, we show a green outline of
|
||||
// where the item will land. The outlines gradually fade out, leaving a trail
|
||||
// behind the drag path.
|
||||
// Set up all the animations that are used to implement this fading.
|
||||
final int duration = res.getInteger(R.integer.config_dragOutlineFadeTime);
|
||||
final int fromAlphaValue = 0;
|
||||
final int toAlphaValue = res.getInteger(R.integer.config_dragOutlineMaxAlpha);
|
||||
for (int i = 0; i < mDragRectAnims.length; i++) {
|
||||
final InterruptibleInOutAnimator anim =
|
||||
new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
|
||||
anim.setInterpolator(interp);
|
||||
final int thisIndex = i;
|
||||
anim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mDragRectAlphas[thisIndex] = (Integer) animation.getAnimatedValue();
|
||||
CellLayout.this.invalidate(mDragRects[thisIndex]);
|
||||
}
|
||||
});
|
||||
mDragRectAnims[i] = anim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +218,14 @@ public class CellLayout extends ViewGroup {
|
||||
@Override
|
||||
public void dispatchDraw(Canvas canvas) {
|
||||
if (mBackgroundAlpha > 0.0f) {
|
||||
final Drawable bg = mHover ? mBackgroundHover : mBackground;
|
||||
Drawable bg;
|
||||
if (mHover && getScaleX() < 0.5f) {
|
||||
bg = mBackgroundMiniHover;
|
||||
} else if (getScaleX() < 0.5f) {
|
||||
bg = mBackgroundMini;
|
||||
} else {
|
||||
bg = mBackground;
|
||||
}
|
||||
bg.setAlpha((int) (mBackgroundAlpha * 255));
|
||||
bg.draw(canvas);
|
||||
}
|
||||
@@ -189,16 +238,6 @@ public class CellLayout extends ViewGroup {
|
||||
final int countX = mCountX;
|
||||
final int countY = mCountY;
|
||||
|
||||
if (!mDragRect.isEmpty()) {
|
||||
mDragRectDrawable.setBounds(
|
||||
(int)mDragRect.left,
|
||||
(int)mDragRect.top,
|
||||
(int)mDragRect.right,
|
||||
(int)mDragRect.bottom);
|
||||
mDragRectDrawable.setAlpha((int) (mCrosshairsVisibility * 255));
|
||||
mDragRectDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
final float MAX_ALPHA = 0.4f;
|
||||
final int MAX_VISIBLE_DISTANCE = 600;
|
||||
final float DISTANCE_MULTIPLIER = 0.002f;
|
||||
@@ -225,9 +264,32 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
x += mCellWidth + mWidthGap;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mDragRects.length; i++) {
|
||||
int alpha = mDragRectAlphas[i];
|
||||
if (alpha > 0) {
|
||||
mDragRectDrawable.setAlpha(alpha);
|
||||
mDragRectDrawable.setBounds(mDragRects[i]);
|
||||
mDragRectDrawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setDimmableProgress(float progress) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
Dimmable d = (Dimmable) getChildAt(i);
|
||||
d.setDimmableProgress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
public float getDimmableProgress() {
|
||||
if (getChildCount() > 0) {
|
||||
return ((Dimmable) getChildAt(0)).getDimmableProgress();
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelLongPress() {
|
||||
super.cancelLongPress();
|
||||
@@ -581,8 +643,11 @@ public class CellLayout extends ViewGroup {
|
||||
if (mBackground != null) {
|
||||
mBackground.setBounds(mBackgroundLayoutRect);
|
||||
}
|
||||
if (mBackgroundHover != null) {
|
||||
mBackgroundHover.setBounds(mBackgroundLayoutRect);
|
||||
if (mBackgroundMiniHover != null) {
|
||||
mBackgroundMiniHover.setBounds(mBackgroundLayoutRect);
|
||||
}
|
||||
if (mBackgroundMini != null) {
|
||||
mBackgroundMini.setBounds(mBackgroundLayoutRect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,13 +788,23 @@ public class CellLayout extends ViewGroup {
|
||||
final int left = topLeft[0];
|
||||
final int top = topLeft[1];
|
||||
|
||||
// Now find the bottom right
|
||||
final int[] bottomRight = mTmpPoint;
|
||||
cellToPoint(nearest[0] + spanX - 1, nearest[1] + spanY - 1, bottomRight);
|
||||
bottomRight[0] += mCellWidth;
|
||||
bottomRight[1] += mCellHeight;
|
||||
mDragRect.set(left, top, bottomRight[0], bottomRight[1]);
|
||||
invalidate();
|
||||
final Rect dragRect = mDragRects[mDragRectCurrent];
|
||||
|
||||
if (dragRect.isEmpty() || left != dragRect.left || top != dragRect.top) {
|
||||
// Now find the bottom right
|
||||
final int[] bottomRight = mTmpPoint;
|
||||
cellToPoint(nearest[0] + spanX - 1, nearest[1] + spanY - 1, bottomRight);
|
||||
bottomRight[0] += mCellWidth;
|
||||
bottomRight[1] += mCellHeight;
|
||||
|
||||
final int oldIndex = mDragRectCurrent;
|
||||
mDragRectCurrent = (oldIndex + 1) % mDragRects.length;
|
||||
|
||||
mDragRects[mDragRectCurrent].set(left, top, bottomRight[0], bottomRight[1]);
|
||||
|
||||
mDragRectAnims[oldIndex].animateOut();
|
||||
mDragRectAnims[mDragRectCurrent].animateIn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,9 +841,9 @@ public class CellLayout extends ViewGroup {
|
||||
*/
|
||||
int[] findNearestVacantArea(
|
||||
int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
|
||||
if (ignoreView != null) {
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
}
|
||||
// mark space take by ignoreView as available (method checks if ignoreView is null)
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
|
||||
// Keep track of best-scoring drop area
|
||||
final int[] bestXY = result != null ? result : new int[2];
|
||||
double bestDistance = Double.MAX_VALUE;
|
||||
@@ -802,9 +877,8 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
// re-mark space taken by ignoreView as occupied
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
|
||||
// Return null if no suitable location found
|
||||
if (bestDistance < Double.MAX_VALUE) {
|
||||
@@ -872,9 +946,8 @@ public class CellLayout extends ViewGroup {
|
||||
*/
|
||||
boolean findCellForSpanThatIntersectsIgnoring(int[] cellXY, int spanX, int spanY,
|
||||
int intersectX, int intersectY, View ignoreView) {
|
||||
if (ignoreView != null) {
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
}
|
||||
// mark space take by ignoreView as available (method checks if ignoreView is null)
|
||||
markCellsAsUnoccupiedForView(ignoreView);
|
||||
|
||||
boolean foundCell = false;
|
||||
while (true) {
|
||||
@@ -927,9 +1000,8 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreView != null) {
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
}
|
||||
// re-mark space taken by ignoreView as occupied
|
||||
markCellsAsOccupiedForView(ignoreView);
|
||||
return foundCell;
|
||||
}
|
||||
|
||||
@@ -948,6 +1020,10 @@ public class CellLayout extends ViewGroup {
|
||||
if (mCrosshairsAnimator != null) {
|
||||
animateCrosshairsTo(0.0f);
|
||||
}
|
||||
|
||||
mDragRectAnims[mDragRectCurrent].animateOut();
|
||||
mDragRectCurrent = (mDragRectCurrent + 1) % mDragRects.length;
|
||||
mDragRects[mDragRectCurrent].setEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -990,7 +1066,6 @@ public class CellLayout extends ViewGroup {
|
||||
* or it may have begun on another layout.
|
||||
*/
|
||||
void onDragEnter(View dragView) {
|
||||
mDragRect.setEmpty();
|
||||
// Fade in the drag indicators
|
||||
if (mCrosshairsAnimator != null) {
|
||||
animateCrosshairsTo(1.0f);
|
||||
@@ -1123,11 +1198,13 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
|
||||
}
|
||||
|
||||
private void markCellsAsOccupiedForView(View view) {
|
||||
if (view == null || view.getParent() != this) return;
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
|
||||
}
|
||||
|
||||
private void markCellsAsUnoccupiedForView(View view) {
|
||||
if (view == null || view.getParent() != this) return;
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.android.launcher2;
|
||||
|
||||
public interface Dimmable {
|
||||
public void setDimmableProgress(float progress);
|
||||
public float getDimmableProgress();
|
||||
}
|
||||
@@ -21,52 +21,21 @@ import com.android.launcher.R;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.View;
|
||||
|
||||
public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView {
|
||||
public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView implements Dimmable {
|
||||
public DimmableAppWidgetHostView(Context context) {
|
||||
super(context);
|
||||
mPaint.setFilterBitmap(true);
|
||||
}
|
||||
|
||||
private final Paint mPaint = new Paint();
|
||||
private int mAlpha;
|
||||
private int mDimmedAlpha;
|
||||
private Bitmap mDimmedView;
|
||||
private Canvas mDimmedViewCanvas;
|
||||
private boolean isDimmedViewUpdatePass;
|
||||
|
||||
private static float cubic(float r) {
|
||||
return (float) (Math.pow(r-1, 3) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated holographic highlight alpha for the effect we want when scrolling
|
||||
* pages.
|
||||
*/
|
||||
public static float highlightAlphaInterpolator(float r) {
|
||||
final float pivot = 0.3f;
|
||||
if (r < pivot) {
|
||||
return Math.max(0.5f, 0.65f*cubic(r/pivot));
|
||||
} else {
|
||||
return Math.min(1.0f, 0.65f*cubic(1 - (r-pivot)/(1-pivot)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated view alpha for the effect we want when scrolling pages.
|
||||
*/
|
||||
public static float viewAlphaInterpolator(float r) {
|
||||
final float pivot = 0.6f;
|
||||
if (r < pivot) {
|
||||
return r/pivot;
|
||||
} else {
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
private float mDimmableProgress;
|
||||
|
||||
private void setChildAlpha(float alpha) {
|
||||
if (getChildCount() > 0) {
|
||||
@@ -83,20 +52,18 @@ public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView {
|
||||
setChildAlpha(getAlpha());
|
||||
}
|
||||
|
||||
@Override
|
||||
//@Override
|
||||
public boolean onSetAlpha(int alpha) {
|
||||
super.onSetAlpha(alpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
final float viewAlpha = viewAlphaInterpolator(alpha);
|
||||
final float dimmedAlpha = highlightAlphaInterpolator(alpha);
|
||||
mAlpha = (int) (viewAlpha * 255);
|
||||
mDimmedAlpha = (int) (dimmedAlpha * 255);
|
||||
super.setAlpha(viewAlpha);
|
||||
setChildAlpha(viewAlpha);
|
||||
public void setDimmableProgress(float progress) {
|
||||
mDimmableProgress = progress;
|
||||
}
|
||||
|
||||
public float getDimmableProgress() {
|
||||
return mDimmableProgress;
|
||||
}
|
||||
|
||||
private void updateDimmedView() {
|
||||
@@ -113,13 +80,14 @@ public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView {
|
||||
int dimmedColor = getContext().getResources().getColor(R.color.dimmed_view_color);
|
||||
mDimmedViewCanvas.drawColor(dimmedColor, PorterDuff.Mode.SRC_IN);
|
||||
isDimmedViewUpdatePass = false;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
|
||||
if (mDimmedView == null && mDimmedAlpha > 0.0f) {
|
||||
if (mDimmedView == null && mDimmableProgress > 0.0f) {
|
||||
updateDimmedView();
|
||||
}
|
||||
}
|
||||
@@ -134,9 +102,9 @@ public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView {
|
||||
canvas.restore();
|
||||
setAlpha(alpha);
|
||||
} else {
|
||||
if (mDimmedView != null && mDimmedAlpha > 0) {
|
||||
if (mDimmedView != null && mDimmableProgress > 0) {
|
||||
// draw the dimmed version of this widget
|
||||
mPaint.setAlpha(mDimmedAlpha);
|
||||
mPaint.setAlpha((int) (mDimmableProgress * 255));
|
||||
canvas.drawBitmap(mDimmedView, 0, 0, mPaint);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,17 @@ import com.android.launcher.R;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class DimmableBubbleTextView extends BubbleTextView {
|
||||
public class DimmableBubbleTextView extends BubbleTextView implements Dimmable {
|
||||
private Paint mDimmedPaint = new Paint();
|
||||
private int mAlpha;
|
||||
private int mDimmedAlpha;
|
||||
private Bitmap mDimmedView;
|
||||
private Canvas mDimmedViewCanvas;
|
||||
private boolean isDimmedViewUpdatePass;
|
||||
private float mDimmableProgress;
|
||||
|
||||
public DimmableBubbleTextView(Context context) {
|
||||
super(context);
|
||||
@@ -49,48 +48,12 @@ public class DimmableBubbleTextView extends BubbleTextView {
|
||||
mDimmedPaint.setFilterBitmap(true);
|
||||
}
|
||||
|
||||
private static float cubic(float r) {
|
||||
return (float) (Math.pow(r-1, 3) + 1);
|
||||
public void setDimmableProgress(float progress) {
|
||||
mDimmableProgress = progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated holographic highlight alpha for the effect we want when scrolling
|
||||
* pages.
|
||||
*/
|
||||
public static float highlightAlphaInterpolator(float r) {
|
||||
final float pivot = 0.3f;
|
||||
if (r < pivot) {
|
||||
return Math.max(0.5f, 0.65f*cubic(r/pivot));
|
||||
} else {
|
||||
return Math.min(1.0f, 0.65f*cubic(1 - (r-pivot)/(1-pivot)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interpolated view alpha for the effect we want when scrolling pages.
|
||||
*/
|
||||
public static float viewAlphaInterpolator(float r) {
|
||||
final float pivot = 0.6f;
|
||||
if (r < pivot) {
|
||||
return r/pivot;
|
||||
} else {
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSetAlpha(int alpha) {
|
||||
super.onSetAlpha(alpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
final float viewAlpha = viewAlphaInterpolator(alpha);
|
||||
final float dimmedAlpha = highlightAlphaInterpolator(alpha);
|
||||
mAlpha = (int) (viewAlpha * 255);
|
||||
mDimmedAlpha = (int) (dimmedAlpha * 255);
|
||||
super.setAlpha(viewAlpha);
|
||||
public float getDimmableProgress() {
|
||||
return mDimmableProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,13 +87,11 @@ public class DimmableBubbleTextView extends BubbleTextView {
|
||||
super.setAlpha(alpha);
|
||||
canvas.restore();
|
||||
} else {
|
||||
if (mAlpha > 0) {
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
if (mDimmedView != null && mDimmedAlpha > 0) {
|
||||
mDimmedPaint.setAlpha(mDimmedAlpha);
|
||||
if (mDimmedView != null && mDimmableProgress > 0) {
|
||||
mDimmedPaint.setAlpha((int) (mDimmableProgress * 255));
|
||||
canvas.drawBitmap(mDimmedView, mScrollX, mScrollY, mDimmedPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.android.launcher.R;
|
||||
|
||||
/**
|
||||
* Class for initiating a drag within a view or across multiple views.
|
||||
*/
|
||||
@@ -47,7 +49,6 @@ public class DragController {
|
||||
public static int DRAG_ACTION_COPY = 1;
|
||||
|
||||
private static final int SCROLL_DELAY = 600;
|
||||
private static final int SCROLL_ZONE = 20;
|
||||
private static final int VIBRATE_DURATION = 35;
|
||||
|
||||
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
|
||||
@@ -87,6 +88,11 @@ public class DragController {
|
||||
/** Y offset from the upper-left corner of the cell to where we touched. */
|
||||
private float mTouchOffsetY;
|
||||
|
||||
/** the area at the edge of the screen that makes the workspace go left
|
||||
* or right while you're dragging.
|
||||
*/
|
||||
private int mScrollZone;
|
||||
|
||||
/** Where the drag originated */
|
||||
private DragSource mDragSource;
|
||||
|
||||
@@ -147,6 +153,7 @@ public class DragController {
|
||||
public DragController(Context context) {
|
||||
mContext = context;
|
||||
mHandler = new Handler();
|
||||
mScrollZone = context.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,13 +482,13 @@ public class DragController {
|
||||
if (mDeleteRegion != null) {
|
||||
inDeleteRegion = mDeleteRegion.contains(x, y);
|
||||
}
|
||||
if (!inDeleteRegion && x < SCROLL_ZONE) {
|
||||
if (!inDeleteRegion && x < mScrollZone) {
|
||||
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
|
||||
mScrollState = SCROLL_WAITING_IN_ZONE;
|
||||
mScrollRunnable.setDirection(SCROLL_LEFT);
|
||||
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
|
||||
}
|
||||
} else if (!inDeleteRegion && x > mScrollView.getWidth() - SCROLL_ZONE) {
|
||||
} else if (!inDeleteRegion && x > mScrollView.getWidth() - mScrollZone) {
|
||||
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
|
||||
mScrollState = SCROLL_WAITING_IN_ZONE;
|
||||
mScrollRunnable.setDirection(SCROLL_RIGHT);
|
||||
@@ -514,7 +521,7 @@ public class DragController {
|
||||
mMotionDownX = screenX;
|
||||
mMotionDownY = screenY;
|
||||
|
||||
if ((screenX < SCROLL_ZONE) || (screenX > mScrollView.getWidth() - SCROLL_ZONE)) {
|
||||
if ((screenX < mScrollZone) || (screenX > mScrollView.getWidth() - mScrollZone)) {
|
||||
mScrollState = SCROLL_WAITING_IN_ZONE;
|
||||
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.launcher2;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A convenience class for two-way animations, e.g. a fadeIn/fadeOut animation.
|
||||
* With a regular ValueAnimator, if you call reverse to show the 'out' animation, you'll get
|
||||
* a frame-by-frame mirror of the 'in' animation -- i.e., the interpolated values will
|
||||
* be exactly reversed. Using this class, both the 'in' and the 'out' animation use the
|
||||
* interpolator in the same direction.
|
||||
*/
|
||||
public class InterruptibleInOutAnimator extends ValueAnimator {
|
||||
private long mOriginalDuration;
|
||||
private Object mOriginalFromValue;
|
||||
private Object mOriginalToValue;
|
||||
|
||||
public InterruptibleInOutAnimator(long duration, Object fromValue, Object toValue) {
|
||||
super(duration, fromValue, toValue);
|
||||
mOriginalDuration = duration;
|
||||
mOriginalFromValue = fromValue;
|
||||
mOriginalToValue = toValue;
|
||||
}
|
||||
|
||||
private void animate(Object fromValue, Object toValue) {
|
||||
// This only makes sense when it's running in the opposite direction, or stopped.
|
||||
setDuration(mOriginalDuration - getCurrentPlayTime());
|
||||
|
||||
final Object startValue = isRunning() ? getAnimatedValue() : fromValue;
|
||||
cancel();
|
||||
setValues(startValue, toValue);
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the equivalent of calling Animator.start(), except that it can be called when
|
||||
* the animation is running in the opposite direction, in which case we reverse
|
||||
* direction and animate for a correspondingly shorter duration.
|
||||
*/
|
||||
public void animateIn() {
|
||||
animate(mOriginalFromValue, mOriginalToValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the roughly the equivalent of calling Animator.reverse(), except that it uses the
|
||||
* same interpolation curve as animateIn(), rather than mirroring it. Also, like animateIn(),
|
||||
* if the animation is currently running in the opposite direction, we reverse
|
||||
* direction and animate for a correspondingly shorter duration.
|
||||
*/
|
||||
public void animateOut() {
|
||||
animate(mOriginalToValue, mOriginalFromValue);
|
||||
}
|
||||
}
|
||||
@@ -300,8 +300,10 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
/**
|
||||
* Creates a new unique child id, for a given cell span across all layouts.
|
||||
*/
|
||||
static int getCellLayoutChildId(int cellId, int screen, int localCellX, int localCellY, int spanX, int spanY) {
|
||||
return ((cellId & 0xFF) << 16) | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
|
||||
static int getCellLayoutChildId(
|
||||
int cellId, int screen, int localCellX, int localCellY, int spanX, int spanY) {
|
||||
return ((cellId & 0xFF) << 24)
|
||||
| (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
|
||||
}
|
||||
|
||||
static int getCellCountX() {
|
||||
@@ -412,8 +414,9 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
|
||||
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
|
||||
// When everything comes back, just reload everything. We might not
|
||||
// have the right icons for apps on external storage.
|
||||
startLoader(mApp, false);
|
||||
|
||||
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
|
||||
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
|
||||
@@ -73,11 +73,13 @@ public abstract class PagedView extends ViewGroup {
|
||||
private float mDownMotionX;
|
||||
private float mLastMotionX;
|
||||
private float mLastMotionY;
|
||||
private int mLastScreenCenter = -1;
|
||||
|
||||
protected final static int TOUCH_STATE_REST = 0;
|
||||
protected final static int TOUCH_STATE_SCROLLING = 1;
|
||||
protected final static int TOUCH_STATE_PREV_PAGE = 2;
|
||||
protected final static int TOUCH_STATE_NEXT_PAGE = 3;
|
||||
protected final static float ALPHA_QUANTIZE_LEVEL = 0.01f;
|
||||
|
||||
protected int mTouchState = TOUCH_STATE_REST;
|
||||
|
||||
@@ -367,7 +369,6 @@ public abstract class PagedView extends ViewGroup {
|
||||
if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) {
|
||||
int halfScreenSize = getMeasuredWidth() / 2;
|
||||
int screenCenter = mScrollX + halfScreenSize;
|
||||
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; ++i) {
|
||||
View layout = (View) getChildAt(i);
|
||||
@@ -391,6 +392,12 @@ public abstract class PagedView extends ViewGroup {
|
||||
dimAlpha = Math.max(0.0f, Math.min(1.0f, (dimAlpha * dimAlpha)));
|
||||
float alpha = 1.0f - dimAlpha;
|
||||
|
||||
if (alpha < ALPHA_QUANTIZE_LEVEL) {
|
||||
alpha = 0.0f;
|
||||
} else if (alpha > 1.0f - ALPHA_QUANTIZE_LEVEL) {
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
if (Float.compare(alpha, layout.getAlpha()) != 0) {
|
||||
layout.setAlpha(alpha);
|
||||
}
|
||||
@@ -400,9 +407,19 @@ public abstract class PagedView extends ViewGroup {
|
||||
}
|
||||
}
|
||||
|
||||
protected void screenScrolled(int screenCenter) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
updateAdjacentPagesAlpha();
|
||||
int halfScreenSize = getMeasuredWidth() / 2;
|
||||
int screenCenter = mScrollX + halfScreenSize;
|
||||
|
||||
if (screenCenter != mLastScreenCenter) {
|
||||
screenScrolled(screenCenter);
|
||||
updateAdjacentPagesAlpha();
|
||||
mLastScreenCenter = screenCenter;
|
||||
}
|
||||
|
||||
// Find out which screens are visible; as an optimization we only call draw on them
|
||||
// As an optimization, this code assumes that all pages have the same width as the 0th
|
||||
|
||||
@@ -110,9 +110,9 @@ public class PagedViewIcon extends TextView implements Checkable {
|
||||
mIconCacheKey = info;
|
||||
mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
|
||||
|
||||
Drawable image = info.loadIcon(packageManager);
|
||||
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
|
||||
setCompoundDrawablesWithIntrinsicBounds(null, image, null, null);
|
||||
Bitmap image = Utilities.createIconBitmap(info.loadIcon(packageManager), mContext);
|
||||
setCompoundDrawablesWithIntrinsicBounds(null,
|
||||
new FastBitmapDrawable(image), null, null);
|
||||
setText(info.loadLabel(packageManager));
|
||||
setTag(info);
|
||||
}
|
||||
|
||||
@@ -26,11 +26,15 @@ public abstract class SmoothPagedView extends PagedView {
|
||||
private static final float SMOOTHING_SPEED = 0.75f;
|
||||
private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
|
||||
|
||||
private float mBaseLineFlingVelocity;
|
||||
private float mFlingVelocityInfluence;
|
||||
|
||||
private static final float BASELINE_FLING_VELOCITY = 2500.f;
|
||||
private static final float FLING_VELOCITY_INFLUENCE = 0.4f;
|
||||
static final int OVERSHOOT_MODE = 0;
|
||||
static final int QUINTIC_MODE = 1;
|
||||
|
||||
private WorkspaceOvershootInterpolator mScrollInterpolator;
|
||||
int mScrollMode;
|
||||
|
||||
private Interpolator mScrollInterpolator;
|
||||
|
||||
private static class WorkspaceOvershootInterpolator implements Interpolator {
|
||||
private static final float DEFAULT_TENSION = 1.3f;
|
||||
@@ -56,6 +60,16 @@ public abstract class SmoothPagedView extends PagedView {
|
||||
}
|
||||
}
|
||||
|
||||
private static class QuinticInterpolator implements Interpolator {
|
||||
public QuinticInterpolator() {
|
||||
}
|
||||
|
||||
public float getInterpolation(float t) {
|
||||
t -= 1.0f;
|
||||
return t*t*t*t*t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to inflate the Workspace from XML.
|
||||
*
|
||||
@@ -83,14 +97,27 @@ public abstract class SmoothPagedView extends PagedView {
|
||||
mDeferScrollUpdate = true;
|
||||
}
|
||||
|
||||
protected int getScrollMode() {
|
||||
return OVERSHOOT_MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes various states for this workspace.
|
||||
*/
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
mScrollInterpolator = new WorkspaceOvershootInterpolator();
|
||||
// overwrite the previous mScroller
|
||||
|
||||
mScrollMode = getScrollMode();
|
||||
if (mScrollMode == QUINTIC_MODE) {
|
||||
mBaseLineFlingVelocity = 700.0f;
|
||||
mFlingVelocityInfluence = 0.8f;
|
||||
mScrollInterpolator = new QuinticInterpolator();
|
||||
} else { // QUINTIC_MODE
|
||||
mBaseLineFlingVelocity = 2500.0f;
|
||||
mFlingVelocityInfluence = 0.4f;
|
||||
mScrollInterpolator = new WorkspaceOvershootInterpolator();
|
||||
}
|
||||
mScroller = new Scroller(getContext(), mScrollInterpolator);
|
||||
}
|
||||
|
||||
@@ -112,25 +139,32 @@ public abstract class SmoothPagedView extends PagedView {
|
||||
final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage));
|
||||
final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
|
||||
final int delta = newX - mScrollX;
|
||||
int duration = (screenDelta + 1) * 100;
|
||||
int duration;
|
||||
if (mScrollMode == OVERSHOOT_MODE) {
|
||||
duration = (screenDelta + 1) * 100;
|
||||
} else { // QUINTIC_MODE
|
||||
duration = Math.round(Math.abs(delta) * 0.6f);
|
||||
}
|
||||
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
|
||||
if (settle) {
|
||||
mScrollInterpolator.setDistance(screenDelta);
|
||||
} else {
|
||||
mScrollInterpolator.disableSettle();
|
||||
if (mScrollMode == OVERSHOOT_MODE) {
|
||||
if (settle) {
|
||||
((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
|
||||
} else {
|
||||
((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle();
|
||||
}
|
||||
}
|
||||
|
||||
velocity = Math.abs(velocity);
|
||||
if (velocity > 0) {
|
||||
duration += (duration / (velocity / BASELINE_FLING_VELOCITY))
|
||||
* FLING_VELOCITY_INFLUENCE;
|
||||
duration += (duration / (velocity / mBaseLineFlingVelocity)) * mFlingVelocityInfluence;
|
||||
} else {
|
||||
duration += 100;
|
||||
}
|
||||
|
||||
snapToPage(whichPage, delta, duration);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Camera;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -63,8 +65,8 @@ public class Workspace extends SmoothPagedView
|
||||
// customization mode
|
||||
private static final float SHRINK_FACTOR = 0.16f;
|
||||
|
||||
// The maximum Y rotation to apply to the mini home screens
|
||||
private static final float MINI_PAGE_MAX_ROTATION = 25.0f;
|
||||
// Y rotation to apply to the workspace screens
|
||||
private static final float WORKSPACE_ROTATION = 12.5f;
|
||||
|
||||
// These are extra scale factors to apply to the mini home screens
|
||||
// so as to achieve the desired transform
|
||||
@@ -72,6 +74,18 @@ public class Workspace extends SmoothPagedView
|
||||
private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
|
||||
private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
|
||||
|
||||
private static final int BACKGROUND_FADE_OUT_DELAY = 300;
|
||||
private static final int BACKGROUND_FADE_OUT_DURATION = 300;
|
||||
private static final int BACKGROUND_FADE_IN_DURATION = 100;
|
||||
|
||||
static final int SCROLL_RIGHT = 0;
|
||||
static final int SCROLL_LEFT = 1;
|
||||
|
||||
// These animators are used to fade the
|
||||
private ObjectAnimator<Float> mBackgroundFadeIn;
|
||||
private ObjectAnimator<Float> mBackgroundFadeOut;
|
||||
private float mBackgroundAlpha = 0;
|
||||
|
||||
private enum ShrinkPosition { SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM };
|
||||
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
@@ -179,6 +193,15 @@ public class Workspace extends SmoothPagedView
|
||||
mSnapVelocity = 600;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollMode() {
|
||||
if (LauncherApplication.isScreenXLarge()) {
|
||||
return SmoothPagedView.QUINTIC_MODE;
|
||||
} else {
|
||||
return SmoothPagedView.OVERSHOOT_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index, LayoutParams params) {
|
||||
if (!(child instanceof CellLayout)) {
|
||||
@@ -322,7 +345,7 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
|
||||
// Get the canonical child id to uniquely represent this view in this screen
|
||||
int childId = LauncherModel.getCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY);
|
||||
int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
|
||||
if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
|
||||
// TODO: This branch occurs when the workspace is adding views
|
||||
// outside of the defined grid
|
||||
@@ -382,12 +405,14 @@ public class Workspace extends SmoothPagedView
|
||||
enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
|
||||
}
|
||||
}
|
||||
showOutlines();
|
||||
}
|
||||
|
||||
protected void pageEndMoving() {
|
||||
if (!LauncherApplication.isScreenXLarge()) {
|
||||
clearChildrenCache();
|
||||
}
|
||||
hideOutlines();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -424,6 +449,99 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
}
|
||||
|
||||
private float getScaleXForRotation(float degrees) {
|
||||
return (float) (1.0f / Math.cos(Math.PI * degrees / 180.0f));
|
||||
}
|
||||
|
||||
public void showOutlines() {
|
||||
if (mBackgroundFadeOut != null) mBackgroundFadeOut.cancel();
|
||||
if (mBackgroundFadeIn != null) mBackgroundFadeIn.cancel();
|
||||
mBackgroundFadeIn = new ObjectAnimator<Float>(BACKGROUND_FADE_IN_DURATION, this,
|
||||
new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f));
|
||||
mBackgroundFadeIn.start();
|
||||
}
|
||||
|
||||
public void hideOutlines() {
|
||||
if (mBackgroundFadeIn != null) mBackgroundFadeIn.cancel();
|
||||
if (mBackgroundFadeOut != null) mBackgroundFadeOut.cancel();
|
||||
mBackgroundFadeOut = new ObjectAnimator<Float>(BACKGROUND_FADE_OUT_DURATION, this,
|
||||
new PropertyValuesHolder<Float>("backgroundAlpha", 0.0f));
|
||||
mBackgroundFadeOut.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
|
||||
mBackgroundFadeOut.start();
|
||||
}
|
||||
|
||||
public void setBackgroundAlpha(float alpha) {
|
||||
mBackgroundAlpha = alpha;
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
CellLayout cl = (CellLayout) getChildAt(i);
|
||||
cl.setBackgroundAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public float getBackgroundAlpha() {
|
||||
return mBackgroundAlpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void screenScrolled(int screenCenter) {
|
||||
View cur = getChildAt(mCurrentPage);
|
||||
View toRight = getChildAt(mCurrentPage + 1);
|
||||
View toLeft = getChildAt(mCurrentPage - 1);
|
||||
|
||||
for (int i = 0; i < mCurrentPage - 1; i++) {
|
||||
View v = getChildAt(i);
|
||||
if (v != null) {
|
||||
v.setRotationY(WORKSPACE_ROTATION);
|
||||
v.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
|
||||
}
|
||||
}
|
||||
for (int i = mCurrentPage + 1; i < getChildCount(); i++) {
|
||||
View v = getChildAt(i);
|
||||
if (v != null) {
|
||||
v.setRotationY(-WORKSPACE_ROTATION);
|
||||
v.setScaleX(getScaleXForRotation(-WORKSPACE_ROTATION));
|
||||
}
|
||||
}
|
||||
|
||||
int pageWidth = cur.getMeasuredWidth();
|
||||
int delta = screenCenter - (mCurrentPage * pageWidth + pageWidth / 2 +
|
||||
getRelativeChildOffset(0));
|
||||
|
||||
float scrollProgress = Math.abs(delta/(pageWidth*1.0f));
|
||||
int scrollDirection = delta > 0 ? SCROLL_LEFT : SCROLL_RIGHT;
|
||||
|
||||
float rotation;
|
||||
|
||||
if (scrollDirection == SCROLL_RIGHT) {
|
||||
rotation = -scrollProgress * WORKSPACE_ROTATION;
|
||||
cur.setRotationY(rotation);
|
||||
cur.setScaleX(getScaleXForRotation(rotation));
|
||||
if (toLeft != null) {
|
||||
rotation = WORKSPACE_ROTATION * (1 - scrollProgress);
|
||||
toLeft.setRotationY(rotation);
|
||||
toLeft.setScaleX(getScaleXForRotation(rotation));
|
||||
}
|
||||
if (toRight != null) {
|
||||
toRight.setRotationY(-WORKSPACE_ROTATION);
|
||||
toRight.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
|
||||
}
|
||||
} else {
|
||||
rotation = scrollProgress * WORKSPACE_ROTATION;
|
||||
cur.setRotationY(rotation);
|
||||
cur.setScaleX(getScaleXForRotation(rotation));
|
||||
|
||||
if (toRight != null) {
|
||||
rotation = -WORKSPACE_ROTATION * (1 - scrollProgress);
|
||||
toRight.setRotationY(rotation);
|
||||
toRight.setScaleX(getScaleXForRotation(rotation));
|
||||
}
|
||||
if (toLeft != null) {
|
||||
toLeft.setRotationY(WORKSPACE_ROTATION);
|
||||
toLeft.setScaleX(getScaleXForRotation(WORKSPACE_ROTATION));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
computeScroll();
|
||||
@@ -624,7 +742,7 @@ public class Workspace extends SmoothPagedView
|
||||
for (int i = 0; i < screenCount; i++) {
|
||||
CellLayout cl = (CellLayout) getChildAt(i);
|
||||
|
||||
float rotation = (-i + 2) * MINI_PAGE_MAX_ROTATION / 2.0f;
|
||||
float rotation = (-i + 2) * WORKSPACE_ROTATION;
|
||||
float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
|
||||
float rotationScaleY = getYScaleForScreen(i);
|
||||
|
||||
@@ -636,14 +754,16 @@ public class Workspace extends SmoothPagedView
|
||||
new PropertyValuesHolder<Float>("scaleX", SHRINK_FACTOR * rotationScaleX),
|
||||
new PropertyValuesHolder<Float>("scaleY", SHRINK_FACTOR * rotationScaleY),
|
||||
new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f),
|
||||
new PropertyValuesHolder<Float>("dimmableProgress", 1.0f),
|
||||
new PropertyValuesHolder<Float>("alpha", 0.0f),
|
||||
new PropertyValuesHolder<Float>("rotationY", rotation)).start();
|
||||
} else {
|
||||
cl.setX((int)newX);
|
||||
cl.setY((int)newY);
|
||||
cl.setScaleX(SHRINK_FACTOR);
|
||||
cl.setScaleY(SHRINK_FACTOR);
|
||||
cl.setScaleX(SHRINK_FACTOR * rotationScaleX);
|
||||
cl.setScaleY(SHRINK_FACTOR * rotationScaleY);
|
||||
cl.setBackgroundAlpha(1.0f);
|
||||
cl.setDimmableProgress(1.0f);
|
||||
cl.setAlpha(0.0f);
|
||||
cl.setRotationY(rotation);
|
||||
}
|
||||
@@ -696,6 +816,14 @@ public class Workspace extends SmoothPagedView
|
||||
for (int i = 0; i < screenCount; i++) {
|
||||
final CellLayout cl = (CellLayout)getChildAt(i);
|
||||
float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
|
||||
float rotation = 0.0f;
|
||||
|
||||
if (i < mCurrentPage) {
|
||||
rotation = WORKSPACE_ROTATION;
|
||||
} else if (i > mCurrentPage) {
|
||||
rotation = -WORKSPACE_ROTATION;
|
||||
}
|
||||
|
||||
if (animated) {
|
||||
s.playTogether(
|
||||
new ObjectAnimator<Float>(duration, cl, "translationX", 0.0f),
|
||||
@@ -704,15 +832,17 @@ public class Workspace extends SmoothPagedView
|
||||
new ObjectAnimator<Float>(duration, cl, "scaleY", 1.0f),
|
||||
new ObjectAnimator<Float>(duration, cl, "backgroundAlpha", 0.0f),
|
||||
new ObjectAnimator<Float>(duration, cl, "alpha", finalAlphaValue),
|
||||
new ObjectAnimator<Float>(duration, cl, "rotationY", 0.0f));
|
||||
new ObjectAnimator<Float>(duration, cl, "dimmableProgress", 0.0f),
|
||||
new ObjectAnimator<Float>(duration, cl, "rotationY", rotation));
|
||||
} else {
|
||||
cl.setTranslationX(0.0f);
|
||||
cl.setTranslationY(0.0f);
|
||||
cl.setScaleX(1.0f);
|
||||
cl.setScaleY(1.0f);
|
||||
cl.setBackgroundAlpha(0.0f);
|
||||
cl.setAlpha(1.0f);
|
||||
cl.setRotationY(0.0f);
|
||||
cl.setDimmableProgress(0.0f);
|
||||
cl.setAlpha(finalAlphaValue);
|
||||
cl.setRotationY(rotation);
|
||||
}
|
||||
}
|
||||
s.addListener(mUnshrinkAnimationListener);
|
||||
@@ -774,23 +904,25 @@ public class Workspace extends SmoothPagedView
|
||||
} else {
|
||||
cellLayout = getCurrentDropLayout();
|
||||
}
|
||||
|
||||
if (source != this) {
|
||||
onDropExternal(originX, originY, dragInfo, cellLayout);
|
||||
} else {
|
||||
// Move internally
|
||||
if (mDragInfo != null) {
|
||||
final View cell = mDragInfo.cell;
|
||||
int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
|
||||
if (index != mDragInfo.screen) {
|
||||
final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
|
||||
originalCellLayout.removeView(cell);
|
||||
addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY,
|
||||
mDragInfo.spanX, mDragInfo.spanY);
|
||||
}
|
||||
|
||||
mTargetCell = findNearestVacantArea(originX, originY,
|
||||
mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
|
||||
mTargetCell);
|
||||
|
||||
int screen = indexOfChild(cellLayout);
|
||||
if (screen != mDragInfo.screen) {
|
||||
final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
|
||||
originalCellLayout.removeView(cell);
|
||||
addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
|
||||
mDragInfo.spanX, mDragInfo.spanY);
|
||||
}
|
||||
cellLayout.onDropChild(cell);
|
||||
|
||||
// update the item's position after drop
|
||||
@@ -799,9 +931,11 @@ public class Workspace extends SmoothPagedView
|
||||
cellLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
|
||||
lp.cellX = mTargetCell[0];
|
||||
lp.cellY = mTargetCell[1];
|
||||
cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
|
||||
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
|
||||
|
||||
LauncherModel.moveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, index,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
|
||||
lp.cellX, lp.cellY);
|
||||
}
|
||||
}
|
||||
@@ -1152,15 +1286,12 @@ public class Workspace extends SmoothPagedView
|
||||
private int[] findNearestVacantArea(int pixelX, int pixelY,
|
||||
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
|
||||
|
||||
final int[] cellXY = mTempCell;
|
||||
int localPixelX = pixelX - (layout.getLeft() - mScrollX);
|
||||
int localPixelY = pixelY - (layout.getTop() - mScrollY);
|
||||
layout.estimateDropCell(localPixelX, localPixelY, spanX, spanY, cellXY);
|
||||
layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
|
||||
|
||||
// Find the best target drop location
|
||||
return layout.findNearestVacantArea(
|
||||
mTempEstimate[0], mTempEstimate[1], spanX, spanY, ignoreView, recycle);
|
||||
localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||