Show color chips for combined view.

Show color chips for account rows and message items on the combined view.

Moved hard-coded color values to resource.

Bug 3138001

Change-Id: Ib93fb9d6e9592ebd0c297f83c3dee2358a80508f
This commit is contained in:
Makoto Onuki 2010-11-22 13:47:11 -08:00
parent 46e60b51e2
commit 5b81690de1
14 changed files with 221 additions and 88 deletions

View File

@ -54,4 +54,13 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
/>
<!-- Color chips are shown only for account rows on combined view. -->
<View
android:id="@+id/color_chip"
android:layout_width="32dip"
android:layout_height="8dip"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:visibility="gone"
/>
</com.android.email.activity.MailboxListItem>

View File

@ -177,4 +177,13 @@
<!-- TYPE_JUNK = 7 -->
<item>@drawable/ic_list_spam</item>
</array>
<!-- Account color chips on combined view -->
<array name="combined_view_account_colors" translatable="false">
<item>@color/combined_view_account_color_1</item>
<item>@color/combined_view_account_color_2</item>
<item>@color/combined_view_account_color_3</item>
<item>@color/combined_view_account_color_4</item>
<item>@color/combined_view_account_color_5</item>
</array>
</resources>

View File

@ -29,4 +29,12 @@
<!-- STOPSHIP Use same color as EditText tray? -->
<color name="divider_color">#ff808080</color>
<!-- Account color chips on combined view -->
<!-- STOPSHIP Replace with final colors -->
<color name="combined_view_account_color_1">#ff0080ff</color>
<color name="combined_view_account_color_2">#ff800040</color>
<color name="combined_view_account_color_3">#ff009b8b</color>
<color name="combined_view_account_color_4">#fff4fd04</color>
<color name="combined_view_account_color_5">#ffe65020</color>
</resources>

View File

@ -4,9 +4,9 @@
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.
@ -26,4 +26,8 @@
<dimen name="message_list_item_height_wide">64dip</dimen>
<dimen name="message_list_item_height_narrow">72dip</dimen>
<dimen name="message_list_item_minimum_width_wide_mode">720dip</dimen>
<dimen name="message_list_item_color_tip_width">35dip</dimen>
<dimen name="message_list_item_color_tip_height">8dip</dimen>
<dimen name="message_list_item_color_tip_right_margin_on_narrow">32dip</dimen>
<dimen name="message_list_item_color_tip_right_margin_on_wide">65dip</dimen>
</resources>

View File

