343 lines
11 KiB
Java
343 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2007 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.example.android.home;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.res.TypedArray;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.LayoutInflater;
|
|
import android.widget.TextView;
|
|
import android.*;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* The ApplicationsStackLayout is a specialized layout used for the purpose of the home screen
|
|
* only. This layout stacks various icons in three distinct areas: the recents, the favorites
|
|
* (or faves) and the button.
|
|
*
|
|
* This layout supports two different orientations: vertical and horizontal. When horizontal,
|
|
* the areas are laid out this way:
|
|
*
|
|
* [RECENTS][FAVES][BUTTON]
|
|
*
|
|
* When vertical, the layout is the following:
|
|
*
|
|
* [RECENTS]
|
|
* [FAVES]
|
|
* [BUTTON]
|
|
*
|
|
* The layout operates from the "bottom up" (or from right to left.) This means that the button
|
|
* area will first be laid out, then the faves area, then the recents. When there are too many
|
|
* favorites, the recents area is not displayed.
|
|
*
|
|
* The following attributes can be set in XML:
|
|
*
|
|
* orientation: horizontal or vertical
|
|
* marginLeft: the left margin of each element in the stack
|
|
* marginTop: the top margin of each element in the stack
|
|
* marginRight: the right margin of each element in the stack
|
|
* marginBottom: the bottom margin of each element in the stack
|
|
*/
|
|
public class ApplicationsStackLayout extends ViewGroup implements View.OnClickListener {
|
|
public static final int HORIZONTAL = 0;
|
|
public static final int VERTICAL = 1;
|
|
|
|
private View mButton;
|
|
private LayoutInflater mInflater;
|
|
|
|
private int mFavoritesEnd;
|
|
private int mFavoritesStart;
|
|
|
|
private List<ApplicationInfo> mFavorites;
|
|
private List<ApplicationInfo> mRecents;
|
|
|
|
private int mOrientation = VERTICAL;
|
|
|
|
private int mMarginLeft;
|
|
private int mMarginTop;
|
|
private int mMarginRight;
|
|
private int mMarginBottom;
|
|
|
|
private Rect mDrawRect = new Rect();
|
|
|
|
private Drawable mBackground;
|
|
private int mIconSize;
|
|
|
|
public ApplicationsStackLayout(Context context) {
|
|
super(context);
|
|
initLayout();
|
|
}
|
|
|
|
public ApplicationsStackLayout(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
|
|
TypedArray a =
|
|
context.obtainStyledAttributes(attrs, R.styleable.ApplicationsStackLayout);
|
|
|
|
mOrientation = a.getInt(R.styleable.ApplicationsStackLayout_stackOrientation, VERTICAL);
|
|
|
|
mMarginLeft = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginLeft, 0);
|
|
mMarginTop = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginTop, 0);
|
|
mMarginRight = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginRight, 0);
|
|
mMarginBottom = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginBottom, 0);
|
|
|
|
a.recycle();
|
|
|
|
mIconSize = (int) getResources().getDimension(android.R.dimen.app_icon_size);
|
|
|
|
initLayout();
|
|
}
|
|
|
|
private void initLayout() {
|
|
mInflater = LayoutInflater.from(getContext());
|
|
mButton = mInflater.inflate(R.layout.all_applications_button, this, false);
|
|
addView(mButton);
|
|
|
|
mBackground = getBackground();
|
|
setBackgroundDrawable(null);
|
|
setWillNotDraw(false);
|
|
}
|
|
|
|
/**
|
|
* Return the current orientation, either VERTICAL (default) or HORIZONTAL.
|
|
*
|
|
* @return the stack orientation
|
|
*/
|
|
public int getOrientation() {
|
|
return mOrientation;
|
|
}
|
|
|
|
@Override
|
|
protected void onDraw(Canvas canvas) {
|
|
final Drawable background = mBackground;
|
|
|
|
final int right = getWidth();
|
|
final int bottom = getHeight();
|
|
|
|
// Draw behind recents
|
|
if (mOrientation == VERTICAL) {
|
|
mDrawRect.set(0, 0, right, mFavoritesStart);
|
|
} else {
|
|
mDrawRect.set(0, 0, mFavoritesStart, bottom);
|
|
}
|
|
background.setBounds(mDrawRect);
|
|
background.draw(canvas);
|
|
|
|
// Draw behind favorites
|
|
if (mFavoritesStart > -1) {
|
|
if (mOrientation == VERTICAL) {
|
|
mDrawRect.set(0, mFavoritesStart, right, mFavoritesEnd);
|
|
} else {
|
|
mDrawRect.set(mFavoritesStart, 0, mFavoritesEnd, bottom);
|
|
}
|
|
background.setBounds(mDrawRect);
|
|
background.draw(canvas);
|
|
}
|
|
|
|
super.onDraw(canvas);
|
|
}
|
|
|
|
@Override
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
|
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
|
|
|
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
|
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
|
|
|
if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
|
|
throw new IllegalStateException("ApplicationsStackLayout can only be used with "
|
|
+ "measure spec mode=EXACTLY");
|
|
}
|
|
|
|
setMeasuredDimension(widthSize, heightSize);
|
|
}
|
|
|
|
@Override
|
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
removeAllApplications();
|
|
|
|
LayoutParams layoutParams = mButton.getLayoutParams();
|
|
final int widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
|
|
final int heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
|
|
mButton.measure(widthSpec, heightSpec);
|
|
|
|
if (mOrientation == VERTICAL) {
|
|
layoutVertical();
|
|
} else {
|
|
layoutHorizontal();
|
|
}
|
|
}
|
|
|
|
private void layoutVertical() {
|
|
int childLeft = 0;
|
|
int childTop = getHeight();
|
|
|
|
int childWidth = mButton.getMeasuredWidth();
|
|
int childHeight = mButton.getMeasuredHeight();
|
|
|
|
childTop -= childHeight + mMarginBottom;
|
|
mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
|
childTop -= mMarginTop;
|
|
mFavoritesEnd = childTop - mMarginBottom;
|
|
|
|
int oldChildTop = childTop;
|
|
childTop = stackApplications(mFavorites, childLeft, childTop);
|
|
if (childTop != oldChildTop) {
|
|
mFavoritesStart = childTop + mMarginTop;
|
|
} else {
|
|
mFavoritesStart = -1;
|
|
}
|
|
|
|
stackApplications(mRecents, childLeft, childTop);
|
|
}
|
|
|
|
private void layoutHorizontal() {
|
|
int childLeft = getWidth();
|
|
int childTop = 0;
|
|
|
|
int childWidth = mButton.getMeasuredWidth();
|
|
int childHeight = mButton.getMeasuredHeight();
|
|
|
|
childLeft -= childWidth;
|
|
mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
|
childLeft -= mMarginLeft;
|
|
mFavoritesEnd = childLeft - mMarginRight;
|
|
|
|
int oldChildLeft = childLeft;
|
|
childLeft = stackApplications(mFavorites, childLeft, childTop);
|
|
if (childLeft != oldChildLeft) {
|
|
mFavoritesStart = childLeft + mMarginLeft;
|
|
} else {
|
|
mFavoritesStart = -1;
|
|
}
|
|
|
|
stackApplications(mRecents, childLeft, childTop);
|
|
}
|
|
|
|
private int stackApplications(List<ApplicationInfo> applications, int childLeft, int childTop) {
|
|
LayoutParams layoutParams;
|
|
int widthSpec;
|
|
int heightSpec;
|
|
int childWidth;
|
|
int childHeight;
|
|
|
|
final boolean isVertical = mOrientation == VERTICAL;
|
|
|
|
final int count = applications.size();
|
|
for (int i = count - 1; i >= 0; i--) {
|
|
final ApplicationInfo info = applications.get(i);
|
|
final View view = createApplicationIcon(mInflater, this, info);
|
|
|
|
layoutParams = view.getLayoutParams();
|
|
widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY);
|
|
heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
|
|
view.measure(widthSpec, heightSpec);
|
|
|
|
childWidth = view.getMeasuredWidth();
|
|
childHeight = view.getMeasuredHeight();
|
|
|
|
if (isVertical) {
|
|
childTop -= childHeight + mMarginBottom;
|
|
|
|
if (childTop < 0) {
|
|
childTop += childHeight + mMarginBottom;
|
|
break;
|
|
}
|
|
} else {
|
|
childLeft -= childWidth + mMarginRight;
|
|
|
|
if (childLeft < 0) {
|
|
childLeft += childWidth + mMarginRight;
|
|
break;
|
|
}
|
|
}
|
|
|
|
addViewInLayout(view, -1, layoutParams);
|
|
|
|
view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
|
|
|
|
if (isVertical) {
|
|
childTop -= mMarginTop;
|
|
} else {
|
|
childLeft -= mMarginLeft;
|
|
}
|
|
}
|
|
|
|
return isVertical ? childTop : childLeft;
|
|
}
|
|
|
|
private void removeAllApplications() {
|
|
final int count = getChildCount();
|
|
for (int i = count - 1; i >= 0; i--) {
|
|
final View view = getChildAt(i);
|
|
if (view != mButton) {
|
|
removeViewAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private View createApplicationIcon(LayoutInflater inflater,
|
|
ViewGroup group, ApplicationInfo info) {
|
|
|
|
TextView textView = (TextView) inflater.inflate(R.layout.favorite, group, false);
|
|
|
|
info.icon.setBounds(0, 0, mIconSize, mIconSize);
|
|
textView.setCompoundDrawables(null, info.icon, null, null);
|
|
textView.setText(info.title);
|
|
|
|
textView.setTag(info.intent);
|
|
textView.setOnClickListener(this);
|
|
|
|
return textView;
|
|
}
|
|
|
|
/**
|
|
* Sets the list of favorites.
|
|
*
|
|
* @param applications the applications to put in the favorites area
|
|
*/
|
|
public void setFavorites(List<ApplicationInfo> applications) {
|
|
mFavorites = applications;
|
|
requestLayout();
|
|
}
|
|
|
|
/**
|
|
* Sets the list of recents.
|
|
*
|
|
* @param applications the applications to put in the recents area
|
|
*/
|
|
public void setRecents(List<ApplicationInfo> applications) {
|
|
mRecents = applications;
|
|
requestLayout();
|
|
}
|
|
|
|
public void onClick(View v) {
|
|
getContext().startActivity((Intent) v.getTag());
|
|
}
|
|
}
|