diff options
-rw-r--r-- | Android.mk | 7 | ||||
-rw-r--r-- | res/drawable-hdpi/ic_contact_picture.png | bin | 2270 -> 0 bytes | |||
-rw-r--r-- | res/drawable-mdpi/ic_contact_picture.png | bin | 1553 -> 0 bytes | |||
-rw-r--r-- | res/layout-v14/address_text_view.xml | 23 | ||||
-rw-r--r-- | res/layout/address_text_view.xml | 23 | ||||
-rw-r--r-- | res/layout/message_compose.xml | 51 | ||||
-rw-r--r-- | src/com/android/email/EmailAddressAdapter.java | 3 | ||||
-rw-r--r-- | src/com/android/email/RecipientAdapter.java | 75 | ||||
-rw-r--r-- | src/com/android/email/activity/ChipsAddressTextView.java | 75 | ||||
-rw-r--r-- | src/com/android/email/activity/MessageCompose.java | 65 |
10 files changed, 269 insertions, 53 deletions
diff --git a/Android.mk b/Android.mk index 8dd6784d8..d586615e4 100644 --- a/Android.mk +++ b/Android.mk @@ -18,12 +18,17 @@ LOCAL_PATH := $(call my-dir) # static library. All tests can be run via runtest email include $(CLEAR_VARS) +# Include res dir from chips +chips_dir := ../../../frameworks/ex/chips/res +res_dir := $(chips_dir) res LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src/com/android/email) LOCAL_SRC_FILES += $(call all-java-files-under, src/com/beetstra) -LOCAL_STATIC_JAVA_LIBRARIES := android-common com.android.emailcommon guava +LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir)) + +LOCAL_STATIC_JAVA_LIBRARIES := android-common com.android.emailcommon guava android-common-chips LOCAL_PACKAGE_NAME := Email diff --git a/res/drawable-hdpi/ic_contact_picture.png b/res/drawable-hdpi/ic_contact_picture.png Binary files differdeleted file mode 100644 index 31953dd57..000000000 --- a/res/drawable-hdpi/ic_contact_picture.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_contact_picture.png b/res/drawable-mdpi/ic_contact_picture.png Binary files differdeleted file mode 100644 index ff6c61a28..000000000 --- a/res/drawable-mdpi/ic_contact_picture.png +++ /dev/null diff --git a/res/layout-v14/address_text_view.xml b/res/layout-v14/address_text_view.xml new file mode 100644 index 000000000..ca9182400 --- /dev/null +++ b/res/layout-v14/address_text_view.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<com.android.email.activity.ChipsAddressTextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorSecondary" + android:inputType="textEmailAddress|textMultiLine" + android:imeOptions="actionNext" + android:layout_weight="1" />
\ No newline at end of file diff --git a/res/layout/address_text_view.xml b/res/layout/address_text_view.xml new file mode 100644 index 000000000..ccae747ea --- /dev/null +++ b/res/layout/address_text_view.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<com.android.email.activity.AddressTextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorSecondary" + android:inputType="textEmailAddress|textMultiLine" + android:imeOptions="actionNext" + android:layout_weight="1" />
\ No newline at end of file diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml index 56f1adebd..de644c3d9 100644 --- a/res/layout/message_compose.xml +++ b/res/layout/message_compose.xml @@ -39,19 +39,16 @@ <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" - android:layout_height="wrap_content"> - <com.android.email.activity.AddressTextView - android:id="@+id/to" + android:layout_height="wrap_content" + android:layout_marginLeft="6dip" + android:layout_marginRight="6dip"> + + <include android:id="@+id/to" + layout="@layout/address_text_view" android:layout_width="0dip" android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:attr/textColorSecondary" - android:layout_marginLeft="6dip" - android:layout_marginRight="6dip" - android:inputType="textEmailAddress|textMultiLine" - android:imeOptions="actionNext" - android:hint="@string/message_compose_to_hint" /> + android:layout_weight="1" /> + <ImageView android:id="@+id/add_cc_bcc" android:layout_height="wrap_content" @@ -64,29 +61,17 @@ android:layout_height="wrap_content" android:orientation="vertical" android:visibility="gone" + android:layout_marginLeft="6dip" + android:layout_marginRight="6dip" > - <com.android.email.activity.AddressTextView - android:id="@+id/cc" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:attr/textColorSecondary" - android:layout_marginLeft="6dip" - android:layout_marginRight="6dip" - android:inputType="textEmailAddress|textMultiLine" - android:imeOptions="actionNext" - android:hint="@string/message_compose_cc_hint" - /> - <com.android.email.activity.AddressTextView - android:id="@+id/bcc" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:attr/textColorSecondary" - android:layout_marginLeft="6dip" - android:layout_marginRight="6dip" - android:inputType="textEmailAddress|textMultiLine" - android:imeOptions="actionNext" - android:hint="@string/message_compose_bcc_hint" - /> + <include android:id="@+id/cc" + layout="@layout/address_text_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + <include android:id="@+id/bcc" + layout="@layout/address_text_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:orientation="horizontal" diff --git a/src/com/android/email/EmailAddressAdapter.java b/src/com/android/email/EmailAddressAdapter.java index cd41becc3..1c07101b3 100644 --- a/src/com/android/email/EmailAddressAdapter.java +++ b/src/com/android/email/EmailAddressAdapter.java @@ -18,6 +18,7 @@ package com.android.email; import com.android.common.contacts.BaseEmailAddressAdapter; import com.android.emailcommon.provider.Account; +import com.android.ex.chips.AccountSpecifier; import android.content.Context; import android.text.TextUtils; @@ -31,7 +32,7 @@ import android.widget.TextView; * purpose of the class is to bind the generic implementation to the resources * defined locally: strings and layouts. */ -public class EmailAddressAdapter extends BaseEmailAddressAdapter { +public class EmailAddressAdapter extends BaseEmailAddressAdapter implements AccountSpecifier { private LayoutInflater mInflater; diff --git a/src/com/android/email/RecipientAdapter.java b/src/com/android/email/RecipientAdapter.java new file mode 100644 index 000000000..38caabeb4 --- /dev/null +++ b/src/com/android/email/RecipientAdapter.java @@ -0,0 +1,75 @@ +/* + * 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.email; + +import com.android.ex.chips.BaseRecipientAdapter; +import com.android.ex.chips.RecipientEditTextView; + +import android.accounts.Account; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +public class RecipientAdapter extends BaseRecipientAdapter { + public RecipientAdapter(Context context, RecipientEditTextView list) { + super(context); + Resources r = context.getResources(); + Bitmap def = BitmapFactory.decodeResource(r, R.drawable.ic_contact_picture); + list.setChipDimensions( + r.getDrawable(R.drawable.chip_background), + r.getDrawable(R.drawable.chip_background_selected), + r.getDrawable(R.drawable.chip_background_invalid), + r.getDrawable(R.drawable.chip_delete), def, R.string.more_string, + R.layout.chips_alternate_item, + r.getDimension(R.dimen.chip_height), + r.getDimension(R.dimen.chip_padding), + r.getDimension(R.dimen.chip_text_size)); + } + + /** + * Set the account when known. Causes the search to prioritize contacts from + * that account. + */ + public void setAccount(Account account) { + if (account != null) { + // TODO: figure out how to infer the contacts account + // type from the email account + super.setAccount(new android.accounts.Account(account.name, "unknown")); + } + } + + @Override + protected int getDefaultPhotoResource() { + return R.drawable.ic_contact_picture; + } + + @Override + protected int getItemLayout() { + return R.layout.chips_recipient_dropdown_item; + } + + @Override + protected int getSeparatorLayout() { + return R.layout.chips_separator; + } + + @Override + protected int getSeparatorWithinGroupLayout() { + return R.layout.chips_separator_within_group; + } +} diff --git a/src/com/android/email/activity/ChipsAddressTextView.java b/src/com/android/email/activity/ChipsAddressTextView.java new file mode 100644 index 000000000..43c036433 --- /dev/null +++ b/src/com/android/email/activity/ChipsAddressTextView.java @@ -0,0 +1,75 @@ +/* + * 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.email.activity; + +import com.android.email.R; +import com.android.ex.chips.RecipientEditTextView; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.MultiAutoCompleteTextView; + +/** + * This is a MultiAutoCompleteTextView which sets the error state + * (@see TextView.setError) when email address validation fails. + */ +class ChipsAddressTextView extends RecipientEditTextView { + private class ForwardValidator implements Validator { + private Validator mValidator = null; + + public CharSequence fixText(CharSequence invalidText) { + mIsValid = false; + return invalidText; + } + + public boolean isValid(CharSequence text) { + return mValidator != null ? mValidator.isValid(text) : true; + } + + public void setValidator(Validator validator) { + mValidator = validator; + } + } + + private boolean mIsValid = true; + private final ForwardValidator mInternalValidator = new ForwardValidator(); + + public ChipsAddressTextView(Context context, AttributeSet attrs) { + super(context, attrs); + super.setValidator(mInternalValidator); + } + + @Override + public void setValidator(Validator validator) { + mInternalValidator.setValidator(validator); + } + + @Override + public void performValidation() { + mIsValid = true; + super.performValidation(); + markError(!mIsValid); + } + + private void markError(boolean enable) { + if (enable) { + setError(getContext().getString(R.string.message_compose_error_invalid_email)); + } else { + setError(null); + } + } +} diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java index 59e2b7dbc..2835d9822 100644 --- a/src/com/android/email/activity/MessageCompose.java +++ b/src/com/android/email/activity/MessageCompose.java @@ -22,6 +22,7 @@ import com.android.email.Email; import com.android.email.EmailAddressAdapter; import com.android.email.EmailAddressValidator; import com.android.email.R; +import com.android.email.RecipientAdapter; import com.android.email.mail.internet.EmailHtmlUtil; import com.android.emailcommon.Logging; import com.android.emailcommon.internet.MimeUtility; @@ -36,6 +37,10 @@ import com.android.emailcommon.provider.Mailbox; import com.android.emailcommon.utility.AttachmentUtilities; import com.android.emailcommon.utility.EmailAsyncTask; import com.android.emailcommon.utility.Utility; +import com.android.ex.chips.AccountSpecifier; +import com.android.ex.chips.BaseRecipientAdapter; +import com.android.ex.chips.ChipsUtil; +import com.android.ex.chips.RecipientEditTextView; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; import com.google.common.collect.Lists; @@ -200,9 +205,9 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus private boolean mMessageLoaded; private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker(); - private EmailAddressAdapter mAddressAdapterTo; - private EmailAddressAdapter mAddressAdapterCc; - private EmailAddressAdapter mAddressAdapterBcc; + private AccountSpecifier mAddressAdapterTo; + private AccountSpecifier mAddressAdapterCc; + private AccountSpecifier mAddressAdapterBcc; private static Intent getBaseIntent(Context context) { Intent i = new Intent(context, MessageCompose.class); @@ -322,9 +327,12 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus throw new IllegalArgumentException(); } mAccount = account; - mAddressAdapterTo.setAccount(account); - mAddressAdapterCc.setAccount(account); - mAddressAdapterBcc.setAccount(account); + mAddressAdapterTo + .setAccount(new android.accounts.Account(account.mEmailAddress, "unknown")); + mAddressAdapterCc + .setAccount(new android.accounts.Account(account.mEmailAddress, "unknown")); + mAddressAdapterBcc + .setAccount(new android.accounts.Account(account.mEmailAddress, "unknown")); if (mFromView != null) { // Some configurations don't show the from field. @@ -446,14 +454,14 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus mTaskTracker.cancellAllInterrupt(); - if (mAddressAdapterTo != null) { - mAddressAdapterTo.close(); + if (mAddressAdapterTo != null && mAddressAdapterTo instanceof EmailAddressAdapter) { + ((EmailAddressAdapter) mAddressAdapterTo).close(); } - if (mAddressAdapterCc != null) { - mAddressAdapterCc.close(); + if (mAddressAdapterCc != null && mAddressAdapterCc instanceof EmailAddressAdapter) { + ((EmailAddressAdapter) mAddressAdapterCc).close(); } - if (mAddressAdapterBcc != null) { - mAddressAdapterBcc.close(); + if (mAddressAdapterBcc != null && mAddressAdapterBcc instanceof EmailAddressAdapter) { + ((EmailAddressAdapter) mAddressAdapterBcc).close(); } } @@ -573,8 +581,12 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus private void initViews() { mToView = UiUtilities.getView(this, R.id.to); + mToView.setHint(R.string.message_compose_to_hint); mCcView = UiUtilities.getView(this, R.id.cc); + mCcView.setHint(R.string.message_compose_cc_hint); mBccView = UiUtilities.getView(this, R.id.bcc); + mBccView.setHint(R.string.message_compose_bcc_hint); + mCcBccContainer = UiUtilities.getView(this, R.id.cc_bcc_container); mSubjectView = UiUtilities.getView(this, R.id.subject); mMessageContentView = UiUtilities.getView(this, R.id.message_content); @@ -603,15 +615,12 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus EmailAddressValidator addressValidator = new EmailAddressValidator(); setupAddressAdapters(); - mToView.setAdapter(mAddressAdapterTo); mToView.setTokenizer(new Rfc822Tokenizer()); mToView.setValidator(addressValidator); - mCcView.setAdapter(mAddressAdapterCc); mCcView.setTokenizer(new Rfc822Tokenizer()); mCcView.setValidator(addressValidator); - mBccView.setAdapter(mAddressAdapterBcc); mBccView.setTokenizer(new Rfc822Tokenizer()); mBccView.setValidator(addressValidator); @@ -660,9 +669,29 @@ public class MessageCompose extends Activity implements OnClickListener, OnFocus * Set up address auto-completion adapters. */ private void setupAddressAdapters() { - mAddressAdapterTo = new EmailAddressAdapter(this); - mAddressAdapterCc = new EmailAddressAdapter(this); - mAddressAdapterBcc = new EmailAddressAdapter(this); + boolean supportsChips = ChipsUtil.supportsChipsUi(); + + if (supportsChips && mToView instanceof RecipientEditTextView) { + mAddressAdapterTo = new RecipientAdapter(this, (RecipientEditTextView) mToView); + mToView.setAdapter((RecipientAdapter) mAddressAdapterTo); + } else { + mAddressAdapterTo = new EmailAddressAdapter(this); + mToView.setAdapter((EmailAddressAdapter) mAddressAdapterTo); + } + if (supportsChips && mCcView instanceof RecipientEditTextView) { + mAddressAdapterCc = new RecipientAdapter(this, (RecipientEditTextView) mCcView); + mCcView.setAdapter((RecipientAdapter) mAddressAdapterCc); + } else { + mAddressAdapterCc = new EmailAddressAdapter(this); + mCcView.setAdapter((EmailAddressAdapter) mAddressAdapterCc); + } + if (supportsChips && mBccView instanceof RecipientEditTextView) { + mAddressAdapterBcc = new RecipientAdapter(this, (RecipientEditTextView) mBccView); + mBccView.setAdapter((RecipientAdapter) mAddressAdapterBcc); + } else { + mAddressAdapterBcc = new EmailAddressAdapter(this); + mBccView.setAdapter((EmailAddressAdapter) mAddressAdapterBcc); + } } /** |