<!-- Edit or insert details for a contact -->
<activity
android:name=".ui.EditContactActivity"
- android:theme="@style/TallTitleBarTheme"
+ android:label="@string/editContactDescription"
android:windowSoftInputMode="stateVisible|adjustResize">
<intent-filter android:label="@string/editContactDescription">
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.
limitations under the License.
-->
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:fillViewport="true">
+ android:orientation="vertical"
+>
- <LinearLayout
- android:id="@+id/panel"
+ <ScrollView
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:fillViewport="true">
+ android:layout_height="1px"
+ android:layout_weight="1"
+ android:fillViewport="true"
+ >
- <com.android.internal.widget.ContactHeaderWidget
- android:id="@+id/contact_header_widget"
+ <LinearLayout android:id="@+id/editors"
android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ />
- <com.android.contacts.ScrollingTabWidget
- android:id="@+id/tab_widget"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
+ </ScrollView>
- <include
- android:id="@android:id/tabcontent"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:fillViewport="true"
- android:visibility="invisible"
- layout="@layout/item_contact_editor" />
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ style="@android:style/ButtonBar"
+ >
- <LinearLayout
- android:layout_width="fill_parent"
+ <Button android:id="@+id/btn_done"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- style="@android:style/ButtonBar">
-
- <Button
- android:id="@+id/btn_done"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/menu_done" />
-
- <Button
- android:id="@+id/btn_discard"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/menu_doNotSave" />
+ android:layout_weight="1"
+ android:text="@string/menu_done"
+ />
- </LinearLayout>
+ <Button android:id="@+id/btn_discard"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/menu_doNotSave"
+ />
</LinearLayout>
-</ScrollView>
+</LinearLayout>
<com.android.contacts.ui.widget.ContactEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:fillViewport="true">
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+>
- <TextView
- android:id="@+id/edit_read_only"
- android:layout_width="fill_parent"
+ <!-- Left side color bar -->
+ <ImageView
+ android:id="@+id/color_bar"
+ android:layout_width="15dip"
+ android:layout_height="fill_parent"
+ />
+
+ <!-- The content -->
+ <RelativeLayout
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:gravity="center|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:paddingTop="5dip"
- android:paddingBottom="5dip"
- android:text="@string/edit_read_only"/>
-
- <FrameLayout
- android:id="@+id/stub_photo"
- android:layout_width="100dip"
- android:layout_height="96dip"
- android:layout_below="@id/edit_read_only"
- android:layout_alignWithParentIfMissing="true"
- android:paddingLeft="12dip"
- android:paddingTop="10dip">
+ android:layout_weight="1"
+ >
+
+ <!-- Account info header -->
+ <RelativeLayout android:id="@+id/header"
+ android:layout_height="64dip"
+ android:layout_width="fill_parent"
+ >
+
+ <ImageView android:id="@+id/header_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="7dip"
+ android:layout_marginRight="7dip"
+ android:layout_centerVertical="true"
+ />
+
+ <TextView android:id="@+id/header_account_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/header_icon"
+ android:layout_alignTop="@id/header_icon"
+ android:layout_marginTop="-4dip"
+
+ android:textSize="24pt"
+ android:textStyle="bold"
+ android:textColor="?android:attr/textColorPrimary"
+ />
+
+ <TextView android:id="@+id/header_account_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/header_icon"
+ android:layout_alignBottom="@+id/header_icon"
+ android:layout_marginBottom="2dip"
+
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ />
+
+ </RelativeLayout>
+
+ <FrameLayout
+ android:id="@+id/stub_photo"
+ android:layout_width="100dip"
+ android:layout_height="96dip"
+ android:layout_below="@id/header"
+ android:layout_alignWithParentIfMissing="true"
+ android:paddingLeft="12dip"
+ android:paddingTop="10dip">
+
+ <include
+ android:id="@+id/edit_photo"
+ layout="@layout/item_photo_editor" />
+
+ </FrameLayout>
<include
- android:id="@+id/edit_photo"
- layout="@layout/item_photo_editor" />
+ android:id="@+id/edit_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/stub_photo"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="4dip"
+ android:layout_alignWithParentIfMissing="true"
+ layout="@layout/item_generic_editor" />
- </FrameLayout>
+ <LinearLayout
+ android:id="@+id/sect_general"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/edit_name"
+ android:orientation="vertical"
+ />
- <include
- android:id="@+id/edit_name"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/edit_read_only"
- android:layout_toRightOf="@id/stub_photo"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip"
- android:layout_alignWithParentIfMissing="true"
- layout="@layout/item_generic_editor" />
-
- <LinearLayout
- android:id="@+id/sect_general"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/edit_name"
- android:orientation="vertical" />
+ <View android:id="@+id/head_secondary_divider"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/sect_general"
+ android:background="?android:attr/listDivider" />
- <TextView
- android:id="@+id/head_secondary"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/sect_general"
- android:gravity="center_vertical"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:background="@color/sect_secondary"
- android:text="@string/edit_secondary_collapse"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/kind_title"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:focusable="true"
- android:clickable="true"
- android:paddingLeft="10dip"
- android:drawablePadding="10dip" />
-
- <LinearLayout
- android:id="@+id/sect_secondary"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/head_secondary"
- android:background="@color/sect_secondary"
- android:orientation="vertical" />
+ <TextView
+ android:id="@+id/head_secondary"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/head_secondary_divider"
+
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:text="@string/edit_secondary_collapse"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/kind_title"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:focusable="true"
+ android:clickable="true"
+ android:paddingLeft="10dip"
+ android:drawablePadding="10dip" />
+
+ <LinearLayout
+ android:id="@+id/sect_secondary"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/head_secondary"
+ android:orientation="vertical" />
+
+ <TextView
+ android:id="@+id/edit_read_only"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/edit_name"
+ android:gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:text="@string/edit_read_only"/>
+
+ </RelativeLayout>
</com.android.contacts.ui.widget.ContactEditorView>
<com.android.contacts.ui.widget.GenericEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:paddingRight="?android:attr/scrollbarSize">
android:title="@string/menu_deleteContact" />
<item
- android:id="@+id/menu_photo_add"
- android:icon="@drawable/ic_menu_add_picture"
- android:title="@string/addPicture" />
-
- <item
- android:id="@+id/menu_photo_remove"
- android:icon="@android:drawable/ic_menu_delete"
- android:title="@string/removePicture" />
-
- <item
android:id="@+id/menu_split"
android:icon="@drawable/ic_menu_merge"
android:title="@string/menu_splitAggregate" />
package com.android.contacts;
import com.android.contacts.Collapser.Collapsible;
-import com.android.contacts.ScrollingTabWidget.OnTabSelectionChangedListener;
-import com.android.contacts.SplitAggregateView.OnContactSelectedListener;
import com.android.contacts.model.ContactsSource;
import com.android.contacts.model.Sources;
import com.android.contacts.model.ContactsSource.DataKind;
import android.content.Entity;
import android.content.EntityIterator;
import android.content.Intent;
-import android.content.DialogInterface.OnClickListener;
import android.content.Entity.NamedContentValues;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
import android.view.ContextMenu;
-import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.ViewGroup;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.animation.Animation;
-import android.view.animation.TranslateAnimation;
-import android.view.animation.Animation.AnimationListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
} else if (requestCode == REQUEST_EDIT_CONTACT) {
if (resultCode == EditContactActivity.RESULT_CLOSE_VIEW_ACTIVITY) {
finish();
- } else {
+ } else if (resultCode == Activity.RESULT_OK) {
mLookupUri = intent.getData();
if (mLookupUri == null) {
finish();
}
}
+ abstract public int getHeaderColor(Context context);
+
+ abstract public int getSideBarColor(Context context);
+
/**
* {@link Comparator} to sort by {@link DataKind#weight}.
*/
return kind;
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff876b47;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffc6ab8c;
+ }
}
* <p>
* In the future this may be inflated from XML defined by a data source.
*/
-public class ExternalSource extends ContactsSource {
+public class ExternalSource extends FallbackSource {
private static final String ACTION_SYNC_ADAPTER = "android.content.SyncAdapter";
private static final String METADATA_CONTACTS = "android.provider.CONTACTS_STRUCTURE";
inflate(context, parser);
}
+ // Bring in name and photo from fallback source, which are non-optional
+ inflateStructuredName(inflateLevel);
+ inflatePhoto(inflateLevel);
+
setInflatedLevel(inflateLevel);
}
return mPublishedMode ? inflatePublished(status.published) : status.title;
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff7f93bc;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffbdc7d8;
+ }
}
}
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff7f93bc;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffbdc7b8;
+ }
}
cursor.close();
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff000000;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffffffff;
+ }
}
package com.android.contacts.ui;
+import com.android.contacts.ContactsListActivity;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.ScrollingTabWidget;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Editor;
+import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.EntitySet;
+import com.android.contacts.model.GoogleSource;
+import com.android.contacts.model.Sources;
+import com.android.contacts.model.Editor.EditorListener;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.ui.widget.ContactEditorView;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.WeakAsyncTask;
+import com.android.internal.widget.ContactHeaderWidget;
+import com.google.android.collect.Lists;
+
import android.accounts.Account;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.OperationApplicationException;
import android.content.ContentProviderOperation.Builder;
import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts.Data;
-import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.contacts.ContactsListActivity;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.ScrollingTabWidget;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.Editor;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.EntitySet;
-import com.android.contacts.model.GoogleSource;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.Editor.EditorListener;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.ui.widget.ContactEditorView;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.WeakAsyncTask;
-import com.android.internal.widget.ContactHeaderWidget;
-import com.google.android.collect.Lists;
-
import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
* Activity for editing or inserting a contact.
*/
-public final class EditContactActivity extends Activity implements View.OnClickListener,
- ScrollingTabWidget.OnTabSelectionChangedListener,
- ContactHeaderWidget.ContactHeaderListener, EditorListener {
+public final class EditContactActivity extends Activity
+ implements View.OnClickListener, EditorListener {
private static final String TAG = "EditContactActivity";
/** The launch code when picking a photo and the raw data is returned */
private static final int REQUEST_JOIN_CONTACT = 3022;
private static final String KEY_EDIT_STATE = "state";
- private static final String KEY_SELECTED_RAW_CONTACT = "selected";
/** The result code when view activity should close after edit returns */
public static final int RESULT_CLOSE_VIEW_ACTIVITY = 777;
public static final int SAVE_MODE_JOIN = 2;
- private String mQuerySelection;
-
- private ScrollingTabWidget mTabWidget;
- private ContactHeaderWidget mHeader;
- private TextView mAccountName;
+ String mQuerySelection;
- private ContactEditorView mEditor;
-
- private EntitySet mState;
private long mContactIdForJoin;
+ EntitySet mState;
+ /** The linear layout holding the ContactEditorViews */
+ LinearLayout mContent;
+
private ArrayList<Dialog> mManagedDialogs = Lists.newArrayList();
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- final Context context = this;
- final LayoutInflater inflater = this.getLayoutInflater();
-
final Intent intent = getIntent();
final String action = intent.getAction();
- final Bundle extras = intent.getExtras();
setContentView(R.layout.act_edit);
- // Header bar is filled later after queries finish
- mHeader = (ContactHeaderWidget)this.findViewById(R.id.contact_header_widget);
- mHeader.setContactHeaderListener(this);
- mHeader.showStar(false);
- mHeader.enableClickListeners();
-
- mTabWidget = (ScrollingTabWidget)this.findViewById(R.id.tab_widget);
- mTabWidget.setTabSelectionListener(this);
- mAccountName = (TextView)mTabWidget.findViewById(R.id.account_name);
-
// Build editor and listen for photo requests
- mEditor = (ContactEditorView)this.findViewById(android.R.id.tabcontent);
- mEditor.getPhotoEditor().setEditorListener(this);
- mEditor.setNameEditorListener(this);
+ mContent = (LinearLayout) findViewById(R.id.editors);
findViewById(R.id.btn_done).setOnClickListener(this);
findViewById(R.id.btn_discard).setOnClickListener(this);
if (Intent.ACTION_EDIT.equals(action) && !hasIncomingState) {
// Read initial state from database
new QueryEntitiesTask(this).execute(intent);
- mHeader.showStar(true);
- mHeader.setContactUri(intent.getData(), false);
} else if (Intent.ACTION_INSERT.equals(action) && !hasIncomingState) {
// Trigger dialog to pick account type
doAddAction();
- mHeader.showStar(false);
}
}
@Override
protected void onPostExecute(EditContactActivity target, Void result) {
// Bind UI to new background state
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
if (hasValidState()) {
// Store entities with modifications
outState.putParcelable(KEY_EDIT_STATE, mState);
- outState.putLong(KEY_SELECTED_RAW_CONTACT, getSelectedRawContactId());
}
super.onSaveInstanceState(outState);
// Read modifications from instance
mState = savedInstanceState.<EntitySet> getParcelable(KEY_EDIT_STATE);
- bindTabs();
- bindHeader();
+ bindEditors();
- if (hasValidState()) {
- final Long selectedId = savedInstanceState.getLong(KEY_SELECTED_RAW_CONTACT);
- setSelectedRawContactId(selectedId);
- }
-
- // Restore selected tab and any focus
super.onRestoreInstanceState(savedInstanceState);
}
/**
* Show this {@link Dialog} and manage with the {@link Activity}.
*/
- private void showAndManageDialog(Dialog dialog) {
+ void showAndManageDialog(Dialog dialog) {
startManagingDialog(dialog);
dialog.show();
}
/**
- * Return the {@link RawContacts#_ID} of the currently selected tab.
- */
- protected Long getSelectedRawContactId() {
- final int tabIndex = mTabWidget.getCurrentTab();
- return this.mTabRawContacts.get(tabIndex);
- }
-
- /**
- * Return the {@link EntityDelta} for the currently selected tab.
- */
- protected EntityDelta getSelectedEntityDelta() {
- final Long rawContactId = getSelectedRawContactId();
- return mState.getByRawContactId(rawContactId);
- }
-
- /**
- * Set the selected tab based on the given {@link RawContacts#_ID}.
- */
- protected void setSelectedRawContactId(Long rawContactId) {
- int tabIndex = 0;
-
- // Find index of requested contact
- final int size = mTabRawContacts.size();
- for (int i = 0; i < size; i++) {
- if (mTabRawContacts.valueAt(i) == rawContactId) {
- tabIndex = i;
- break;
- }
- }
-
- mTabWidget.setCurrentTab(tabIndex);
- this.onTabSelectionChanged(tabIndex, false);
- }
-
- /**
* Check if our internal {@link #mState} is valid, usually checked before
* performing user actions.
*/
/**
- * Map from {@link #mTabWidget} indexes to {@link RawContacts#_ID}, usually
- * used when mapping to {@link #mState}.
+ * An array of the raw contacts in the order they appear in the list.
*/
- private SparseArray<Long> mTabRawContacts = new SparseArray<Long>();
-
+ private EntityDelta[] mEntities;
/**
- * Rebuild tabs to match our underlying {@link #mState} object, usually
+ * Rebuild the editors to match our underlying {@link #mState} object, usually
* called once we've parsed {@link Entity} data or have inserted a new
* {@link RawContacts}.
*/
- protected void bindTabs() {
+ protected void bindEditors() {
if (!hasValidState()) return;
+ final LayoutInflater inflater = (LayoutInflater) getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
final Sources sources = Sources.getInstance(this);
- final Long selectedRawContactId = this.getSelectedRawContactId();
- // Remove any existing tabs and rebuild any visible
- mTabWidget.removeAllTabs();
- mTabRawContacts.clear();
- for (EntityDelta entity : mState) {
+ // Remove any existing editors and rebuild any visible
+
+ mContent.removeAllViews();
+ mEntities = new EntityDelta[mState.size()];
+ int size = mState.size();
+ for (int i = 0; i < size; i++) {
+ // TODO ensure proper ordering of entities in the list
+ EntityDelta entity = mState.get(i);
final ValuesDelta values = entity.getValues();
if (!values.isVisible()) continue;
final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
- final Long rawContactId = values.getAsLong(RawContacts._ID);
final ContactsSource source = sources.getInflatedSource(accountType,
ContactsSource.LEVEL_CONSTRAINTS);
- final int tabIndex = mTabWidget.getTabCount();
- final View tabView = ContactsUtils.createTabIndicatorView(
- mTabWidget.getTabParent(), source);
- mTabWidget.addTab(tabView);
- mTabRawContacts.put(tabIndex, rawContactId);
- }
-
- final boolean hasActiveTabs = mTabWidget.getTabCount() > 0;
- if (hasActiveTabs) {
- // Focus on last selected contact
- this.setSelectedRawContactId(selectedRawContactId);
- } else {
- // Nothing remains to edit, save and bail entirely
- this.doSaveAction(SAVE_MODE_DEFAULT);
+ ContactEditorView editor = (ContactEditorView) inflater.inflate(
+ R.layout.item_contact_editor, mContent, false);
+ mContent.addView(editor);
+ editor.setState(entity, source);
+ mEntities[i] = entity;
}
// Show editor now that we've loaded state
- mEditor.setVisibility(View.VISIBLE);
- }
-
- /**
- * Bind our header based on {@link #mState}, which include any edits.
- * Usually called once {@link Entity} data has been loaded, or after a
- * primary {@link Data} change.
- */
- protected void bindHeader() {
- if (!hasValidState()) return;
-
- boolean starred = false;
-
- ValuesDelta photoDelta = mState.getSuperPrimaryEntry(Photo.CONTENT_ITEM_TYPE);
- if (photoDelta != null) {
- final byte[] photoBytes = photoDelta.getAsByteArray(Photo.PHOTO);
- if (photoBytes != null) {
- Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
- photoBytes.length);
- mHeader.setPhoto(photo);
- }
- }
-
- ValuesDelta nameDelta = mState.getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
- if (nameDelta != null) {
- String visibleName = getVisibleName(nameDelta);
- if (visibleName != null) {
- mHeader.setDisplayName(visibleName, null);
- }
- }
-
- for (EntityDelta delta : mState) {
- Long isCurrStarred = delta.getValues().getAsLong(RawContacts.STARRED);
- starred = starred || (isCurrStarred != null && isCurrStarred != 0);
- }
- mHeader.setStared(starred);
- }
-
- private static String getVisibleName(ValuesDelta nameDelta) {
- final String givenName = nameDelta.getAsString(StructuredName.GIVEN_NAME);
- final String familyName = nameDelta.getAsString(StructuredName.FAMILY_NAME);
- final boolean hasGiven = !TextUtils.isEmpty(givenName);
- final boolean hasFamily = !TextUtils.isEmpty(familyName);
-
- if (hasGiven && hasFamily) {
- return givenName + " " + familyName;
- } else if (hasFamily) {
- return familyName;
- } else if (hasGiven) {
- return givenName;
- } else {
- return null;
- }
- }
-
- /** {@inheritDoc} */
- public void onTabSelectionChanged(int tabIndex, boolean clicked) {
- if (!hasValidState()) return;
-
- // Find entity and source for selected tab
- final EntityDelta entity = this.getSelectedEntityDelta();
- if (entity == null) return;
-
- final Sources sources = Sources.getInstance(this);
- final ValuesDelta values = entity.getValues();
- final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
- final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
- final ContactsSource source = sources.getInflatedSource(accountType,
- ContactsSource.LEVEL_CONSTRAINTS);
-
- mAccountName.setText(getString(R.string.account_name_format,
- source.getDisplayLabel(this), accountName));
- mAccountName.setVisibility(View.VISIBLE);
-
- // Assign editor state based on entity and source
- mEditor.setState(entity, source);
+ mContent.setVisibility(View.VISIBLE);
}
/** {@inheritDoc} */
switch (requestCode) {
case PHOTO_PICKED_WITH_DATA: {
+/*
// When reaching this point, we've already inflated our tab
// state and returned to the last-visible tab.
final Bitmap photo = data.getParcelableExtra("data");
mEditor.setPhotoBitmap(photo);
- bindHeader();
break;
+*/
}
case REQUEST_JOIN_CONTACT: {
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- final boolean hasPhotoEditor = mEditor.hasPhotoEditor();
- final boolean hasSetPhoto = mEditor.hasSetPhoto();
-
- menu.findItem(R.id.menu_photo_add).setVisible(hasPhotoEditor);
- menu.findItem(R.id.menu_photo_remove).setVisible(hasSetPhoto);
-
- return true;
- }
-
- @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_done:
return doAddAction();
case R.id.menu_delete:
return doDeleteAction();
- case R.id.menu_photo_add:
- return doPickPhotoAction();
- case R.id.menu_photo_remove:
- return doRemovePhotoAction();
case R.id.menu_split:
return doSplitContactAction();
case R.id.menu_join:
* Saves or creates the contact based on the mode, and if successful
* finishes the activity.
*/
- private boolean doSaveAction(int saveMode) {
+ boolean doSaveAction(int saveMode) {
if (!hasValidState()) return false;
final PersistTask task = new PersistTask(this, saveMode);
return true;
}
- /**
- * Clear any existing photo under the currently selected tab.
- */
- public boolean doRemovePhotoAction() {
- if (!hasValidState()) return false;
-
- // Remove photo from selected contact
- mEditor.setPhotoBitmap(null);
- return true;
- }
-
/** {@inheritDoc} */
public void onDeleted(Editor editor) {
// Ignore any editor deletes
break;
}
case EditorListener.FIELD_CHANGED: {
- bindHeader();
break;
}
}
// Update the UI.
EditContactActivity target = mTarget.get();
if (target != null) {
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
};
// Account was auto-selected on the background thread,
// but we need to update the UI still in the
// now-current UI thread.
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
}
builder.setMessage(R.string.deleteConfirmation);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- // Mark the currently selected contact for deletion
- final EntityDelta delta = getSelectedEntityDelta();
- if (delta == null) return;
- delta.markDeleted();
+ // Mark all raw contacts for deletion
+ for (EntityDelta delta : mState) {
+ delta.markDeleted();
+ }
- bindTabs();
- bindHeader();
+ // Save the deletes
+ doSaveAction(SAVE_MODE_DEFAULT);
+ finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
final ValuesDelta structuredName = allNames.get(which);
structuredName.put(Data.IS_PRIMARY, 1);
structuredName.put(Data.IS_SUPER_PRIMARY, 1);
-
- // Update header based on edited values
- bindHeader();
}
};
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
-import android.widget.RelativeLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
/**
* adding {@link Data} rows or changing {@link EditType}, are performed through
* {@link EntityModifier} to ensure that {@link ContactsSource} are enforced.
*/
-public class ContactEditorView extends RelativeLayout implements OnClickListener {
+public class ContactEditorView extends LinearLayout implements OnClickListener {
private LayoutInflater mInflater;
private TextView mReadOnly;
private Drawable mSecondaryOpen;
private Drawable mSecondaryClosed;
+ private View mHeader;
+ private View mSideBar;
+ private ImageView mHeaderIcon;
+ private TextView mHeaderAccountType;
+ private TextView mHeaderAccountName;
+
public ContactEditorView(Context context) {
super(context);
}
mGeneral = (ViewGroup)findViewById(R.id.sect_general);
mSecondary = (ViewGroup)findViewById(R.id.sect_secondary);
+ mHeader = findViewById(R.id.header);
+ mSideBar = findViewById(R.id.color_bar);
+ mHeaderIcon = (ImageView) findViewById(R.id.header_icon);
+ mHeaderAccountType = (TextView) findViewById(R.id.header_account_type);
+ mHeaderAccountName = (TextView) findViewById(R.id.header_account_name);
+
mSecondaryHeader = (TextView)findViewById(R.id.head_secondary);
mSecondaryHeader.setOnClickListener(this);
// Make sure we have StructuredName
EntityModifier.ensureKindExists(state, source, StructuredName.CONTENT_ITEM_TYPE);
+ // Fill in the header info
+ mHeader.setBackgroundColor(source.getHeaderColor(mContext));
+ mSideBar.setBackgroundColor(source.getSideBarColor(mContext));
+ ValuesDelta values = state.getValues();
+ String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
+ if (TextUtils.isEmpty(accountName)) {
+ // TODO get from resource
+ accountName = "Local contact";
+ }
+ mHeaderAccountName.setText(accountName);
+ mHeaderAccountType.setText(source.getDisplayLabel(mContext));
+ mHeaderIcon.setImageDrawable(source.getDisplayIcon(mContext));
+
// Show photo editor when supported
EntityModifier.ensureKindExists(state, source, Photo.CONTENT_ITEM_TYPE);
mHasPhotoEditor = (source.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null);
mPhoto.setEnabled(!source.readOnly);
mName.setEnabled(!source.readOnly);
- mReadOnly.setVisibility(source.readOnly ? View.VISIBLE : View.GONE);
-
+ boolean readOnly = source.readOnly;
+ if (readOnly) {
+ mGeneral.setVisibility(View.GONE);
+ mSecondary.setVisibility(View.GONE);
+ mSecondaryHeader.setVisibility(View.GONE);
+ } else {
+ mReadOnly.setVisibility(View.GONE);
+ }
+
// Create editor sections for each possible data kind
for (DataKind kind : source.getSortedDataKinds()) {
// Skip kind of not editable
// Handle special case editor for photos
final ValuesDelta primary = state.getPrimaryEntry(mimeType);
mPhoto.setValues(kind, primary, state, source.readOnly);
- } else {
+ } else if (!readOnly) {
// Otherwise use generic section-based editors
if (kind.fieldList == null) continue;
final ViewGroup parent = kind.secondary ? mSecondary : mGeneral;
addKind(kind);
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffffff;
+ }
}
/**