diff options
-rw-r--r-- | res/drawable-hdpi/active_page.png | bin | 1295 -> 1223 bytes | |||
-rw-r--r-- | res/drawable-hdpi/inactive_page.png | bin | 1402 -> 1275 bytes | |||
-rw-r--r-- | res/drawable-mdpi/active_page.png | bin | 1186 -> 1225 bytes | |||
-rw-r--r-- | res/drawable-mdpi/inactive_page.png | bin | 1268 -> 1189 bytes | |||
-rw-r--r-- | res/drawable-xhdpi/active_page.png | bin | 1367 -> 1225 bytes | |||
-rw-r--r-- | res/drawable-xhdpi/inactive_page.png | bin | 1450 -> 1235 bytes | |||
-rw-r--r-- | res/layout/page_indicator.xml | 3 | ||||
-rw-r--r-- | res/values/attrs.xml | 7 | ||||
-rw-r--r-- | res/values/config.xml | 3 | ||||
-rw-r--r-- | src/com/android/launcher3/MemoryTracker.java | 35 | ||||
-rw-r--r-- | src/com/android/launcher3/PageIndicator.java | 149 | ||||
-rw-r--r-- | src/com/android/launcher3/PageIndicatorMarker.java | 44 |
12 files changed, 204 insertions, 37 deletions
diff --git a/res/drawable-hdpi/active_page.png b/res/drawable-hdpi/active_page.png Binary files differindex ce2d5b169..58aa7f9ee 100644 --- a/res/drawable-hdpi/active_page.png +++ b/res/drawable-hdpi/active_page.png diff --git a/res/drawable-hdpi/inactive_page.png b/res/drawable-hdpi/inactive_page.png Binary files differindex 2186f519a..b70d9f418 100644 --- a/res/drawable-hdpi/inactive_page.png +++ b/res/drawable-hdpi/inactive_page.png diff --git a/res/drawable-mdpi/active_page.png b/res/drawable-mdpi/active_page.png Binary files differindex 9e23eccb0..296a9a6b0 100644 --- a/res/drawable-mdpi/active_page.png +++ b/res/drawable-mdpi/active_page.png diff --git a/res/drawable-mdpi/inactive_page.png b/res/drawable-mdpi/inactive_page.png Binary files differindex 9468a62ed..2225d250b 100644 --- a/res/drawable-mdpi/inactive_page.png +++ b/res/drawable-mdpi/inactive_page.png diff --git a/res/drawable-xhdpi/active_page.png b/res/drawable-xhdpi/active_page.png Binary files differindex c43e67c40..a1cfc354b 100644 --- a/res/drawable-xhdpi/active_page.png +++ b/res/drawable-xhdpi/active_page.png diff --git a/res/drawable-xhdpi/inactive_page.png b/res/drawable-xhdpi/inactive_page.png Binary files differindex ae3f9885b..177b25305 100644 --- a/res/drawable-xhdpi/inactive_page.png +++ b/res/drawable-xhdpi/inactive_page.png diff --git a/res/layout/page_indicator.xml b/res/layout/page_indicator.xml index 8aae752c5..14eff75d0 100644 --- a/res/layout/page_indicator.xml +++ b/res/layout/page_indicator.xml @@ -16,5 +16,6 @@ <com.android.launcher3.PageIndicator xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - android:animateLayoutChanges="true"> + android:animateLayoutChanges="true" + launcher:windowSize="@integer/config_maxNumberOfPageIndicatorsToShow"> </com.android.launcher3.PageIndicator> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 154508379..09b880420 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -32,6 +32,13 @@ <attr name="drawIdentifier" format="string" /> </declare-styleable> + <!-- Page Indicator specific attributes. These attributes are used to customize + the cling in XML files. --> + <declare-styleable name="PageIndicator"> + <!-- Used to identify how to draw the cling bg --> + <attr name="windowSize" format="integer" /> + </declare-styleable> + <!-- Workspace specific attributes. These attributes are used to customize the workspace in XML files. --> <declare-styleable name="Workspace"> diff --git a/res/values/config.xml b/res/values/config.xml index 6aaca1ad5..cc3d4f0bf 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -3,6 +3,9 @@ <bool name="is_large_screen">false</bool> <bool name="allow_rotation">false</bool> + <!-- Max number of page indicators to show --> + <integer name="config_maxNumberOfPageIndicatorsToShow">21</integer> + <!-- DragController --> <integer name="config_flingToDeleteMinVelocity">-1500</integer> diff --git a/src/com/android/launcher3/MemoryTracker.java b/src/com/android/launcher3/MemoryTracker.java index d3bb77c77..0a796a261 100644 --- a/src/com/android/launcher3/MemoryTracker.java +++ b/src/com/android/launcher3/MemoryTracker.java @@ -107,24 +107,33 @@ public class MemoryTracker extends Service { if (mPids.contains(lpid)) return; mPids.add(lpid); - final int N = mPids.size(); - mPidsArray = new int[N]; - StringBuffer sb = new StringBuffer("Now tracking processes: "); - for (int i=0; i<N; i++) { - final int p = mPids.get(i).intValue(); - mPidsArray[i] = p; - sb.append(p); sb.append(" "); - } + updatePidsArrayL(); + mData.put(pid, new ProcessMemInfo(pid, name, start)); - Log.v(TAG, sb.toString()); } } + void updatePidsArrayL() { + final int N = mPids.size(); + mPidsArray = new int[N]; + StringBuffer sb = new StringBuffer("Now tracking processes: "); + for (int i=0; i<N; i++) { + final int p = mPids.get(i).intValue(); + mPidsArray[i] = p; + sb.append(p); sb.append(" "); + } + Log.v(TAG, sb.toString()); + } + void update() { synchronized (mLock) { Debug.MemoryInfo[] dinfos = mAm.getProcessMemoryInfo(mPidsArray); for (int i=0; i<dinfos.length; i++) { Debug.MemoryInfo dinfo = dinfos[i]; + if (i > mPids.size()) { + Log.e(TAG, "update: unknown process info received: " + dinfo); + break; + } final long pid = mPids.get(i).intValue(); final ProcessMemInfo info = mData.get(pid); info.head = (info.head+1) % info.pss.length; @@ -142,6 +151,7 @@ public class MemoryTracker extends Service { final long pid = mPids.get(i).intValue(); if (mData.get(pid) == null) { mPids.remove(i); + updatePidsArrayL(); } } } @@ -155,7 +165,9 @@ public class MemoryTracker extends Service { List<ActivityManager.RunningServiceInfo> svcs = mAm.getRunningServices(256); for (ActivityManager.RunningServiceInfo svc : svcs) { if (svc.service.getPackageName().equals(getPackageName())) { - startTrackingProcess(svc.pid, svc.process, System.currentTimeMillis() - (SystemClock.elapsedRealtime() - svc.activeSince)); + Log.v(TAG, "discovered running service: " + svc.process + " (" + svc.pid + ")"); + startTrackingProcess(svc.pid, svc.process, + System.currentTimeMillis() - (SystemClock.elapsedRealtime() - svc.activeSince)); } } @@ -163,6 +175,7 @@ public class MemoryTracker extends Service { for (ActivityManager.RunningAppProcessInfo proc : procs) { final String pname = proc.processName; if (pname.startsWith(getPackageName())) { + Log.v(TAG, "discovered other running process: " + pname + " (" + proc.pid + ")"); startTrackingProcess(proc.pid, pname, System.currentTimeMillis()); } } @@ -175,7 +188,7 @@ public class MemoryTracker extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - Log.i(TAG, "Received start id " + startId + ": " + intent); + Log.v(TAG, "Received start id " + startId + ": " + intent); if (intent != null) { if (ACTION_START_TRACKING.equals(intent.getAction())) { diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java index ecaa8f544..d7778fb1a 100644 --- a/src/com/android/launcher3/PageIndicator.java +++ b/src/com/android/launcher3/PageIndicator.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; +import android.animation.TimeInterpolator; import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; @@ -37,8 +38,22 @@ import java.util.ArrayList; public class PageIndicator extends LinearLayout { @SuppressWarnings("unused") private static final String TAG = "PageIndicator"; + // Want this to look good? Keep it odd + private static final boolean MODULATE_ALPHA_ENABLED = false; private LayoutInflater mLayoutInflater; + private int[] mWindowRange = new int[2]; + private int mMaxWindowSize; + + private ArrayList<PageIndicatorMarker> mMarkers = + new ArrayList<PageIndicatorMarker>(); + private int mActiveMarkerIndex; + + private TimeInterpolator mAlphaInterpolator = new TimeInterpolator() { + public float getInterpolation(float t) { + return t; + } + }; public PageIndicator(Context context) { this(context, null); @@ -50,16 +65,110 @@ public class PageIndicator extends LinearLayout { public PageIndicator(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.PageIndicator, defStyle, 0); + mMaxWindowSize = a.getInteger(R.styleable.PageIndicator_windowSize, 15); + mWindowRange[0] = 0; + mWindowRange[1] = 0; mLayoutInflater = LayoutInflater.from(context); + a.recycle(); + + // Set the layout transition properties + LayoutTransition transition = getLayoutTransition(); + transition.setDuration(175); + } + + private void enableLayoutTransitions() { + LayoutTransition transition = getLayoutTransition(); + transition.enableTransitionType(LayoutTransition.APPEARING); + transition.enableTransitionType(LayoutTransition.DISAPPEARING); + transition.enableTransitionType(LayoutTransition.CHANGE_APPEARING); + transition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); + } + private void disableLayoutTransitions() { LayoutTransition transition = getLayoutTransition(); - transition.setDuration(250); + transition.disableTransitionType(LayoutTransition.APPEARING); + transition.disableTransitionType(LayoutTransition.DISAPPEARING); + transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); + transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); + } + + void offsetWindowCenterTo(int activeIndex, boolean allowAnimations) { + if (activeIndex < 0) { + new Throwable().printStackTrace(); + } + int windowSize = Math.min(mMarkers.size(), mMaxWindowSize); + int hWindowSize = (int) windowSize / 2; + float hfWindowSize = windowSize / 2f; + int windowStart = Math.max(0, activeIndex - hWindowSize); + int windowEnd = Math.min(mMarkers.size(), windowStart + mMaxWindowSize); + windowStart = windowEnd - Math.min(mMarkers.size(), windowSize); + int windowMid = windowStart + (windowEnd - windowStart) / 2; + boolean windowAtStart = (windowStart == 0); + boolean windowAtEnd = (windowEnd == mMarkers.size()); + boolean windowMoved = (mWindowRange[0] != windowStart) || + (mWindowRange[1] != windowEnd); + + if (!allowAnimations) { + disableLayoutTransitions(); + } + + // Remove all the previous children that are no longer in the window + for (int i = getChildCount() - 1; i >= 0; --i) { + PageIndicatorMarker marker = (PageIndicatorMarker) getChildAt(i); + int markerIndex = mMarkers.indexOf(marker); + if (markerIndex < windowStart || markerIndex >= windowEnd) { + removeView(marker); + } + } + + // Add all the new children that belong in the window + for (int i = 0; i < mMarkers.size(); ++i) { + PageIndicatorMarker marker = (PageIndicatorMarker) mMarkers.get(i); + if (windowStart <= i && i < windowEnd) { + if (indexOfChild(marker) < 0) { + addView(marker, i - windowStart); + } + if (i == activeIndex) { + marker.activate(windowMoved); + } else { + marker.inactivate(windowMoved); + } + } else { + marker.inactivate(true); + } + + if (MODULATE_ALPHA_ENABLED) { + // Update the marker's alpha + float alpha = 1f; + if (mMarkers.size() > windowSize) { + if ((windowAtStart && i > hWindowSize) || + (windowAtEnd && i < (mMarkers.size() - hWindowSize)) || + (!windowAtStart && !windowAtEnd)) { + alpha = 1f - Math.abs((i - windowMid) / hfWindowSize); + } + } + marker.animate().alpha(alpha).setDuration(500).start(); + } + } + + if (!allowAnimations) { + enableLayoutTransitions(); + } + + mWindowRange[0] = windowStart; + mWindowRange[1] = windowEnd; } void addMarker(int index) { - index = Math.max(0, Math.min(index, getChildCount())); - View marker = mLayoutInflater.inflate(R.layout.page_indicator_marker, this, false); - addView(marker, index); + index = Math.max(0, Math.min(index, mMarkers.size())); + + int mLayoutId = R.layout.page_indicator_marker; + PageIndicatorMarker marker = + (PageIndicatorMarker) mLayoutInflater.inflate(mLayoutId, this, false); + mMarkers.add(index, marker); + offsetWindowCenterTo(mActiveMarkerIndex, true); } void addMarkers(int count) { for (int i = 0; i < count; ++i) { @@ -68,25 +177,37 @@ public class PageIndicator extends LinearLayout { } void removeMarker(int index) { - if (getChildCount() > 0) { - index = Math.max(0, Math.min(index, getChildCount() - 1)); - removeViewAt(index); + if (mMarkers.size() > 0) { + index = Math.max(0, Math.min(mMarkers.size() - 1, index)); + mMarkers.remove(index); + offsetWindowCenterTo(mActiveMarkerIndex, true); } } void removeAllMarkers() { - while (getChildCount() > 0) { + while (mMarkers.size() > 0) { removeMarker(Integer.MAX_VALUE); } } void setActiveMarker(int index) { + // Center the active marker + mActiveMarkerIndex = index; + offsetWindowCenterTo(index, false); + } + + void dumpState(String txt) { + System.out.println(txt); + System.out.println("\tmMarkers: " + mMarkers.size()); + for (int i = 0; i < mMarkers.size(); ++i) { + PageIndicatorMarker m = mMarkers.get(i); + System.out.println("\t\t(" + i + ") " + m); + } + System.out.println("\twindow: [" + mWindowRange[0] + ", " + mWindowRange[1] + "]"); + System.out.println("\tchildren: " + getChildCount()); for (int i = 0; i < getChildCount(); ++i) { - PageIndicatorMarker marker = (PageIndicatorMarker) getChildAt(i); - if (index == i) { - marker.activate(); - } else { - marker.inactivate(); - } + PageIndicatorMarker m = (PageIndicatorMarker) getChildAt(i); + System.out.println("\t\t(" + i + ") " + m); } + System.out.println("\tactive: " + mActiveMarkerIndex); } } diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java index 852ee518f..f64c14fdc 100644 --- a/src/com/android/launcher3/PageIndicatorMarker.java +++ b/src/com/android/launcher3/PageIndicatorMarker.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; import android.content.Context; import android.util.AttributeSet; @@ -29,10 +30,11 @@ public class PageIndicatorMarker extends FrameLayout { @SuppressWarnings("unused") private static final String TAG = "PageIndicator"; - private static final int MARKER_FADE_DURATION = 150; + private static final int MARKER_FADE_DURATION = 175; private View mActiveMarker; private View mInactiveMarker; + private boolean mIsActive = false; public PageIndicatorMarker(Context context) { this(context, null); @@ -51,16 +53,36 @@ public class PageIndicatorMarker extends FrameLayout { mInactiveMarker = findViewById(R.id.inactive); } - public void activate() { - mActiveMarker.animate().alpha(1f) - .setDuration(MARKER_FADE_DURATION).start(); - mInactiveMarker.animate().alpha(0f) - .setDuration(MARKER_FADE_DURATION).start(); + void activate(boolean immediate) { + if (immediate) { + mActiveMarker.animate().cancel(); + mActiveMarker.setAlpha(1f); + mInactiveMarker.animate().cancel(); + mInactiveMarker.setAlpha(0f); + } else { + mActiveMarker.animate().alpha(1f) + .setDuration(MARKER_FADE_DURATION).start(); + mInactiveMarker.animate().alpha(0f) + .setDuration(MARKER_FADE_DURATION).start(); + } + mIsActive = true; } - public void inactivate() { - mInactiveMarker.animate().alpha(1f) - .setDuration(MARKER_FADE_DURATION).start(); - mActiveMarker.animate().alpha(0f) - .setDuration(MARKER_FADE_DURATION).start(); + void inactivate(boolean immediate) { + if (immediate) { + mInactiveMarker.animate().cancel(); + mInactiveMarker.setAlpha(1f); + mActiveMarker.animate().cancel(); + mActiveMarker.setAlpha(0f); + } else { + mInactiveMarker.animate().alpha(1f) + .setDuration(MARKER_FADE_DURATION).start(); + mActiveMarker.animate().alpha(0f) + .setDuration(MARKER_FADE_DURATION).start(); + } + mIsActive = false; + } + + boolean isActive() { + return mIsActive; } } |