Files
Lawnchair/src/com/android/launcher2/AllAppsPagedView.java
T
Winson Chung 80baf5a6b3 Adding paging for the widget/shortcut/folder customization area and fixing bugs.
Adding pages for customization drawer with initial implementation of proposed flow
layout for widgets.  Fixes for keeping all apps, and widgets in sync with Launcher
Model, optimizations for reloading all apps pages when invalidating.  Adding some
animations for tab transitions and feedback when long pressing to add certain items.

Change-Id: I8d51749f3a91c964bed35681f3a9192200b0d93e
2010-08-16 15:51:43 -07:00

377 lines
12 KiB
Java

/*
* 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 java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import android.animation.Animatable;
import android.animation.AnimatableListenerAdapter;
import android.animation.Animator;
import android.animation.PropertyAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Animation.AnimationListener;
import android.widget.TextView;
import com.android.launcher.R;
/**
* An implementation of PagedView that populates the pages of the workspace
* with all of the user's applications.
*/
public class AllAppsPagedView extends PagedView
implements AllAppsView, View.OnClickListener, View.OnLongClickListener, DragSource,
PagedViewCellLayout.DimmedBitmapSetupListener {
private static final String TAG = "AllAppsPagedView";
private static final boolean DEBUG = false;
private Launcher mLauncher;
private DragController mDragController;
// preserve compatibility with 3D all apps:
// 0.0 -> hidden
// 1.0 -> shown and opaque
// intermediate values -> partially shown & partially opaque
private float mZoom;
// set of all applications
private ArrayList<ApplicationInfo> mApps;
private ArrayList<ApplicationInfo> mFilteredApps;
// the types of applications to filter
static final int ALL_APPS_FLAG = -1;
private int mAppFilter = ALL_APPS_FLAG;
private int mCellCountX;
private int mCellCountY;
private final LayoutInflater mInflater;
public AllAppsPagedView(Context context) {
this(context, null);
}
public AllAppsPagedView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
mInflater = LayoutInflater.from(context);
a.recycle();
setSoundEffectsEnabled(false);
}
@Override
public void setLauncher(Launcher launcher) {
mLauncher = launcher;
}
@Override
public void setDragController(DragController dragger) {
mDragController = dragger;
}
public void setAppFilter(int filterType) {
mAppFilter = filterType;
if (mApps != null) {
mFilteredApps = rebuildFilteredApps(mApps);
setCurrentScreen(0);
invalidatePageData();
}
}
@Override
public void zoom(float zoom, boolean animate) {
mZoom = zoom;
cancelLongPress();
if (isVisible()) {
getParent().bringChildToFront(this);
setVisibility(View.VISIBLE);
if (animate) {
startAnimation(AnimationUtils.loadAnimation(getContext(),
R.anim.all_apps_2d_fade_in));
} else {
onAnimationEnd();
}
} else {
if (animate) {
startAnimation(AnimationUtils.loadAnimation(getContext(),
R.anim.all_apps_2d_fade_out));
} else {
onAnimationEnd();
}
}
}
protected void onAnimationEnd() {
if (!isVisible()) {
setVisibility(View.GONE);
mZoom = 0.0f;
} else {
mZoom = 1.0f;
}
if (mLauncher != null)
mLauncher.zoomed(mZoom);
}
private int getChildIndexForGrandChild(View v) {
final int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i);
if (layout.indexOfChild(v) > -1) {
return i;
}
}
return -1;
}
@Override
public void onClick(View v) {
int childIndex = getChildIndexForGrandChild(v);
if (childIndex == getCurrentScreen()) {
final ApplicationInfo app = (ApplicationInfo) v.getTag();
// animate some feedback to the click
animateClickFeedback(v, new Runnable() {
@Override
public void run() {
mLauncher.startActivitySafely(app.intent, app);
}
});
}
}
@Override
public boolean onLongClick(View v) {
if (!v.isInTouchMode()) {
return false;
}
ApplicationInfo app = (ApplicationInfo) v.getTag();
app = new ApplicationInfo(app);
mDragController.startDrag(v, this, app, DragController.DRAG_ACTION_COPY);
mLauncher.closeAllApps(true);
return true;
}
@Override
public void onDropCompleted(View target, boolean success) {
// do nothing
}
@Override
public boolean isVisible() {
return mZoom > 0.001f;
}
@Override
public boolean isAnimating() {
return (getAnimation() != null);
}
private ArrayList<ApplicationInfo> rebuildFilteredApps(ArrayList<ApplicationInfo> apps) {
ArrayList<ApplicationInfo> filteredApps = new ArrayList<ApplicationInfo>();
if (mAppFilter == ALL_APPS_FLAG) {
return apps;
} else {
final int length = apps.size();
for (int i = 0; i < length; ++i) {
ApplicationInfo info = apps.get(i);
if ((info.flags & mAppFilter) > 0) {
filteredApps.add(info);
}
}
}
return filteredApps;
}
@Override
public void setApps(ArrayList<ApplicationInfo> list) {
mApps = list;
Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
mFilteredApps = rebuildFilteredApps(mApps);
invalidatePageData();
}
private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// we add it in place, in alphabetical order
final int count = list.size();
for (int i = 0; i < count; ++i) {
final ApplicationInfo info = list.get(i);
final int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
if (index < 0) {
mApps.add(-(index + 1), info);
}
}
mFilteredApps = rebuildFilteredApps(mApps);
}
@Override
public void addApps(ArrayList<ApplicationInfo> list) {
addAppsWithoutInvalidate(list);
invalidatePageData();
}
private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// loop through all the apps and remove apps that have the same component
final int length = list.size();
for (int i = 0; i < length; ++i) {
int removeIndex = findAppByComponent(mApps, list.get(i));
if (removeIndex > -1) {
mApps.remove(removeIndex);
}
}
mFilteredApps = rebuildFilteredApps(mApps);
}
@Override
public void removeApps(ArrayList<ApplicationInfo> list) {
removeAppsWithoutInvalidate(list);
invalidatePageData();
}
@Override
public void updateApps(ArrayList<ApplicationInfo> list) {
removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list);
invalidatePageData();
}
private int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
ComponentName removeComponent = item.intent.getComponent();
final int length = list.size();
for (int i = 0; i < length; ++i) {
ApplicationInfo info = list.get(i);
if (info.intent.getComponent().equals(removeComponent)) {
return i;
}
}
return -1;
}
@Override
public void dumpState() {
ApplicationInfo.dumpApplicationInfoList(TAG, "mApps", mApps);
}
@Override
public void surrender() {
// do nothing?
}
@Override
public void syncPages() {
// ensure that we have the right number of pages
int numPages = (int) Math.ceil((float) mFilteredApps.size() / (mCellCountX * mCellCountY));
int curNumPages = getChildCount();
// remove any extra pages after the "last" page
int extraPageDiff = curNumPages - numPages;
for (int i = 0; i < extraPageDiff; ++i) {
removeViewAt(numPages);
}
// add any necessary pages
for (int i = curNumPages; i < numPages; ++i) {
PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
layout.setCellCount(mCellCountX, mCellCountY);
layout.setDimmedBitmapSetupListener(this);
addView(layout);
}
// bound the current page
setCurrentScreen(Math.max(0, Math.min(numPages - 1, getCurrentScreen())));
}
@Override
public void syncPageItems(int page) {
// ensure that we have the right number of items on the pages
final int cellsPerPage = mCellCountX * mCellCountY;
final int startIndex = page * cellsPerPage;
final int endIndex = Math.min(startIndex + cellsPerPage, mFilteredApps.size());
PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
final int curNumPageItems = layout.getChildCount();
final int numPageItems = endIndex - startIndex;
// remove any extra items
int extraPageItemsDiff = curNumPageItems - numPageItems;
for (int i = 0; i < extraPageItemsDiff; ++i) {
layout.removeViewAt(numPageItems);
}
// add any necessary items
for (int i = curNumPageItems; i < numPageItems; ++i) {
TextView text = (TextView) mInflater.inflate(R.layout.all_apps_paged_view_application, layout, false);
text.setOnClickListener(this);
text.setOnLongClickListener(this);
layout.addViewToCellLayout(text, -1, i,
new PagedViewCellLayout.LayoutParams(0, 0, 1, 1));
}
// actually reapply to the existing text views
for (int i = startIndex; i < endIndex; ++i) {
int index = i - startIndex;
ApplicationInfo info = mFilteredApps.get(i);
TextView text = (TextView) layout.getChildAt(index);
text.setCompoundDrawablesWithIntrinsicBounds(null,
new BitmapDrawable(info.iconBitmap), null, null);
text.setText(info.title);
text.setTag(info);
PagedViewCellLayout.LayoutParams params =
(PagedViewCellLayout.LayoutParams) text.getLayoutParams();
params.cellX = index % mCellCountX;
params.cellY = index / mCellCountX;
}
}
@Override
public void onPreUpdateDimmedBitmap(PagedViewCellLayout layout) {
// disable all children text for now
final int childCount = layout.getChildCount();
for (int i = 0; i < childCount; ++i) {
TextView text = (TextView) layout.getChildAt(i);
text.setText("");
}
}
@Override
public void onPostUpdateDimmedBitmap(PagedViewCellLayout layout) {
// re-enable all children text
final int childCount = layout.getChildCount();
for (int i = 0; i < childCount; ++i) {
TextView text = (TextView) layout.getChildAt(i);
final ApplicationInfo info = (ApplicationInfo) text.getTag();
text.setText(info.title);
}
}
}