Don't delete kind sections when there are >1 emails in the raw contact
* Also fix jank when deleting compact editor input fields
We were animating removal of input fields when there was more
than one field in the raw contact (i.e. Editor.deleteEditor)
but not when hiding entire KindViewSections
(i.e. KindSectionView.setVisibility(GONE)). When animating
KindSectionView removals, we must mark it for deletion
since we need to re-assess the number of KindSectionViews that
are visibile (in order to show icons) before the removal
animation finishes (the visibility is set to GONE at the end
of the animation).
* Prevent nicknames from being deleted
Bug 22228718
Bug 22299522
Change-Id: I28dad184c53e89f067d54675fcb3e7ebac9d971e
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index b91671c..d1159a4 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -137,8 +137,8 @@
private ViewGroup mNicknames;
private ViewGroup mPhoneNumbers;
private ViewGroup mEmails;
- private ViewGroup mOther;
- private Map<String,LinearLayout> mOtherMap = new HashMap<>();
+ private ViewGroup mOtherTypes;
+ private Map<String,LinearLayout> mOtherTypesMap = new HashMap<>();
private View mMoreFields;
// The ValuesDelta for the non super primary name that was displayed to the user.
@@ -180,7 +180,7 @@
mNicknames = (LinearLayout) findViewById(R.id.nicknames);
mPhoneNumbers = (LinearLayout) findViewById(R.id.phone_numbers);
mEmails = (LinearLayout) findViewById(R.id.emails);
- mOther = (LinearLayout) findViewById(R.id.other);
+ mOtherTypes = (LinearLayout) findViewById(R.id.other);
mMoreFields = findViewById(R.id.more_fields);
mMoreFields.setOnClickListener(this);
}
@@ -200,8 +200,8 @@
setEnabled(enabled, mNicknames);
setEnabled(enabled, mPhoneNumbers);
setEnabled(enabled, mEmails);
- for (Map.Entry<String,LinearLayout> other : mOtherMap.entrySet()) {
- setEnabled(enabled, other.getValue());
+ for (Map.Entry<String,LinearLayout> otherType : mOtherTypesMap.entrySet()) {
+ setEnabled(enabled, otherType.getValue());
}
}
@@ -287,8 +287,8 @@
mNicknames.removeAllViews();
mPhoneNumbers.removeAllViews();
mEmails.removeAllViews();
- mOther.removeAllViews();
- mOtherMap.clear();
+ mOtherTypes.removeAllViews();
+ mOtherTypesMap.clear();
if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
return;
@@ -308,8 +308,8 @@
updateKindEditorIcons(mPhoneNumbers);
updateKindEditorEmptyFields(mEmails);
updateKindEditorIcons(mEmails);
- for (Map.Entry<String,LinearLayout> other : mOtherMap.entrySet()) {
- updateKindEditorIcons(other.getValue());
+ for (Map.Entry<String,LinearLayout> otherTypes : mOtherTypesMap.entrySet()) {
+ updateKindEditorIcons(otherTypes.getValue());
}
}
@@ -662,18 +662,27 @@
mPhoneticNames, accountType, valuesDelta, rawContactDelta));
}
} else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
- // Only add nicknames if there is a non-empty one
- if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
- mNicknames.addView(inflateKindSectionView(mNicknames, dataKind,
- rawContactDelta));
+ // Add all non-empty nicknames
+ final List<ValuesDelta> valuesDeltas = getNonEmptyValuesDeltas(
+ rawContactDelta, Nickname.CONTENT_ITEM_TYPE, dataKind);
+ if (valuesDeltas != null && !valuesDeltas.isEmpty()) {
+ for (ValuesDelta valuesDelta : valuesDeltas){
+ mNicknames.addView(inflateNicknameEditorView(
+ mNicknames, dataKind, valuesDelta, rawContactDelta));
+ }
}
} else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
final KindSectionView kindSectionView =
inflateKindSectionView(mPhoneNumbers, dataKind, rawContactDelta);
kindSectionView.setListener(new KindSectionView.Listener() {
@Override
- public void onDeleteRequested() {
- kindSectionView.setVisibility(View.GONE);
+ public void onDeleteRequested(Editor editor) {
+ if (kindSectionView.getEditorCount() == 1) {
+ kindSectionView.markForRemoval();
+ EditorAnimator.getInstance().removeEditorView(kindSectionView);
+ } else {
+ editor.deleteEditor();
+ }
updateKindEditorEmptyFields(mPhoneNumbers);
updateKindEditorIcons(mPhoneNumbers);
}
@@ -684,35 +693,43 @@
inflateKindSectionView(mEmails, dataKind, rawContactDelta);
kindSectionView.setListener(new KindSectionView.Listener() {
@Override
- public void onDeleteRequested() {
- kindSectionView.setVisibility(View.GONE);
+ public void onDeleteRequested(Editor editor) {
+ if (kindSectionView.getEditorCount() == 1) {
+ kindSectionView.markForRemoval();
+ EditorAnimator.getInstance().removeEditorView(kindSectionView);
+ } else {
+ editor.deleteEditor();
+ }
updateKindEditorEmptyFields(mEmails);
updateKindEditorIcons(mEmails);
}
});
mEmails.addView(kindSectionView);
} else if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
- final LinearLayout otherViewGroup;
- if (mOtherMap.containsKey(mimeType)) {
- otherViewGroup = mOtherMap.get(mimeType);
+ final LinearLayout otherTypeViewGroup;
+ if (mOtherTypesMap.containsKey(mimeType)) {
+ otherTypeViewGroup = mOtherTypesMap.get(mimeType);
} else {
- otherViewGroup = new LinearLayout(getContext());
- otherViewGroup.setOrientation(LinearLayout.VERTICAL);
- mOther.addView(otherViewGroup);
- mOtherMap.put(mimeType, otherViewGroup);
+ otherTypeViewGroup = new LinearLayout(getContext());
+ otherTypeViewGroup.setOrientation(LinearLayout.VERTICAL);
+ mOtherTypes.addView(otherTypeViewGroup);
+ mOtherTypesMap.put(mimeType, otherTypeViewGroup);
}
final KindSectionView kindSectionView =
- inflateKindSectionView(mOther, dataKind, rawContactDelta);
+ inflateKindSectionView(mOtherTypes, dataKind, rawContactDelta);
kindSectionView.setListener(new KindSectionView.Listener() {
@Override
- public void onDeleteRequested() {
- if (kindSectionView.getVisibleEditorCount() == 1) {
- kindSectionView.setVisibility(View.GONE);
+ public void onDeleteRequested(Editor editor) {
+ if (kindSectionView.getEditorCount() == 1) {
+ kindSectionView.markForRemoval();
+ EditorAnimator.getInstance().removeEditorView(kindSectionView);
+ } else {
+ editor.deleteEditor();
}
- updateKindEditorIcons(otherViewGroup);
+ updateKindEditorIcons(otherTypeViewGroup);
}
});
- otherViewGroup.addView(kindSectionView);
+ otherTypeViewGroup.addView(kindSectionView);
}
}
}
@@ -737,7 +754,8 @@
boolean iconVisible = false;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
final KindSectionView kindSectionView = (KindSectionView) viewGroup.getChildAt(i);
- if (kindSectionView.getVisibility() != View.VISIBLE) {
+ if (kindSectionView.getVisibility() != View.VISIBLE
+ || kindSectionView.isMarkedForRemoval()) {
continue;
}
if (!iconVisible) {
@@ -832,6 +850,21 @@
return result;
}
+ private TextFieldsEditorView inflateNicknameEditorView(ViewGroup viewGroup, DataKind dataKind,
+ ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
+ final TextFieldsEditorView result = (TextFieldsEditorView) mLayoutInflater.inflate(
+ R.layout.nick_name_editor_view, viewGroup, /* attachToRoot =*/ false);
+ result.setDeletable(false);
+ result.setValues(
+ dataKind,
+ valuesDelta,
+ rawContactDelta,
+ /* readOnly =*/ false,
+ mViewIdGenerator);
+ return result;
+ }
+
+
private KindSectionView inflateKindSectionView(ViewGroup viewGroup, DataKind dataKind,
RawContactDelta rawContactDelta) {
final KindSectionView result = (KindSectionView) mLayoutInflater.inflate(
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index 461e714..bf456d5 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -61,7 +61,7 @@
/**
* Invoked when any editor that is displayed in this section view is deleted by the user.
*/
- public void onDeleteRequested();
+ public void onDeleteRequested(Editor editor);
}
private ViewGroup mEditors;
@@ -72,6 +72,14 @@
private boolean mReadOnly;
private boolean mShowOneEmptyEditor;
+ /**
+ * Whether this KindSectionView will be removed from the layout.
+ * We need this because we want to animate KindSectionViews away (which takes time),
+ * but calculate which KindSectionViews will be visible immediately after starting removal
+ * animations.
+ */
+ private boolean mMarkedForRemoval;
+
private ViewIdGenerator mViewIdGenerator;
private LayoutInflater mInflater;
@@ -117,17 +125,27 @@
@Override
public void onDeleteRequested(Editor editor) {
- // If there is only 1 editor in the section, then don't allow the user to delete it.
- // Just clear the fields in the editor.
- if (getEditorCount() == 1 && mShowOneEmptyEditor) {
+ if (mShowOneEmptyEditor && getEditorCount() == 1) {
+ // If there is only 1 editor in the section, then don't allow the user to delete it.
+ // Just clear the fields in the editor.
editor.clearAllFields();
} else {
- // Otherwise it's okay to delete this {@link Editor}
- editor.deleteEditor();
+ // If there is a listener, let it decide whether to delete the Editor or the entire
+ // KindSectionView so that there is no jank from both animations happening in succession.
+ if (mListener != null) {
+ mListener.onDeleteRequested(editor);
+ } else {
+ editor.deleteEditor();
+ }
}
- if (mListener != null) {
- mListener.onDeleteRequested();
- }
+ }
+
+ public void markForRemoval() {
+ mMarkedForRemoval = true;
+ }
+
+ public boolean isMarkedForRemoval() {
+ return mMarkedForRemoval;
}
@Override
@@ -312,16 +330,6 @@
return mEditors.getChildCount();
}
- public int getVisibleEditorCount() {
- int count = 0;
- for (int i = 0; i < mEditors.getChildCount(); i++) {
- if (mEditors.getChildAt(i).getVisibility() == View.VISIBLE) {
- count++;
- }
- }
- return count;
- }
-
public DataKind getKind() {
return mKind;
}