Merge "Rebuilt notification list using a new custom layout."

This commit is contained in:
Daniel Sandler
2011-06-13 07:29:39 -07:00
committed by Android (Google) Code Review
8 changed files with 289 additions and 11 deletions

View File

@@ -1,6 +1,6 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="65dp"
android:layout_height="@dimen/notification_height"
>
<ImageButton

View File

@@ -18,7 +18,9 @@
*/
-->
<com.android.systemui.statusbar.phone.ExpandedView xmlns:android="http://schemas.android.com/apk/res/android"
<com.android.systemui.statusbar.phone.ExpandedView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:orientation="vertical"
android:focusable="true"
android:descendantFocusability="afterDescendants"
@@ -97,10 +99,11 @@
android:textAppearance="@style/TextAppearance.StatusBar.Title"
android:text="@string/status_bar_ongoing_events_title"
/>
<LinearLayout android:id="@+id/ongoingItems"
<com.android.systemui.statusbar.policy.NotificationRowLayout
android:id="@+id/ongoingItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
systemui:rowHeight="@dimen/notification_height"
/>
<TextView android:id="@+id/latestTitle"
@@ -111,10 +114,11 @@
android:textAppearance="@style/TextAppearance.StatusBar.Title"
android:text="@string/status_bar_latest_events_title"
/>
<LinearLayout android:id="@+id/latestItems"
<com.android.systemui.statusbar.policy.NotificationRowLayout
android:id="@+id/latestItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
systemui:rowHeight="@dimen/notification_height"
/>
</LinearLayout>
</ScrollView>

View File

@@ -1,6 +1,6 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="65dp"
android:layout_height="@dimen/notification_height"
>
<ImageButton

View File

@@ -24,5 +24,8 @@
<declare-styleable name="NotificationLinearLayout">
<attr name="insetLeft" format="dimension" />
</declare-styleable>
<declare-styleable name="NotificationRowLayout">
<attr name="rowHeight" format="dimension" />
</declare-styleable>
</resources>

View File

@@ -47,5 +47,8 @@
<!-- thickness (height) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">42dp</dimen>
<!-- thickness (height) of each notification row, including any separators or padding -->
<dimen name="notification_height">65dp</dimen>
</resources>

View File

@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
import android.animation.LayoutTransition;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Display;
@@ -37,6 +38,8 @@ public class ExpandedView extends LinearLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
setLayerType(LAYER_TYPE_HARDWARE, null);
}
/** We want to shrink down to 0, and ignore the background. */

View File