@ -162,49 +162,10 @@ public class Email extends Application {
public static final String EXCHANGE_ACCOUNT_MANAGER_TYPE = "com.android.exchange";
public static final String POP_IMAP_ACCOUNT_MANAGER_TYPE = "com.android.email";
// The color chip resources and the RGB color values in the array below must be kept in sync
private static final int[] ACCOUNT_COLOR_CHIP_RES_IDS = new int[] {
R.drawable.appointment_indicator_leftside_1,
R.drawable.appointment_indicator_leftside_2,
R.drawable.appointment_indicator_leftside_3,
R.drawable.appointment_indicator_leftside_4,
R.drawable.appointment_indicator_leftside_5,
R.drawable.appointment_indicator_leftside_6,
R.drawable.appointment_indicator_leftside_7,
R.drawable.appointment_indicator_leftside_8,
R.drawable.appointment_indicator_leftside_9,
};
private static final int[] ACCOUNT_COLOR_CHIP_RGBS = new int[] {
0x71aea7,
0x621919,
0x18462f,
0xbf8e52,
0x001f79,
0xa8afc2,
0x6b64c4,
0x738359,
0x9d50a4,
};
private static File sTempDirectory;
private static Thread sUiThread;
/* package for testing */ static int getColorIndexFromAccountId(long accountId) {
// Account id is 1-based, so - 1.
// Use abs so that it won't possibly return negative.
return Math.abs((int) (accountId - 1) % ACCOUNT_COLOR_CHIP_RES_IDS.length);
}
public static int getAccountColorResourceId(long accountId) {
return ACCOUNT_COLOR_CHIP_RES_IDS[getColorIndexFromAccountId(accountId)];
}
public static int getAccountColor(long accountId) {
return ACCOUNT_COLOR_CHIP_RGBS[getColorIndexFromAccountId(accountId)];
}
public static void setTempDirectory(Context context) {
sTempDirectory = context.getCacheDir();
}

View File

@ -0,0 +1,73 @@
/*
* 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.email;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
/**
* Helper class to load resources.
*/
public class ResourceHelper {
private static ResourceHelper sInstance;
private final Context mContext;
private final Resources mResources;
private final int[] mAccountColors;
private final Paint[] mAccountColorPaints;
private ResourceHelper(Context context) {
mContext = context;
mResources = mContext.getResources();
mAccountColors = mResources.getIntArray(R.array.combined_view_account_colors);
mAccountColorPaints = new Paint[mAccountColors.length];
for (int i = 0; i < mAccountColors.length; i++) {
Paint p = new Paint();
p.setColor(mAccountColors[i]);
mAccountColorPaints[i] = p;
}
}
public static synchronized ResourceHelper getInstance(Context context) {
if (sInstance == null) {
sInstance = new ResourceHelper(context);
}
return sInstance;
}
/* package */ int getAccountColorIndex(long accountId) {
// The account ID is 1-based, so -1.
// Use abs so that it'd work for -1 as well.
return Math.abs((int) ((accountId - 1) % mAccountColors.length));
}
/**
* @return color for an account.
*/
public int getAccountColor(long accountId) {
return mAccountColors[getAccountColorIndex(accountId)];
}
/**
* @return {@link Paint} equivalent to {@link #getAccountColor}.
*/
public Paint getAccountColorPaint(long accountId) {
return mAccountColorPaints[getAccountColorIndex(accountId)];
}
}

View File

@ -218,9 +218,9 @@ public class AccountsAdapter extends CursorAdapter {
itemView.mAccountId = cursor.getLong(Account.CONTENT_ID_COLUMN);
long accountId = cursor.getLong(Account.CONTENT_ID_COLUMN);
View chipView = view.findViewById(R.id.chip);
chipView.setBackgroundResource(Email.getAccountColorResourceId(accountId));
chipView.setVisibility(View.VISIBLE);
// No color chip for now. TODO Revisit for phone UI
view.findViewById(R.id.chip).setVisibility(View.GONE);
String text = cursor.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
if (text != null) {

View File

@ -18,6 +18,7 @@ package com.android.email.activity;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.ResourceHelper;
import com.android.email.Utility;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.email.provider.EmailContent;
@ -111,6 +112,7 @@ import android.widget.TextView;
private final Context mContext;
private final LayoutInflater mInflater;
private final ResourceHelper mResourceHelper;
private final int mMode;
private static boolean sEnableUpdate = true;
@ -122,6 +124,7 @@ import android.widget.TextView;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mMode = mode;
mCallback = callback;
mResourceHelper = ResourceHelper.getInstance(mContext);
}
/**
@ -260,12 +263,13 @@ import android.widget.TextView;
}
private void bindViewNormalMode(View view, Context context, Cursor cursor) {
final boolean isAccount = isAccountRow(cursor);
final int type = cursor.getInt(COLUMN_TYPE);
final long mailboxId = cursor.getLong(COLUMN_ID);
final long id = cursor.getLong(COLUMN_ID);
MailboxListItem listItem = (MailboxListItem)view;
listItem.mMailboxType = type;
listItem.mMailboxId = mailboxId;
listItem.mMailboxId = id;
listItem.mAdapter = this;
// Set the background depending on whether we're in drag mode, the mailbox is a valid
@ -301,7 +305,15 @@ import android.widget.TextView;
// Set folder icon
((ImageView) view.findViewById(R.id.folder_icon)).setImageDrawable(
Utility.FolderProperties.getInstance(context).getIcon(type, mailboxId));
Utility.FolderProperties.getInstance(context).getIcon(type, id));
final View chipView = view.findViewById(R.id.color_chip);
if (isAccount) {
chipView.setVisibility(View.VISIBLE);
chipView.setBackgroundColor(mResourceHelper.getAccountColor(id));
} else {
chipView.setVisibility(View.GONE);
}
}
private View newViewNormalMode(Context context, Cursor cursor, ViewGroup parent) {

View File

@ -1089,6 +1089,7 @@ public class MessageListFragment extends ListFragment
// Update the list
mListAdapter.changeCursor(cursor);
mListAdapter.setShowColorChips(mMailboxId < 0); // Show chips if combined view
setListAdapter(mListAdapter);
setListShown(true);

View File

@ -23,6 +23,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Typeface;
@ -98,6 +99,8 @@ public class MessageListItem extends View {
public boolean mHasAttachment = false;
public boolean mHasInvite = true;
public boolean mIsFavorite = false;
/** {@link Paint} for account color chips. null if no chips should be drawn. */
public Paint mColorChipPaint;
private int mMode = -1;
@ -117,6 +120,10 @@ public class MessageListItem extends View {
private static int sItemHeightWide;
private static int sItemHeightNarrow;
private static int sMinimumWidthWideMode;
private static int sColorTipWidth;
private static int sColorTipHeight;
private static int sColorTipRightMarginOnNarrow;
private static int sColorTipRightMarginOnWide;
public int mSnippetLineCount = NEEDS_LAYOUT;
private final CharSequence[] mSnippetLines = new CharSequence[MAX_SUBJECT_SNIPPET_LINES];
@ -147,6 +154,14 @@ public class MessageListItem extends View {
r.getDimensionPixelSize(R.dimen.message_list_item_height_narrow);
sMinimumWidthWideMode =
r.getDimensionPixelSize(R.dimen.message_list_item_minimum_width_wide_mode);
sColorTipWidth =
r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_width);
sColorTipHeight =
r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_height);
sColorTipRightMarginOnNarrow =
r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_right_margin_on_narrow);
sColorTipRightMarginOnWide =
r.getDimensionPixelSize(R.dimen.message_list_item_color_tip_right_margin_on_wide);
sDefaultPaint.setTypeface(Typeface.DEFAULT);
sDefaultPaint.setTextSize(sTextSize);
@ -312,6 +327,14 @@ public class MessageListItem extends View {
snippetY = senderY + lineHeight + sPaddingVerySmall;
}
// Draw the color chip
if (mColorChipPaint != null) {
final int rightMargin = (mMode == MODE_WIDE)
? sColorTipRightMarginOnWide : sColorTipRightMarginOnNarrow;
final int x = mViewWidth - rightMargin - sColorTipWidth;
canvas.drawRect(x, 0, x + sColorTipWidth, sColorTipHeight, mColorChipPaint);
}
// Draw the checkbox
int checkboxLeft = (sCheckboxHitWidth - sSelectedIconOff.getWidth()) / 2;
int checkboxTop = (mViewHeight - sSelectedIconOff.getHeight()) / 2;

View File

@ -18,6 +18,7 @@ package com.android.email.activity;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.ResourceHelper;
import com.android.email.Utility;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.email.provider.EmailContent;
@ -64,6 +65,11 @@ import java.util.Set;
public static final int COLUMN_FLAGS = 9;
public static final int COLUMN_SNIPPET = 10;
private final ResourceHelper mResourceHelper;
/** If true, show color chips. */
private boolean mShowColorChips;
/**
* Set of seleced message IDs.
*/
@ -84,6 +90,7 @@ import java.util.Set;
public MessagesAdapter(Context context, Callback callback) {
super(context.getApplicationContext(), null, 0 /* no auto requery */);
mResourceHelper = ResourceHelper.getInstance(context);
mCallback = callback;
}
@ -105,6 +112,13 @@ import java.util.Set;
}
}
/**
* Set true for combined mailboxes.
*/
public void setShowColorChips(boolean show) {
mShowColorChips = show;
}
public Set<Long> getSelectedSet() {
return mSelectedSet;
}
@ -122,7 +136,8 @@ import java.util.Set;
// Load the public fields in the view (for later use)
itemView.mMessageId = cursor.getLong(COLUMN_ID);
itemView.mMailboxId = cursor.getLong(COLUMN_MAILBOX_KEY);
itemView.mAccountId = cursor.getLong(COLUMN_ACCOUNT_KEY);
final long accountId = cursor.getLong(COLUMN_ACCOUNT_KEY);
itemView.mAccountId = accountId;
itemView.mRead = cursor.getInt(COLUMN_READ) != 0;
itemView.mIsFavorite = cursor.getInt(COLUMN_FAVORITE) != 0;
itemView.mHasInvite =
@ -132,6 +147,8 @@ import java.util.Set;
itemView.mSender = cursor.getString(COLUMN_DISPLAY_NAME);
itemView.mSnippet = cursor.getString(COLUMN_SNIPPET);
itemView.mSnippetLineCount = MessageListItem.NEEDS_LAYOUT;
itemView.mColorChipPaint =
mShowColorChips ? mResourceHelper.getAccountColorPaint(accountId) : null;
String text = cursor.getString(COLUMN_SUBJECT);
String snippet = cursor.getString(COLUMN_SNIPPET);
@ -199,15 +216,15 @@ import java.util.Set;
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
Log.d(Email.LOG_TAG, "MessagesAdapter createLoader mailboxId=" + mailboxId);
}
return new MessagesCursor(context, mailboxId);
return new MessagesCursorLoader(context, mailboxId);
}
private static class MessagesCursor extends ThrottlingCursorLoader {
private static class MessagesCursorLoader extends ThrottlingCursorLoader {
private final Context mContext;
private final long mMailboxId;
public MessagesCursor(Context context, long mailboxId) {
public MessagesCursorLoader(Context context, long mailboxId) {
// Initialize with no where clause. We'll set it later.
super(context, EmailContent.Message.CONTENT_URI,
MESSAGE_PROJECTION, null, null,

View File

@ -18,6 +18,7 @@ package com.android.exchange.utility;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.ResourceHelper;
import com.android.email.Utility;
import com.android.email.mail.Address;
import com.android.email.provider.EmailContent;
@ -1215,7 +1216,8 @@ public class CalendarUtilities {
// TODO Coordinate account colors w/ Calendar, if possible
// Make Email account color opaque
cv.put(Calendars.COLOR, 0xFF000000 | Email.getAccountColor(account.mId));
int color = ResourceHelper.getInstance(service.mContext).getAccountColor(account.mId);
cv.put(Calendars.COLOR, color);
cv.put(Calendars.TIMEZONE, Time.getCurrentTimezone());
cv.put(Calendars.ACCESS_LEVEL, Calendars.OWNER_ACCESS);
cv.put(Calendars.OWNER_ACCOUNT, account.mEmailAddress);

View File

@ -1,36 +0,0 @@
/*
* 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.email;
import junit.framework.TestCase;
public class EmailTest extends TestCase {
public void testGetColorIndexFromAccountId() {
// First account (id=1) gets index 0.
assertEquals(0, Email.getColorIndexFromAccountId(1));
assertEquals(1, Email.getColorIndexFromAccountId(2));
// Never return negative.
assertTrue(Email.getColorIndexFromAccountId(-5) >= 0);
// Shouldn't throw ArrayIndexOutOfRange or anything.
for (int i = -100; i < 100; i++) {
Email.getAccountColorResourceId(i);
Email.getAccountColor(i);
}
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.email;
import android.graphics.Paint;
import android.test.AndroidTestCase;
public class ResourceHelperTest extends AndroidTestCase {
private ResourceHelper mResourceHelper;
@Override
protected void setUp() throws Exception {
super.setUp();
mResourceHelper = ResourceHelper.getInstance(getContext());
}
public void testGetAccountColor() {
Integer lastColor = null;
Paint lastPaint = null;
for (long accountId = -1; accountId < 100; accountId++) {
// Shouldn't throw any exception (such as IndexOutOfRange)
Integer color = mResourceHelper.getAccountColor(accountId);
Paint paint = mResourceHelper.getAccountColorPaint(accountId);
// Should be different from the previous one
assertNotNull(color);
assertNotNull(paint);
assertFalse(color.equals(lastColor));
assertFalse(paint.equals(lastPaint));
lastColor = color;
lastPaint = paint;
}
}
}