Integrate chips into Email.

Change-Id: Ice037a55a169037f725a667fad7714c7e9580b86
This commit is contained in:
Mindy Pereira 2011-06-15 19:35:15 -07:00
parent b40bdb17df
commit 87763f0ae8
10 changed files with 269 additions and 53 deletions

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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" />

View File

@ -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" />

View File

@ -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"

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
/**