@@ -130,11 +130,11 @@ public class PhoneStatusBar extends StatusBar {
// ongoing
NotificationData mOngoing = new NotificationData();
TextView mOngoingTitle;
LinearLayout mOngoingItems;
ViewGroup mOngoingItems;
// latest
NotificationData mLatest = new NotificationData();
TextView mLatestTitle;
LinearLayout mLatestItems;
ViewGroup mLatestItems;
// position
int[] mPositionTmp = new int[2];
boolean mExpanded;
@@ -268,9 +268,9 @@ public class PhoneStatusBar extends StatusBar {
mExpandedView = expanded;
mExpandedContents = expanded.findViewById(R.id.notificationLinearLayout);
mOngoingTitle = (TextView)expanded.findViewById(R.id.ongoingTitle);
mOngoingItems = (LinearLayout)expanded.findViewById(R.id.ongoingItems);
mOngoingItems = (ViewGroup)expanded.findViewById(R.id.ongoingItems);
mLatestTitle = (TextView)expanded.findViewById(R.id.latestTitle);
mLatestItems = (LinearLayout)expanded.findViewById(R.id.latestItems);
mLatestItems = (ViewGroup)expanded.findViewById(R.id.latestItems);
mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
mClearButton = (TextView)expanded.findViewById(R.id.clear_all_button);
mClearButton.setOnClickListener(mClearButtonListener);

View File

@@ -0,0 +1,265 @@
/*
* Copyright (C) 2011 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.systemui.statusbar.policy;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.HashSet;
import com.android.systemui.R;
public class NotificationRowLayout extends ViewGroup {
private static final String TAG = "NotificationRowLayout";
private static final boolean DEBUG = false;
private static final boolean ANIMATE_LAYOUT = true;
private static final int ANIM_LEN = DEBUG ? 5000 : 250;
Rect mTmpRect = new Rect();
int mNumRows = 0;
int mRowHeight = 0;
int mHeight = 0;
HashSet<View> mAppearingViews = new HashSet<View>();
HashSet<View> mDisappearingViews = new HashSet<View>();
public NotificationRowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationRowLayout,
defStyle, 0);
mRowHeight = a.getDimensionPixelSize(R.styleable.NotificationRowLayout_rowHeight, 0);
a.recycle();
setLayoutTransition(null);
if (DEBUG) {
setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
Slog.d(TAG, "view added: " + child + "; new count: " + getChildCount());
}
@Override
public void onChildViewRemoved(View parent, View child) {
Slog.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
}
});
setBackgroundColor(0x80FF8000);
}
}
//**
@Override
public void addView(View child, int index, LayoutParams params) {
super.addView(child, index, params);
final View childF = child;
if (ANIMATE_LAYOUT) {
mAppearingViews.add(child);
child.setPivotY(0);
AnimatorSet a = new AnimatorSet();
a.playTogether(
ObjectAnimator.ofFloat(child, "alpha", 0f, 1f)
// ,ObjectAnimator.ofFloat(child, "scaleY", 0f, 1f)
);
a.setDuration(ANIM_LEN);
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mAppearingViews.remove(childF);
}
});
a.start();
requestLayout(); // start the container animation
}
}
@Override
public void removeView(View child) {
final View childF = child;
if (ANIMATE_LAYOUT) {
if (mAppearingViews.contains(child)) {
mAppearingViews.remove(child);
}
mDisappearingViews.add(child);
child.setPivotY(0);
AnimatorSet a = new AnimatorSet();
a.playTogether(
ObjectAnimator.ofFloat(child, "alpha", 0f)
// ,ObjectAnimator.ofFloat(child, "scaleY", 0f)
,ObjectAnimator.ofFloat(child, "translationX", 300f)
);
a.setDuration(ANIM_LEN);
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
NotificationRowLayout.super.removeView(childF);
childF.setAlpha(1f);
mDisappearingViews.remove(childF);
}
});
a.start();
requestLayout(); // start the container animation
} else {
super.removeView(child);
}
}
//**
@Override
public void onFinishInflate() {
super.onFinishInflate();
setWillNotDraw(false);
}
@Override
public void onDraw(android.graphics.Canvas c) {
super.onDraw(c);
if (DEBUG) {
Slog.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
+ getMeasuredHeight() + "px");
c.save();
c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
android.graphics.Region.Op.DIFFERENCE);
c.drawColor(0xFFFF8000);
c.restore();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int count = getChildCount();
// pass 1: count the number of non-GONE views
int numRows = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
if (mDisappearingViews.contains(child)) {
continue;
}
numRows++;
}
if (numRows != mNumRows) {
// uh oh, now you made us go and do work
final int computedHeight = numRows * mRowHeight;
if (DEBUG) {
Slog.d(TAG, String.format("rows went from %d to %d, resizing to %dpx",
mNumRows, numRows, computedHeight));
}
mNumRows = numRows;
if (ANIMATE_LAYOUT && isShown()) {
ObjectAnimator.ofInt(this, "forcedHeight", computedHeight)
.setDuration(ANIM_LEN)
.start();
} else {
setForcedHeight(computedHeight);
}
}
// pass 2: you know, do the measuring
final int childWidthMS = widthMeasureSpec;
final int childHeightMS = MeasureSpec.makeMeasureSpec(
mRowHeight, MeasureSpec.EXACTLY);
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
child.measure(childWidthMS, childHeightMS);
}
setMeasuredDimension(
getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
resolveSize(getForcedHeight(), heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int width = right - left;
final int height = bottom - top;
if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
final int count = getChildCount();
int y = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == GONE) {
continue;
}
// final int thisRowHeight = (int)(
// ((mAppearingViews.contains(child) || mDisappearingViews.contains(child))
// ? child.getScaleY()
// : 1.0f)
// * mRowHeight);
final int thisRowHeight = (int)(child.getAlpha() * mRowHeight);
// child.layout(0, y, width, y + thisRowHeight);
child.layout(0, y, width, y + mRowHeight);
y += thisRowHeight;
}
}
public void setForcedHeight(int h) {
if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
if (h != mHeight) {
mHeight = h;
requestLayout();
}
}
public int getForcedHeight() {
return mHeight;
}
}