Remember editor expansion state on rotates (E10)
* Prompt user about discarding changes when back pressed
on editor (regressed in E5)
* Show a toast and close when no editors (i.e. input
fields) can be bound.
* Try to clarify the different behavior of
CompactSectionSectionView for names and groups.
Bug 23589603
Change-Id: If045ddb6d839574dc4109195b0d8841cd6083561
diff --git a/src/com/android/contacts/activities/ContactEditorBaseActivity.java b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
index 18ff30f..a86196b 100644
--- a/src/com/android/contacts/activities/ContactEditorBaseActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorBaseActivity.java
@@ -273,7 +273,7 @@
@Override
public void onBackPressed() {
if (mFragment != null) {
- mFragment.save(ContactEditor.SaveMode.CLOSE);
+ mFragment.revert();
}
}
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index d5209cb..e98a8de 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -40,6 +40,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import android.widget.Toast;
import java.io.FileNotFoundException;
@@ -353,6 +354,17 @@
rebindEditorsForNewContact(oldState, oldAccount, newAccount);
}
+ @Override
+ public void onBindEditorsFailed() {
+ final Activity activity = getActivity();
+ if (activity != null && !activity.isFinishing()) {
+ Toast.makeText(activity, R.string.compact_editor_failed_to_load,
+ Toast.LENGTH_SHORT).show();
+ activity.setResult(Activity.RESULT_CANCELED);
+ activity.finish();
+ }
+ }
+
private CompactRawContactsEditorView getContent() {
return (CompactRawContactsEditorView) mContent;
}
diff --git a/src/com/android/contacts/editor/CompactKindSectionView.java b/src/com/android/contacts/editor/CompactKindSectionView.java
index 25712d0..b506666 100644
--- a/src/com/android/contacts/editor/CompactKindSectionView.java
+++ b/src/com/android/contacts/editor/CompactKindSectionView.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -34,7 +33,6 @@
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.editor.Editor.EditorListener;
import java.util.ArrayList;
import java.util.List;
@@ -42,25 +40,21 @@
/**
* Version of {@link KindSectionView} that supports multiple RawContactDeltas.
*/
-public class CompactKindSectionView extends LinearLayout implements EditorListener {
+public class CompactKindSectionView extends LinearLayout {
/**
* Marks a name as super primary when it is changed.
*
* This is for the case when two or more raw contacts with names are joined where neither is
- * marked as super primary. If the user hits back (which causes a save) after changing the
- * name that was arbitrarily displayed, we want that to be the name that is used.
- *
- * Should only be set when a super primary name does not already exist since we only show
- * one name field.
+ * marked as super primary.
*/
- private static final class NameEditorListener implements Editor.EditorListener {
+ private static final class StructuredNameEditorListener implements Editor.EditorListener {
private final ValuesDelta mValuesDelta;
private final long mRawContactId;
private final CompactRawContactsEditorView.Listener mListener;
- public NameEditorListener(ValuesDelta valuesDelta, long rawContactId,
+ public StructuredNameEditorListener(ValuesDelta valuesDelta, long rawContactId,
CompactRawContactsEditorView.Listener listener) {
mValuesDelta = valuesDelta;
mRawContactId = rawContactId;
@@ -85,7 +79,11 @@
}
}
- private static final class NicknameEditorListener implements Editor.EditorListener {
+ /**
+ * Clears fields when deletes are requested (on phonetic and nickename fields);
+ * does not change the number of editors.
+ */
+ private static final class OtherNameKindEditorListener implements Editor.EditorListener {
@Override
public void onRequest(int request) {
@@ -97,16 +95,42 @@
}
}
+ /**
+ * Updates empty fields when fields are deleted or turns empty.
+ * Whether a new empty editor is added is controlled by {@link #setShowOneEmptyEditor} and
+ * {@link #setHideWhenEmpty}.
+ */
+ private final class NonNameEditorListener implements Editor.EditorListener {
+
+ @Override
+ public void onRequest(int request) {
+ // If a field has become empty or non-empty, then check if another row
+ // can be added dynamically.
+ if (request == FIELD_TURNED_EMPTY || request == FIELD_TURNED_NON_EMPTY) {
+ updateEmptyEditors(/* shouldAnimate = */ true);
+ }
+ }
+
+ @Override
+ public void onDeleteRequested(Editor editor) {
+ if (mShowOneEmptyEditor && mEditors.getChildCount() == 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 {
+ editor.deleteEditor();
+ }
+ }
+ }
+
private List<KindSectionData> mKindSectionDataList;
- private boolean mReadOnly;
private ViewIdGenerator mViewIdGenerator;
private CompactRawContactsEditorView.Listener mListener;
- private String mMimeType;
private boolean mShowOneEmptyEditor = false;
private boolean mHideIfEmpty = true;
- private LayoutInflater mInflater;
+ private LayoutInflater mLayoutInflater;
private ViewGroup mEditors;
private ImageView mIcon;
@@ -129,42 +153,22 @@
}
}
- /** {@inheritDoc} */
@Override
protected void onFinishInflate() {
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
- mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mLayoutInflater = (LayoutInflater) getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
mEditors = (ViewGroup) findViewById(R.id.kind_editors);
mIcon = (ImageView) findViewById(R.id.kind_icon);
}
- @Override
- public void onDeleteRequested(Editor editor) {
- 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 {
- editor.deleteEditor();
- }
- }
-
- @Override
- public void onRequest(int request) {
- // If a field has become empty or non-empty, then check if another row
- // can be added dynamically.
- if (request == FIELD_TURNED_EMPTY || request == FIELD_TURNED_NON_EMPTY) {
- updateEmptyEditors(/* shouldAnimate = */ true);
- }
- }
-
/**
* @param showOneEmptyEditor If true, we will always show one empty editor, otherwise an empty
- * editor will not be shown until the user enters a value. Note, this has no effect
- * on name editors since the policy is to always show names.
+ * editor will not be shown until the user enters a value. Note, this does not apply
+ * to name editors since those are always displayed.
*/
public void setShowOneEmptyEditor(boolean showOneEmptyEditor) {
mShowOneEmptyEditor = showOneEmptyEditor;
@@ -172,13 +176,14 @@
/**
* @param hideWhenEmpty If true, the entire section will be hidden if all inputs are empty,
- * otherwise one empty input will always be displayed. Note, this has no effect
- * on name editors since the policy is to always show names.
+ * otherwise one empty input will always be displayed. Note, this does not apply
+ * to name editors since those are always displayed.
*/
public void setHideWhenEmpty(boolean hideWhenEmpty) {
mHideIfEmpty = hideWhenEmpty;
}
+ /** Binds the given group data to every {@link GroupMembershipView}. */
public void setGroupMetaData(Cursor cursor) {
for (int i = 0; i < mEditors.getChildCount(); i++) {
final View view = mEditors.getChildAt(i);
@@ -188,32 +193,39 @@
}
}
- public void setState(List<KindSectionData> kindSectionDataList, boolean readOnly,
+ /**
+ * Binds views for the given {@link KindSectionData} list.
+ *
+ * We create a structured name and phonetic name editor for each {@link DataKind} with a
+ * {@link }StructuredName#CONTENT_ITEM_TYPE} mime type. The number and order of editors are
+ * rendered as they are given to {@link #setState}.
+ *
+ * Empty name editors are never added and at least one structured name editor is always
+ * displayed, even if it is empty.
+ */
+ public void setState(List<KindSectionData> kindSectionDataList,
ViewIdGenerator viewIdGenerator, CompactRawContactsEditorView.Listener listener) {
mKindSectionDataList = kindSectionDataList;
- mReadOnly = readOnly;
mViewIdGenerator = viewIdGenerator;
mListener = listener;
- // Set the icon using the first DataKind (all DataKinds should be the same type)
+ // Set the icon using the first DataKind
final DataKind dataKind = mKindSectionDataList.isEmpty()
? null : mKindSectionDataList.get(0).getDataKind();
if (dataKind != null) {
- mIcon.setContentDescription(dataKind.titleRes == -1 || dataKind.titleRes == 0
- ? "" : getResources().getString(dataKind.titleRes));
mIcon.setImageDrawable(EditorUiUtils.getMimeTypeDrawable(getContext(),
dataKind.mimeType));
- if (mIcon.getDrawable() == null) mIcon.setContentDescription(null);
- mMimeType = dataKind.mimeType;
+ if (mIcon.getDrawable() != null) {
+ mIcon.setContentDescription(dataKind.titleRes == -1 || dataKind.titleRes == 0
+ ? "" : getResources().getString(dataKind.titleRes));
+ }
}
rebuildFromState();
+
updateEmptyEditors(/* shouldAnimate = */ false);
}
- /**
- * Build editors for all current rows.
- */
private void rebuildFromState() {
mEditors.removeAllViews();
@@ -221,29 +233,31 @@
final String mimeType = kindSectionData.getDataKind().mimeType;
if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
for (ValuesDelta valuesDelta : kindSectionData.getValuesDeltas()) {
- createNameEditorViews(kindSectionData.getAccountType(),
+ addNameEditorViews(kindSectionData.getAccountType(),
valuesDelta, kindSectionData.getRawContactDelta());
}
} else if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
- createGroupEditorView(kindSectionData.getRawContactDelta(),
+ addGroupEditorView(kindSectionData.getRawContactDelta(),
kindSectionData.getDataKind());
} else {
+ final Editor.EditorListener editorListener = kindSectionData.isNicknameDataKind()
+ ? new OtherNameKindEditorListener() : new NonNameEditorListener();
for (ValuesDelta valuesDelta : kindSectionData.getValuesDeltas()) {
- createEditorView(kindSectionData.getRawContactDelta(),
- kindSectionData.getDataKind(), valuesDelta);
+ addNonNameEditorView(kindSectionData.getRawContactDelta(),
+ kindSectionData.getDataKind(), valuesDelta, editorListener);
}
}
}
}
- private void createNameEditorViews(AccountType accountType,
+ private void addNameEditorViews(AccountType accountType,
ValuesDelta valuesDelta, RawContactDelta rawContactDelta) {
final boolean readOnly = !accountType.areContactsWritable();
// Structured name
- final StructuredNameEditorView nameView = (StructuredNameEditorView) mInflater.inflate(
- R.layout.structured_name_editor_view, mEditors, /* attachToRoot =*/ false);
- nameView.setEditorListener(new NameEditorListener(valuesDelta,
+ final StructuredNameEditorView nameView = (StructuredNameEditorView) mLayoutInflater
+ .inflate(R.layout.structured_name_editor_view, mEditors, /* attachToRoot =*/ false);
+ nameView.setEditorListener(new StructuredNameEditorListener(valuesDelta,
rawContactDelta.getRawContactId(), mListener));
nameView.setDeletable(false);
nameView.setValues(
@@ -251,15 +265,16 @@
valuesDelta, rawContactDelta, readOnly, mViewIdGenerator);
if (readOnly) nameView.setAccountType(accountType);
- // Correct start margin since there is another icon in the structured name layout
+ // Correct start margin since there is a second icon in the structured name layout
nameView.findViewById(R.id.kind_icon).setVisibility(View.GONE);
mEditors.addView(nameView);
// Phonetic name
if (readOnly) return;
- final PhoneticNameEditorView phoneticNameView = (PhoneticNameEditorView) mInflater.inflate(
- R.layout.phonetic_name_editor_view, mEditors, /* attachToRoot =*/ false);
+ final PhoneticNameEditorView phoneticNameView = (PhoneticNameEditorView) mLayoutInflater
+ .inflate(R.layout.phonetic_name_editor_view, mEditors, /* attachToRoot =*/ false);
+ phoneticNameView.setEditorListener(new OtherNameKindEditorListener());
phoneticNameView.setDeletable(false);
phoneticNameView.setValues(
accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME),
@@ -273,57 +288,40 @@
mEditors.addView(phoneticNameView);
}
- private void createGroupEditorView(RawContactDelta rawContactDelta, DataKind dataKind) {
- final GroupMembershipView view = (GroupMembershipView) mInflater.inflate(
+ private void addGroupEditorView(RawContactDelta rawContactDelta, DataKind dataKind) {
+ final GroupMembershipView view = (GroupMembershipView) mLayoutInflater.inflate(
R.layout.item_group_membership, mEditors, /* attachToRoot =*/ false);
view.setKind(dataKind);
view.setEnabled(isEnabled());
view.setState(rawContactDelta);
- // Correct start margin since there is another icon in the group layout
+ // Correct start margin since there is a second icon in the group layout
view.findViewById(R.id.kind_icon).setVisibility(View.GONE);
mEditors.addView(view);
}
- /**
- * Creates an EditorView for the given values delta. This function must be used while
- * constructing the views corresponding to the the object-model. The resulting EditorView is
- * also added to the end of mEditors
- */
- private View createEditorView(RawContactDelta rawContactDelta, DataKind dataKind,
- ValuesDelta valuesDelta) {
+ private View addNonNameEditorView(RawContactDelta rawContactDelta, DataKind dataKind,
+ ValuesDelta valuesDelta, Editor.EditorListener editorListener) {
// Inflate the layout
- final View view;
- final int layoutResId = EditorUiUtils.getLayoutResourceId(dataKind.mimeType);
- try {
- view = mInflater.inflate(layoutResId, mEditors, false);
- } catch (Exception e) {
- throw new RuntimeException("Failed to allocate editor with layout resource ID " +
- layoutResId + " for mime type " + dataKind.mimeType + ": " + e.toString());
- }
+ final View view = mLayoutInflater.inflate(
+ EditorUiUtils.getLayoutResourceId(dataKind.mimeType), mEditors, false);
+ view.setEnabled(isEnabled());
// Hide the types drop downs until the associated edit field is focused
if (view instanceof LabeledEditorView) {
((LabeledEditorView) view).setHideTypeInitially(true);
}
- // Set whether the editor is enabled
- view.setEnabled(isEnabled());
-
if (view instanceof Editor) {
final Editor editor = (Editor) view;
editor.setDeletable(true);
- // TODO: it's awkward to be doing something special for nicknames here
- if (Nickname.CONTENT_ITEM_TYPE.equals(dataKind.mimeType)) {
- editor.setEditorListener(new NicknameEditorListener());
- } else {
- editor.setEditorListener(this);
- }
+ editor.setEditorListener(editorListener);
editor.setValues(dataKind, valuesDelta, rawContactDelta, !dataKind.editable,
mViewIdGenerator);
}
mEditors.addView(view);
+
return view;
}
@@ -334,9 +332,43 @@
* then the entire section is hidden.
*/
public void updateEmptyEditors(boolean shouldAnimate) {
- if (mKindSectionDataList.get(0).isNameDataKind()) {
+ final boolean isNameKindSection = mKindSectionDataList.get(0).isNameDataKind();
+ final boolean isGroupKindSection = GroupMembership.CONTENT_ITEM_TYPE.equals(
+ mKindSectionDataList.get(0).getDataKind().mimeType);
+
+ if (isNameKindSection) {
+ // The name kind section is always visible
+ setVisibility(VISIBLE);
+
updateEmptyNameEditors(shouldAnimate);
+ } else if (isGroupKindSection) {
+ // Check whether metadata has been bound for all group views
+ for (int i = 0; i < mEditors.getChildCount(); i++) {
+ final View view = mEditors.getChildAt(i);
+ if (view instanceof GroupMembershipView
+ && !((GroupMembershipView) view).wasGroupMetaDataBound()) {
+ setVisibility(GONE);
+ return;
+ }
+ }
+ // Check that the user has selected to display all fields
+ if (mHideIfEmpty) {
+ setVisibility(GONE);
+ return;
+ }
+ setVisibility(VISIBLE);
+
+ // We don't check the emptiness of the group views
} else {
+ // Determine if the entire kind section should be visible
+ final int editorCount = mEditors.getChildCount();
+ final List<View> emptyEditors = getEmptyEditors();
+ if (editorCount == emptyEditors.size() && mHideIfEmpty) {
+ setVisibility(GONE);
+ return;
+ }
+ setVisibility(VISIBLE);
+
updateEmptyNonNameEditors(shouldAnimate);
}
}
@@ -365,25 +397,17 @@
} else {
// For phonetic names and nicknames, which can't be added, just show or hide them
if (mHideIfEmpty && editor.isEmpty()) {
- hideView(view, shouldAnimate);
+ hideView(view);
} else {
- showView(view, shouldAnimate);
+ showView(view, /* shouldAnimate =*/ false); // Animation here causes jank
}
}
}
}
private void updateEmptyNonNameEditors(boolean shouldAnimate) {
- // Update whether the entire section is visible or not
- final int editorCount = getEditorCount();
- final List<View> emptyEditors = getEmptyEditors();
- if (editorCount == emptyEditors.size() && mHideIfEmpty) {
- setVisibility(GONE);
- return;
- }
- setVisibility(VISIBLE);
-
// Prune excess empty editors
+ final List<View> emptyEditors = getEmptyEditors();
if (emptyEditors.size() > 1) {
// If there is more than 1 empty editor, then remove it from the list of editors.
int deleted = 0;
@@ -403,29 +427,27 @@
}
// Determine if we should add a new empty editor
final DataKind dataKind = mKindSectionDataList.get(0).getDataKind();
- if (mReadOnly // We don't show empty editors for read only data kinds.
- || dataKind == null // There is nothing we can do.
+ if (dataKind == null // There is nothing we can do.
// We have already reached the maximum number of editors, don't add any more.
- || (dataKind.typeOverallMax == editorCount && dataKind.typeOverallMax != 0)
+ || (dataKind.typeOverallMax == mEditors.getChildCount()
+ && dataKind.typeOverallMax != 0)
// We have already reached the maximum number of empty editors, don't add any more.
|| emptyEditors.size() == 1) {
return;
}
// Add a new empty editor
if (mShowOneEmptyEditor) {
- final RawContactDelta rawContactDelta = mKindSectionDataList.get(0).getRawContactDelta();
+ final RawContactDelta rawContactDelta =
+ mKindSectionDataList.get(0).getRawContactDelta();
final ValuesDelta values = RawContactModifier.insertChild(rawContactDelta, dataKind);
- final View view = createEditorView(rawContactDelta, dataKind, values);
+ final View view = addNonNameEditorView(rawContactDelta, dataKind, values,
+ new NonNameEditorListener());
showView(view, shouldAnimate);
}
}
- private void hideView(View view, boolean shouldAnimate) {
- if (shouldAnimate) {
- EditorAnimator.getInstance().hideEditorView(view);
- } else {
- view.setVisibility(View.GONE);
- }
+ private void hideView(View view) {
+ view.setVisibility(View.GONE);
}
private void deleteView(View view, boolean shouldAnimate) {
@@ -440,35 +462,20 @@
private void showView(View view, boolean shouldAnimate) {
if (shouldAnimate) {
view.setVisibility(View.GONE);
- // TODO: still need this since we have animateLayoutChanges="true" on the parent layout?
EditorAnimator.getInstance().showFieldFooter(view);
} else {
view.setVisibility(View.VISIBLE);
}
}
- /**
- * Returns a list of empty editor views in this section.
- */
private List<View> getEmptyEditors() {
- List<View> emptyEditorViews = new ArrayList<View>();
+ final List<View> emptyEditors = new ArrayList<>();
for (int i = 0; i < mEditors.getChildCount(); i++) {
final View view = mEditors.getChildAt(i);
if (view instanceof Editor && ((Editor) view).isEmpty()) {
- emptyEditorViews.add(view);
+ emptyEditors.add(view);
}
}
- return emptyEditorViews;
- }
-
- private int getEditorCount() {
- return mEditors.getChildCount();
- }
-
- /**
- * Returns the mime type the kind being edited in this section.
- */
- public String getMimeType() {
- return mMimeType;
+ return emptyEditors;
}
}
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 8ca6389..656f25f 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -34,6 +34,8 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
@@ -102,6 +104,11 @@
*/
public void onRebindEditorsForNewContact(RawContactDelta oldState,
AccountWithDataSet oldAccount, AccountWithDataSet newAccount);
+
+ /**
+ * Invoked when no editors could be bound for the contact.
+ */
+ public void onBindEditorsFailed();
}
/** Used to sort entire kind sections. */
@@ -130,7 +137,7 @@
* <li>All names are together at the top.</li>
* <li>IM is moved up after addresses</li>
* <li>SIP addresses are moved to below phone numbers</li>
- * <li>Group membership is palced at the end</li>
+ * <li>Group membership is placed at the end</li>
* </ol>
*/
private static final class MimeTypeComparator implements Comparator<String> {
@@ -240,13 +247,43 @@
}
// The primary account name should be before all others
- if (isRawContactDelta1Primary) return 1;
- if (isRawContactDelta2Primary) return -1;
+ if (isRawContactDelta1Primary) return -1;
+ if (isRawContactDelta2Primary) return 1;
return mRawContactDeltaComparator.compare(rawContactDelta1, rawContactDelta2);
}
}
+ public static class SavedState extends BaseSavedState {
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+
+ private boolean mIsExpanded;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ mIsExpanded = in.readInt() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(mIsExpanded ? 1 : 0);
+ }
+ }
+
private CompactRawContactsEditorView.Listener mListener;
private AccountTypeManager mAccountTypeManager;
@@ -277,6 +314,7 @@
private Map<String,List<CompactKindSectionView>> mKindSectionViewsMap = new HashMap<>();
private View mMoreFields;
+ private boolean mIsExpanded;
private long mPhotoRawContactId;
public CompactRawContactsEditorView(Context context) {
@@ -322,19 +360,7 @@
@Override
public void onClick(View view) {
if (view.getId() == R.id.more_fields) {
- // Stop hiding empty editors and allow the user to enter values for all kinds now
- for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
- final CompactKindSectionView kindSectionView =
- (CompactKindSectionView) mKindSectionViews.getChildAt(i);
- kindSectionView.setHideWhenEmpty(false);
- // Except the user is never allowed to add new names
- final String mimeType = kindSectionView.getMimeType();
- if (!StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
- kindSectionView.setShowOneEmptyEditor(true);
- }
- kindSectionView.updateEmptyEditors(/* shouldAnimate =*/ false);
- }
-
+ showMoreFields();
updateMoreFieldsButton();
}
}
@@ -348,6 +374,28 @@
}
}
+ @Override
+ public Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ final SavedState savedState = new SavedState(superState);
+ savedState.mIsExpanded = mIsExpanded;
+ return savedState;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if(!(state instanceof SavedState)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+ final SavedState savedState = (SavedState) state;
+ super.onRestoreInstanceState(savedState.getSuperState());
+ mIsExpanded = savedState.mIsExpanded;
+ if (mIsExpanded && !mKindSectionDataMap.isEmpty()) {
+ showMoreFields();
+ }
+ }
+
/**
* Pass through to {@link CompactPhotoEditorView#setPhotoHandler}.
*/
@@ -398,6 +446,12 @@
for (CompactKindSectionView kindSectionView : kindSectionViews) {
kindSectionView.setGroupMetaData(groupMetaData);
}
+
+ // Groups metadata may be set after we restore expansion state so just do it again
+ if (mIsExpanded) {
+ showMoreFields();
+ }
+ updateMoreFieldsButton();
}
public void setState(RawContactDeltaList rawContactDeltas,
@@ -423,11 +477,13 @@
// Parse the given raw contact deltas
if (rawContactDeltas == null || rawContactDeltas.isEmpty()) {
elog("No raw contact deltas");
+ if (mListener != null) mListener.onBindEditorsFailed();
return;
}
parseRawContactDeltas(rawContactDeltas, mPrimaryAccount);
- if (mKindSectionDataMap == null || mKindSectionDataMap.isEmpty()) {
+ if (mKindSectionDataMap.isEmpty()) {
elog("No kind section data parsed from RawContactDelta(s)");
+ if (mListener != null) mListener.onBindEditorsFailed();
return;
}
@@ -437,6 +493,7 @@
addAccountInfo();
addPhotoView();
addKindSectionViews();
+
updateMoreFieldsButton();
}
@@ -509,10 +566,9 @@
new KindSectionData(accountType, dataKind, rawContactDelta);
kindSectionDataList.add(kindSectionData);
- // Note we must create a nickname entry on inserts
+ // Note we must create nickname entries
if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)
- && kindSectionData.getValuesDeltas().isEmpty()
- && mHasNewContact) {
+ && kindSectionData.getValuesDeltas().isEmpty()) {
RawContactModifier.insertChild(rawContactDelta, dataKind);
}
@@ -659,10 +715,6 @@
private Pair<KindSectionData,ValuesDelta> getPrimaryKindSectionData(long id) {
final String mimeType = Photo.CONTENT_ITEM_TYPE;
final List<KindSectionData> kindSectionDataList = mKindSectionDataMap.get(mimeType);
- if (kindSectionDataList == null || kindSectionDataList.isEmpty()) {
- wlog("photo: no kind section data parsed");
- return null;
- }
KindSectionData resultKindSectionData = null;
ValuesDelta resultValuesDelta = null;
@@ -779,12 +831,22 @@
Collections.sort(kindSectionDataList, new EditorComparator(getContext()));
}
- kindSectionView.setState(kindSectionDataList, /* readOnly =*/ false, mViewIdGenerator,
- mListener);
+ kindSectionView.setState(kindSectionDataList, mViewIdGenerator, mListener);
return kindSectionView;
}
+ private void showMoreFields() {
+ // Stop hiding empty editors and allow the user to enter values for all kinds now
+ for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
+ final CompactKindSectionView kindSectionView =
+ (CompactKindSectionView) mKindSectionViews.getChildAt(i);
+ kindSectionView.setHideWhenEmpty(false);
+ kindSectionView.updateEmptyEditors(/* shouldAnimate =*/ true);
+ }
+ mIsExpanded = true;
+ }
+
private void updateMoreFieldsButton() {
// If any kind section views are hidden then show the link
for (int i = 0; i < mKindSectionViews.getChildCount(); i++) {
diff --git a/src/com/android/contacts/editor/EditorIntents.java b/src/com/android/contacts/editor/EditorIntents.java
index ca8d5ae..26279df 100644
--- a/src/com/android/contacts/editor/EditorIntents.java
+++ b/src/com/android/contacts/editor/EditorIntents.java
@@ -110,7 +110,6 @@
* Returns an Intent to start the fully expanded {@link ContactEditorActivity} for a
* new contact.
*/
- // TODO: Delete this if we don't need it to load the full editor for read only accounts
public static Intent createInsertContactIntent(RawContactDeltaList rawContactDeltaList,
String displayName, String phoneticName, boolean isNewLocalProfile) {
final Intent intent = new Intent(ContactEditorBaseActivity.ACTION_INSERT,
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index f1d9db9..b13da62 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -202,6 +202,11 @@
}
}
+ /** Whether {@link #setGroupMetaData} has been invoked yet. */
+ public boolean wasGroupMetaDataBound() {
+ return mGroupMetaData != null;
+ }
+
public void setState(RawContactDelta state) {
mState = state;
mAccountType = mState.getAccountType();
diff --git a/src/com/android/contacts/editor/KindSectionData.java b/src/com/android/contacts/editor/KindSectionData.java
index 7b383fb..d46001a 100644
--- a/src/com/android/contacts/editor/KindSectionData.java
+++ b/src/com/android/contacts/editor/KindSectionData.java
@@ -98,8 +98,11 @@
}
public boolean isNameDataKind() {
- return StructuredName.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType)
- || Nickname.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
+ return StructuredName.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
+ }
+
+ public boolean isNicknameDataKind() {
+ return Nickname.CONTENT_ITEM_TYPE.equals(mDataKind.mimeType);
}
public RawContactDelta getRawContactDelta() {