Merge "Fix photo + basic contact info header on tablet"
diff --git a/res/layout/group_list_header_item.xml b/res/layout/group_browse_list_account_header.xml
similarity index 98%
rename from res/layout/group_list_header_item.xml
rename to res/layout/group_browse_list_account_header.xml
index b38920f..73684c1 100644
--- a/res/layout/group_list_header_item.xml
+++ b/res/layout/group_browse_list_account_header.xml
@@ -33,6 +33,7 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/people_app_theme_color"
android:textStyle="bold"
+ android:textAllCaps="true"
android:singleLine="true"/>
<TextView
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
index b829704..ecdc132 100644
--- a/res/layout/group_browse_list_item.xml
+++ b/res/layout/group_browse_list_item.xml
@@ -14,21 +14,48 @@
limitations under the License.
-->
-<view
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.contacts.group.GroupBrowseListAdapter$GroupListItem"
- android:orientation="horizontal"
+ android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingBottom="10dip"
style="@style/GroupBrowseListItem">
+ <ImageView
+ android:id="@+id/divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_marginBottom="10dip"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:scaleType="fitXY"
+ android:src="@color/people_app_theme_color"/>
+
+ <include
+ android:id="@+id/group_list_header"
+ layout="@layout/group_browse_list_account_header"
+ android:visibility="gone" />
+
<TextView
android:id="@+id/label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:padding="10dip"
- android:textAppearance="?android:attr/textAppearanceLarge"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="end"
android:singleLine="true" />
-</view>
+ <TextView
+ android:id="@+id/count"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingLeft="10dip"
+ android:paddingRight="10dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorTertiary"
+ android:ellipsize="end"
+ android:singleLine="true" />
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7d11c54..7f729f6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1557,6 +1557,12 @@
<item quantity="other"><xliff:g id="count">%1$d</xliff:g> people from <xliff:g id="account_type">%2$s</xliff:g></item>
</plurals>
+ <!-- Subtitle of a group (in the group list) that describes how many people are in the current group [CHAR LIMIT=30] -->
+ <plurals name="group_list_num_contacts_in_group">
+ <item quantity="one"><xliff:g id="count">%1$d</xliff:g> person</item>
+ <item quantity="other"><xliff:g id="count">%1$d</xliff:g> people</item>
+ </plurals>
+
<!-- Toast displayed when the user creates a new contact and attempts to join it
with another before entering any data [CHAR LIMIT=256] -->
<string name="toast_join_with_empty_contact">Please enter contact name before joining
diff --git a/src/com/android/contacts/GroupListLoader.java b/src/com/android/contacts/GroupListLoader.java
new file mode 100644
index 0000000..49aa602
--- /dev/null
+++ b/src/com/android/contacts/GroupListLoader.java
@@ -0,0 +1,52 @@
+/*
+ * 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.contacts;
+
+import android.content.Context;
+import android.content.CursorLoader;
+import android.provider.ContactsContract.Groups;
+
+/**
+ * Group loader for the group list that includes details such as the number of contacts per group.
+ * This group list excludes default, favorite, and deleted groups.
+ */
+public final class GroupListLoader extends CursorLoader {
+
+ private final static String[] COLUMNS = new String[] {
+ Groups.ACCOUNT_NAME,
+ Groups.ACCOUNT_TYPE,
+ Groups._ID,
+ Groups.TITLE,
+ Groups.ACTION,
+ Groups.ACTION_URI,
+ Groups.SUMMARY_COUNT,
+ };
+
+ public final static int ACCOUNT_NAME = 0;
+ public final static int ACCOUNT_TYPE = 1;
+ public final static int GROUP_ID = 2;
+ public final static int TITLE = 3;
+ public final static int ACTION = 4;
+ public final static int ACTION_URI = 5;
+ public final static int MEMBER_COUNT = 6;
+
+ public GroupListLoader(Context context) {
+ super(context, Groups.CONTENT_SUMMARY_URI, COLUMNS, Groups.ACCOUNT_TYPE + " NOT NULL AND "
+ + Groups.ACCOUNT_NAME + " NOT NULL AND " + Groups.AUTO_ADD + "=0 AND " +
+ Groups.FAVORITES + "=0 AND " + Groups.DELETED + "=0", null,
+ Groups.ACCOUNT_NAME + " ASC");
+ }
+}
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
index 2dd194d..d44733b 100644
--- a/src/com/android/contacts/group/GroupBrowseListAdapter.java
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -16,28 +16,22 @@
package com.android.contacts.group;
-import com.android.contacts.GroupMetaData;
+import com.android.contacts.GroupListLoader;
import com.android.contacts.R;
import com.android.contacts.model.AccountType;
import com.android.contacts.model.AccountTypeManager;
-import android.accounts.Account;
import android.content.ContentUris;
import android.content.Context;
+import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.Groups;
-import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
/**
* Adapter to populate the list of groups.
*/
@@ -47,49 +41,36 @@
private final LayoutInflater mLayoutInflater;
private final AccountTypeManager mAccountTypeManager;
- private List<GroupListEntry> mGroupList = new ArrayList<GroupListEntry>();
+ private Cursor mCursor;
+
private boolean mSelectionVisible;
private Uri mSelectedGroupUri;
- enum ViewType {
- HEADER, ITEM;
- }
-
- private static final int VIEW_TYPE_COUNT = ViewType.values().length;
-
- public GroupBrowseListAdapter(Context context, Map<Account, List<GroupMetaData>> groupMap) {
+ public GroupBrowseListAdapter(Context context) {
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
mAccountTypeManager = AccountTypeManager.getInstance(mContext);
+ }
- for (Account account : groupMap.keySet()) {
- List<GroupMetaData> groupsListForAccount = groupMap.get(account);
-
- // Add account name, type, and # of groups as header for section
- mGroupList.add(GroupListEntry.createEntryForHeader(account.name, account.type,
- groupsListForAccount.size()));
-
- // Add groups within that account as subsequent list items.
- for (GroupMetaData singleGroup : groupsListForAccount) {
- mGroupList.add(GroupListEntry.createEntryForGroup(singleGroup));
- }
- }
+ public void setCursor(Cursor cursor) {
+ mCursor = cursor;
+ notifyDataSetChanged();
}
public int getSelectedGroupPosition() {
- if (mSelectedGroupUri == null) {
+ if (mSelectedGroupUri == null || mCursor == null || mCursor.getCount() == 0) {
return -1;
}
- int size = mGroupList.size();
- for (int i = 0; i < size; i++) {
- GroupListEntry group = mGroupList.get(i);
- if (group.type == ViewType.ITEM) {
- Uri uri = getGroupUriFromId(group.groupData.getGroupId());
- if (mSelectedGroupUri.equals(uri)) {
- return i;
- }
+ int index = 0;
+ mCursor.moveToPosition(-1);
+ while (mCursor.moveToNext()) {
+ long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
+ Uri uri = getGroupUriFromId(groupId);
+ if (mSelectedGroupUri.equals(uri)) {
+ return index;
}
+ index++;
}
return -1;
}
@@ -108,163 +89,123 @@
@Override
public int getCount() {
- return mGroupList.size();
+ return mCursor == null ? 0 : mCursor.getCount();
}
@Override
public long getItemId(int position) {
- return mGroupList.get(position).id;
+ return position;
}
@Override
- public GroupListEntry getItem(int position) {
- return mGroupList.get(position);
- }
+ public GroupListItem getItem(int position) {
+ if (mCursor == null || mCursor.isClosed() || !mCursor.moveToPosition(position)) {
+ return null;
+ }
+ String accountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
+ String accountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
+ long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
+ String title = mCursor.getString(GroupListLoader.TITLE);
+ int memberCount = mCursor.getInt(GroupListLoader.MEMBER_COUNT);
- @Override
- public int getItemViewType(int position) {
- return mGroupList.get(position).type.ordinal();
- }
+ // Figure out if this is the first group for this account name / account type pair by
+ // checking the previous entry. This is to determine whether or not we need to display an
+ // account header in this item.
+ int previousIndex = position - 1;
+ boolean isFirstGroupInAccount = true;
+ if (previousIndex >= 0 && mCursor.moveToPosition(previousIndex)) {
+ String previousGroupAccountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
+ String previousGroupAccountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
+ if (accountName.equals(previousGroupAccountName) &&
+ accountType.equals(previousGroupAccountType)) {
+ isFirstGroupInAccount = false;
+ }
+ }
- @Override
- public int getViewTypeCount() {
- return VIEW_TYPE_COUNT;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return mGroupList.get(position).type == ViewType.ITEM;
+ return new GroupListItem(accountName, accountType, groupId, title, isFirstGroupInAccount,
+ memberCount);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- GroupListEntry item = getItem(position);
- switch (item.type) {
- case HEADER:
- return getHeaderView(item, convertView, parent);
- case ITEM:
- return getGroupListItemView(item, convertView, parent);
- default:
- throw new IllegalStateException("Invalid GroupListEntry item type " + item.type);
+ GroupListItem entry = getItem(position);
+ View result;
+ GroupListItemViewCache viewCache;
+ if (convertView != null) {
+ result = convertView;
+ viewCache = (GroupListItemViewCache) result.getTag();
+ } else {
+ result = mLayoutInflater.inflate(R.layout.group_browse_list_item, parent, false);
+ viewCache = new GroupListItemViewCache(result);
+ result.setTag(viewCache);
}
- }
+ // Add a header if this is the first group in an account and hide the divider
+ if (entry.isFirstGroupInAccount()) {
+ bindHeaderView(entry, viewCache);
+ viewCache.accountHeader.setVisibility(View.VISIBLE);
+ viewCache.divider.setVisibility(View.GONE);
+ } else {
+ viewCache.accountHeader.setVisibility(View.GONE);
+ viewCache.divider.setVisibility(View.VISIBLE);
+ }
- private View getHeaderView(GroupListEntry entry, View convertView, ViewGroup parent) {
- View result = (convertView == null ?
- mLayoutInflater.inflate(R.layout.group_list_header_item, parent, false) :
- convertView);
+ // Bind the group data
+ Uri groupUri = getGroupUriFromId(entry.getGroupId());
+ String memberCountString = mContext.getResources().getQuantityString(
+ R.plurals.group_list_num_contacts_in_group, entry.getMemberCount(),
+ entry.getMemberCount());
+ viewCache.setUri(groupUri);
+ viewCache.groupTitle.setText(entry.getTitle());
+ viewCache.groupMemberCount.setText(memberCountString);
- TextView accountTypeTextView = (TextView) result.findViewById(R.id.account_type);
- AccountType accountType = mAccountTypeManager.getAccountType(entry.accountType);
- accountTypeTextView.setText(accountType.getDisplayLabel(mContext).toString().toUpperCase());
-
- TextView accountNameTextView = (TextView) result.findViewById(R.id.account_name);
- accountNameTextView.setText(entry.accountName);
-
- String groupCountString = mContext.getResources().getQuantityString(
- R.plurals.num_groups_in_account, entry.count, entry.count);
- TextView groupCountTextView = (TextView) result.findViewById(R.id.group_count);
- groupCountTextView.setText(groupCountString);
-
- return result;
- }
-
- private View getGroupListItemView(GroupListEntry entry, View convertView, ViewGroup parent) {
- GroupListItem result = (GroupListItem) (convertView == null ?
- mLayoutInflater.inflate(R.layout.group_browse_list_item, parent, false) :
- convertView);
- result.loadFromGroup(entry.groupData);
if (mSelectionVisible) {
- result.setActivated(isSelectedGroup(result.getUri()));
+ result.setActivated(isSelectedGroup(groupUri));
}
return result;
}
- /**
- * This is a data model object to represent one row in the list of groups were the entry
- * could be a header or group item.
- */
- public static class GroupListEntry {
- public final ViewType type;
- public final String accountType;
- public final String accountName;
- public final int count;
- public final GroupMetaData groupData;
- /**
- * The id is equal to the group ID (if groupData is available), otherwise it is -1 for
- * header entries.
- */
- public final long id;
+ private void bindHeaderView(GroupListItem entry, GroupListItemViewCache viewCache) {
+ AccountType accountType = mAccountTypeManager.getAccountType(entry.getAccountType());
+ viewCache.accountType.setText(accountType.getDisplayLabel(mContext).toString());
+ viewCache.accountName.setText(entry.getAccountName());
- private GroupListEntry(ViewType entryType, String groupAccountName, String groupAccountType,
- int headerGroupCount, GroupMetaData groupMetaData, long entryId) {
- type = entryType;
- accountName = groupAccountName;
- accountType = groupAccountType;
- count = headerGroupCount;
- groupData = groupMetaData;
- id = entryId;
- }
+ // TODO: Add in number of groups within this account name / type using this string:
+ // getQuantityString(R.plurals.num_groups_in_account, entry.count, entry.count);
+ }
- public static GroupListEntry createEntryForHeader(String groupAccountName,
- String groupAccountType, int groupCount) {
- return new GroupListEntry(ViewType.HEADER, groupAccountName, groupAccountType,
- groupCount, null, -1);
- }
-
- public static GroupListEntry createEntryForGroup(GroupMetaData groupMetaData) {
- if (groupMetaData == null) {
- throw new IllegalStateException("Cannot create list entry for a null group");
- }
- return new GroupListEntry(ViewType.ITEM, null, null, 0, groupMetaData,
- groupMetaData.getGroupId());
- }
+ private static Uri getGroupUriFromId(long groupId) {
+ return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
}
/**
- * A row in a list of groups, where this row displays a single group's title
- * and associated account.
+ * Cache of the children views of a contact detail entry represented by a
+ * {@link GroupListItem}
*/
- public static class GroupListItem extends LinearLayout {
-
- private TextView mLabel;
+ public static class GroupListItemViewCache {
+ public final TextView accountType;
+ public final TextView accountName;
+ public final TextView groupTitle;
+ public final TextView groupMemberCount;
+ public final View accountHeader;
+ public final View divider;
private Uri mUri;
- public GroupListItem(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
+ public GroupListItemViewCache(View view) {
+ accountType = (TextView) view.findViewById(R.id.account_type);
+ accountName = (TextView) view.findViewById(R.id.account_name);
+ groupTitle = (TextView) view.findViewById(R.id.label);
+ groupMemberCount = (TextView) view.findViewById(R.id.count);
+ accountHeader = view.findViewById(R.id.group_list_header);
+ divider = view.findViewById(R.id.divider);
}
- public GroupListItem(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public GroupListItem(Context context) {
- super(context);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mLabel = (TextView) findViewById(R.id.label);
- }
-
- public void loadFromGroup(GroupMetaData group) {
- mLabel.setText(group.getTitle());
- mUri = getGroupUriFromId(group.getGroupId());
+ public void setUri(Uri uri) {
+ mUri = uri;
}
public Uri getUri() {
return mUri;
}
}
-
- private static Uri getGroupUriFromId(long groupId) {
- return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
- }
}
\ No newline at end of file
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index 4e6bdbc..d0d370e 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -16,13 +16,11 @@
package com.android.contacts.group;
-import com.android.contacts.GroupMetaData;
-import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.GroupListLoader;
import com.android.contacts.R;
-import com.android.contacts.group.GroupBrowseListAdapter.GroupListItem;
+import com.android.contacts.group.GroupBrowseListAdapter.GroupListItemViewCache;
import com.android.contacts.widget.AutoScrollListView;
-import android.accounts.Account;
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
@@ -34,7 +32,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
-import android.provider.ContactsContract.Groups;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -47,11 +44,6 @@
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
* Fragment to display the list of groups.
*/
@@ -82,13 +74,6 @@
private static final String EXTRA_KEY_GROUP_URI = "groups.groupUri";
- /**
- * Map of {@link Account} to a list of {@link GroupMetaData} objects
- * representing groups within that account.
- */
- private final Map<Account, List<GroupMetaData>> mGroupMap =
- new HashMap<Account, List<GroupMetaData>>();
-
private View mRootView;
private AutoScrollListView mListView;
private View mEmptyView;
@@ -108,10 +93,25 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.group_browse_list_fragment, null);
+ mEmptyView = mRootView.findViewById(R.id.empty);
+
+ mAdapter = new GroupBrowseListAdapter(mContext);
+ mAdapter.setSelectionVisible(mSelectionVisible);
+ mAdapter.setSelectedGroup(mSelectedGroupUri);
+
mListView = (AutoScrollListView) mRootView.findViewById(R.id.list);
mListView.setOnFocusChangeListener(this);
mListView.setOnTouchListener(this);
- mEmptyView = mRootView.findViewById(R.id.empty);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ GroupListItemViewCache groupListItem = (GroupListItemViewCache) view.getTag();
+ if (groupListItem != null) {
+ viewGroup(groupListItem.getUri());
+ }
+ }
+ });
if (savedInstanceState != null) {
String groupUriString = savedInstanceState.getString(EXTRA_KEY_GROUP_URI);
@@ -173,7 +173,7 @@
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
- return new GroupMetaDataLoader(mContext, Groups.CONTENT_URI);
+ return new GroupListLoader(mContext);
}
@Override
@@ -190,64 +190,16 @@
if (mGroupListCursor == null) {
return;
}
- mGroupMap.clear();
- mGroupListCursor.moveToPosition(-1);
- while (mGroupListCursor.moveToNext()) {
- String accountName = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_NAME);
- String accountType = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
- long groupId = mGroupListCursor.getLong(GroupMetaDataLoader.GROUP_ID);
- String title = mGroupListCursor.getString(GroupMetaDataLoader.TITLE);
- boolean deleted =
- (mGroupListCursor.getInt(GroupMetaDataLoader.DELETED) == 1);
- boolean defaultGroup = mGroupListCursor.isNull(GroupMetaDataLoader.AUTO_ADD)
- ? false
- : mGroupListCursor.getInt(GroupMetaDataLoader.AUTO_ADD) != 0;
- boolean favorites = mGroupListCursor.isNull(GroupMetaDataLoader.FAVORITES)
- ? false
- : mGroupListCursor.getInt(GroupMetaDataLoader.FAVORITES) != 0;
-
- // Don't show the "auto-added" (i.e. My Contacts) or "favorites" groups because
- // they show up elsewhere in the app. Also skip groups that are marked as "deleted"
- if (defaultGroup || favorites || deleted) {
- continue;
- }
-
- GroupMetaData newGroup = new GroupMetaData(accountName, accountType, groupId, title,
- defaultGroup, favorites);
- Account account = new Account(accountName, accountType);
-
- if (mGroupMap.containsKey(account)) {
- List<GroupMetaData> groups = mGroupMap.get(account);
- groups.add(newGroup);
- } else {
- List<GroupMetaData> groups = new ArrayList<GroupMetaData>();
- groups.add(newGroup);
- mGroupMap.put(account, groups);
- }
-
- }
-
- mAdapter = new GroupBrowseListAdapter(mContext, mGroupMap);
- mAdapter.setSelectionVisible(mSelectionVisible);
- mAdapter.setSelectedGroup(mSelectedGroupUri);
+ mAdapter.setCursor(mGroupListCursor);
Parcelable listState = mListView.onSaveInstanceState();
- mListView.setAdapter(mAdapter);
- mListView.setEmptyView(mEmptyView);
- mListView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- GroupListItem groupListItem = (GroupListItem) view;
- viewGroup(groupListItem.getUri());
- }
- });
-
if (mSelectionToScreenRequested) {
requestSelectionToScreen();
} else {
// Restore the scroll position.
mListView.onRestoreInstanceState(listState);
}
+ mListView.setEmptyView(mEmptyView);
if (mSelectionVisible && mSelectedGroupUri != null) {
viewGroup(mSelectedGroupUri);
@@ -260,6 +212,9 @@
public void setSelectionVisible(boolean flag) {
mSelectionVisible = flag;
+ if (mAdapter != null) {
+ mAdapter.setSelectionVisible(mSelectionVisible);
+ }
}
private void setSelectedGroup(Uri groupUri) {
diff --git a/src/com/android/contacts/group/GroupListItem.java b/src/com/android/contacts/group/GroupListItem.java
new file mode 100644
index 0000000..4740c44
--- /dev/null
+++ b/src/com/android/contacts/group/GroupListItem.java
@@ -0,0 +1,67 @@
+/*
+ * 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.contacts.group;
+
+/**
+ * Meta-data for a contact group. We load all groups associated with the contact's
+ * constituent accounts.
+ */
+public final class GroupListItem {
+ private final String mAccountName;
+ private final String mAccountType;
+ private final long mGroupId;
+ private final String mTitle;
+ private final boolean mIsFirstGroupInAccount;
+ private final int mMemberCount;
+
+ public GroupListItem(String accountName, String accountType, long groupId, String title,
+ boolean isFirstGroupInAccount, int memberCount) {
+ this.mAccountName = accountName;
+ this.mAccountType = accountType;
+ this.mGroupId = groupId;
+ this.mTitle = title;
+ this.mIsFirstGroupInAccount = isFirstGroupInAccount;
+ this.mMemberCount = memberCount;
+ }
+
+ public String getAccountName() {
+ return mAccountName;
+ }
+
+ public String getAccountType() {
+ return mAccountType;
+ }
+
+ public long getGroupId() {
+ return mGroupId;
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public int getMemberCount() {
+ return mMemberCount;
+ }
+
+ public boolean hasMemberCount() {
+ return mMemberCount != -1;
+ }
+
+ public boolean isFirstGroupInAccount() {
+ return mIsFirstGroupInAccount;
+ }
+}
\ No newline at end of file