Loading res/values/colors.xml +5 −0 Original line number Diff line number Diff line Loading @@ -84,4 +84,9 @@ <!-- Color of background of all empty states. --> <color name="empty_state_background">#efefef</color> <!-- Colors of swipeRefreshLayout's spinning circle. --> <color name="swipe_refresh_color1">#0f9d58</color> <color name="swipe_refresh_color2">#dd4b37</color> <color name="swipe_refresh_color3">#4285f4</color> <color name="swipe_refresh_color4">#f4b400</color> </resources> res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -292,4 +292,7 @@ <!-- Minimum height for group name EditText --> <dimen name="group_name_edit_text_min_height">48dp</dimen> <!-- Distance to pull down before causing a refresh. --> <dimen name="pull_to_refresh_distance">40dp</dimen> </resources> src/com/android/contacts/activities/PeopleActivity.java +44 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.GravityCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.util.Log; import android.view.KeyCharacterMap; Loading @@ -54,6 +55,7 @@ import com.android.contacts.ContactSaveService; import com.android.contacts.ContactsDrawerActivity; import com.android.contacts.R; import com.android.contacts.activities.ActionBarAdapter.TabState; import com.android.contacts.common.Experiments; import com.android.contacts.common.activity.RequestPermissionsActivity; import com.android.contacts.common.interactions.ImportExportDialogFragment; import com.android.contacts.common.list.ContactEntryListFragment; Loading @@ -72,6 +74,7 @@ import com.android.contacts.common.model.account.GoogleAccountType; import com.android.contacts.common.util.Constants; import com.android.contacts.common.util.ImplicitIntentsUtil; import com.android.contacts.common.widget.FloatingActionButtonController; import com.android.contacts.commonbind.experiments.Flags; import com.android.contacts.editor.EditorIntents; import com.android.contacts.interactions.ContactDeletionInteraction; import com.android.contacts.interactions.ContactMultiDeletionInteraction; Loading Loading @@ -1408,6 +1411,47 @@ public class PeopleActivity extends ContactsDrawerActivity implements } getSupportActionBar().setTitle(actionBarTitle); } // Determine whether the account has pullToRefresh feature if (Flags.getInstance(this).getBoolean(Experiments.PULL_TO_REFRESH)) { setSwipeRefreshLayoutEnabledOrNot(filter); } } private void setSwipeRefreshLayoutEnabledOrNot(ContactListFilter filter) { final SwipeRefreshLayout swipeRefreshLayout = mAllFragment.getSwipeRefreshLayout(); if (swipeRefreshLayout == null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null"); } return; } swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setEnabled(false); if (mActionBarAdapter.isSearchMode()) { return; } if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType) && filter.dataSet == null && filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { swipeRefreshLayout.setEnabled(true); return; } // TODO(samchen): check against both FILTER_TYPE_ALL_ACCOUNTS and FILTER_TYPE_DEFAULT if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(this) .getAccounts(/* contactsWritableOnly */ true); if (accounts != null && accounts.size() > 0) { for (AccountWithDataSet account : accounts) { if (GoogleAccountType.ACCOUNT_TYPE.equals(account.type) && filter.dataSet == null) { swipeRefreshLayout.setEnabled(true); return; } } } } } private String getActionBarTitleForAccount(ContactListFilter filter) { Loading src/com/android/contacts/list/ContactBrowseListFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ public abstract class ContactBrowseListFragment extends private boolean mSelectionVerified; private int mLastSelectedPosition = -1; private boolean mRefreshingContactUri; private ContactListFilter mFilter; protected ContactListFilter mFilter; private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX; protected OnContactBrowserActionListener mListener; Loading src/com/android/contacts/list/DefaultContactBrowseListFragment.java +77 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,17 @@ */ package com.android.contacts.list; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.ContactsContract; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; Loading @@ -29,13 +35,19 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.contacts.R; import com.android.contacts.common.Experiments; import com.android.contacts.common.list.ContactListAdapter; import com.android.contacts.common.list.ContactListFilter; import com.android.contacts.common.list.ContactListFilterController; import com.android.contacts.common.list.ContactListItemView; import com.android.contacts.common.list.DefaultContactListAdapter; import com.android.contacts.common.list.FavoritesAndContactsLoader; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.common.model.account.GoogleAccountType; import com.android.contacts.commonbind.experiments.Flags; import java.util.List; /** * Fragment containing a contact list used for browsing (as compared to Loading @@ -45,6 +57,7 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment private View mSearchHeaderView; private View mSearchProgress; private TextView mSearchProgressText; private SwipeRefreshLayout mSwipeRefreshLayout; public DefaultContactBrowseListFragment() { setPhotoLoaderEnabled(true); Loading Loading @@ -119,6 +132,10 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment protected void onCreateView(LayoutInflater inflater, ViewGroup container) { super.onCreateView(inflater, container); if (Flags.getInstance(getActivity()).getBoolean(Experiments.PULL_TO_REFRESH)) { initSwipeRefreshLayout(); } // Putting the header view inside a container will allow us to make // it invisible later. See checkHeaderViewVisibility() FrameLayout headerContainer = new FrameLayout(inflater.getContext()); Loading @@ -131,6 +148,62 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment mSearchProgressText = (TextView) mSearchHeaderView.findViewById(R.id.totalContactsText); } private void initSwipeRefreshLayout() { mSwipeRefreshLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_refresh); if (mSwipeRefreshLayout == null) { return; } mSwipeRefreshLayout.setEnabled(true); // Request sync contacts mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { syncContacts(mFilter); new Handler().postDelayed(new Runnable() { @Override public void run() { mSwipeRefreshLayout.setRefreshing(false); } }, 3000 /* spinning time */); } }); mSwipeRefreshLayout.setColorSchemeResources( R.color.swipe_refresh_color1, R.color.swipe_refresh_color2, R.color.swipe_refresh_color3, R.color.swipe_refresh_color4); mSwipeRefreshLayout.setDistanceToTriggerSync( (int) getResources().getDimension(R.dimen.pull_to_refresh_distance)); } /** Request sync for Google accounts(not include G+ accounts) in filter. */ private void syncContacts(ContactListFilter filter) { if (filter == null) { return; } final Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType) && filter.dataSet == null) { final Account account = new Account(filter.accountName, filter.accountType); ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle); } else { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance( getActivity()).getAccounts(/* contactsWritableOnly= */ true); if (accounts != null && accounts.size() > 0) { for (AccountWithDataSet account : accounts) { if (GoogleAccountType.ACCOUNT_TYPE.equals(account.type) && filter.dataSet == null) { ContentResolver.requestSync(new Account(account.name, account.type), ContactsContract.AUTHORITY, bundle); } } } } } @Override protected void setSearchMode(boolean flag) { super.setSearchMode(flag); Loading Loading @@ -179,4 +252,8 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment } } } public SwipeRefreshLayout getSwipeRefreshLayout() { return mSwipeRefreshLayout; } } No newline at end of file Loading
res/values/colors.xml +5 −0 Original line number Diff line number Diff line Loading @@ -84,4 +84,9 @@ <!-- Color of background of all empty states. --> <color name="empty_state_background">#efefef</color> <!-- Colors of swipeRefreshLayout's spinning circle. --> <color name="swipe_refresh_color1">#0f9d58</color> <color name="swipe_refresh_color2">#dd4b37</color> <color name="swipe_refresh_color3">#4285f4</color> <color name="swipe_refresh_color4">#f4b400</color> </resources>
res/values/dimens.xml +3 −0 Original line number Diff line number Diff line Loading @@ -292,4 +292,7 @@ <!-- Minimum height for group name EditText --> <dimen name="group_name_edit_text_min_height">48dp</dimen> <!-- Distance to pull down before causing a refresh. --> <dimen name="pull_to_refresh_distance">40dp</dimen> </resources>
src/com/android/contacts/activities/PeopleActivity.java +44 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.GravityCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.util.Log; import android.view.KeyCharacterMap; Loading @@ -54,6 +55,7 @@ import com.android.contacts.ContactSaveService; import com.android.contacts.ContactsDrawerActivity; import com.android.contacts.R; import com.android.contacts.activities.ActionBarAdapter.TabState; import com.android.contacts.common.Experiments; import com.android.contacts.common.activity.RequestPermissionsActivity; import com.android.contacts.common.interactions.ImportExportDialogFragment; import com.android.contacts.common.list.ContactEntryListFragment; Loading @@ -72,6 +74,7 @@ import com.android.contacts.common.model.account.GoogleAccountType; import com.android.contacts.common.util.Constants; import com.android.contacts.common.util.ImplicitIntentsUtil; import com.android.contacts.common.widget.FloatingActionButtonController; import com.android.contacts.commonbind.experiments.Flags; import com.android.contacts.editor.EditorIntents; import com.android.contacts.interactions.ContactDeletionInteraction; import com.android.contacts.interactions.ContactMultiDeletionInteraction; Loading Loading @@ -1408,6 +1411,47 @@ public class PeopleActivity extends ContactsDrawerActivity implements } getSupportActionBar().setTitle(actionBarTitle); } // Determine whether the account has pullToRefresh feature if (Flags.getInstance(this).getBoolean(Experiments.PULL_TO_REFRESH)) { setSwipeRefreshLayoutEnabledOrNot(filter); } } private void setSwipeRefreshLayoutEnabledOrNot(ContactListFilter filter) { final SwipeRefreshLayout swipeRefreshLayout = mAllFragment.getSwipeRefreshLayout(); if (swipeRefreshLayout == null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Can not load swipeRefreshLayout, swipeRefreshLayout is null"); } return; } swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setEnabled(false); if (mActionBarAdapter.isSearchMode()) { return; } if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType) && filter.dataSet == null && filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { swipeRefreshLayout.setEnabled(true); return; } // TODO(samchen): check against both FILTER_TYPE_ALL_ACCOUNTS and FILTER_TYPE_DEFAULT if (filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS) { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(this) .getAccounts(/* contactsWritableOnly */ true); if (accounts != null && accounts.size() > 0) { for (AccountWithDataSet account : accounts) { if (GoogleAccountType.ACCOUNT_TYPE.equals(account.type) && filter.dataSet == null) { swipeRefreshLayout.setEnabled(true); return; } } } } } private String getActionBarTitleForAccount(ContactListFilter filter) { Loading
src/com/android/contacts/list/ContactBrowseListFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ public abstract class ContactBrowseListFragment extends private boolean mSelectionVerified; private int mLastSelectedPosition = -1; private boolean mRefreshingContactUri; private ContactListFilter mFilter; protected ContactListFilter mFilter; private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX; protected OnContactBrowserActionListener mListener; Loading
src/com/android/contacts/list/DefaultContactBrowseListFragment.java +77 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,17 @@ */ package com.android.contacts.list; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.ContactsContract; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; Loading @@ -29,13 +35,19 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.contacts.R; import com.android.contacts.common.Experiments; import com.android.contacts.common.list.ContactListAdapter; import com.android.contacts.common.list.ContactListFilter; import com.android.contacts.common.list.ContactListFilterController; import com.android.contacts.common.list.ContactListItemView; import com.android.contacts.common.list.DefaultContactListAdapter; import com.android.contacts.common.list.FavoritesAndContactsLoader; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.common.model.account.GoogleAccountType; import com.android.contacts.commonbind.experiments.Flags; import java.util.List; /** * Fragment containing a contact list used for browsing (as compared to Loading @@ -45,6 +57,7 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment private View mSearchHeaderView; private View mSearchProgress; private TextView mSearchProgressText; private SwipeRefreshLayout mSwipeRefreshLayout; public DefaultContactBrowseListFragment() { setPhotoLoaderEnabled(true); Loading Loading @@ -119,6 +132,10 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment protected void onCreateView(LayoutInflater inflater, ViewGroup container) { super.onCreateView(inflater, container); if (Flags.getInstance(getActivity()).getBoolean(Experiments.PULL_TO_REFRESH)) { initSwipeRefreshLayout(); } // Putting the header view inside a container will allow us to make // it invisible later. See checkHeaderViewVisibility() FrameLayout headerContainer = new FrameLayout(inflater.getContext()); Loading @@ -131,6 +148,62 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment mSearchProgressText = (TextView) mSearchHeaderView.findViewById(R.id.totalContactsText); } private void initSwipeRefreshLayout() { mSwipeRefreshLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_refresh); if (mSwipeRefreshLayout == null) { return; } mSwipeRefreshLayout.setEnabled(true); // Request sync contacts mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { syncContacts(mFilter); new Handler().postDelayed(new Runnable() { @Override public void run() { mSwipeRefreshLayout.setRefreshing(false); } }, 3000 /* spinning time */); } }); mSwipeRefreshLayout.setColorSchemeResources( R.color.swipe_refresh_color1, R.color.swipe_refresh_color2, R.color.swipe_refresh_color3, R.color.swipe_refresh_color4); mSwipeRefreshLayout.setDistanceToTriggerSync( (int) getResources().getDimension(R.dimen.pull_to_refresh_distance)); } /** Request sync for Google accounts(not include G+ accounts) in filter. */ private void syncContacts(ContactListFilter filter) { if (filter == null) { return; } final Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); if (GoogleAccountType.ACCOUNT_TYPE.equals(filter.accountType) && filter.dataSet == null) { final Account account = new Account(filter.accountName, filter.accountType); ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle); } else { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance( getActivity()).getAccounts(/* contactsWritableOnly= */ true); if (accounts != null && accounts.size() > 0) { for (AccountWithDataSet account : accounts) { if (GoogleAccountType.ACCOUNT_TYPE.equals(account.type) && filter.dataSet == null) { ContentResolver.requestSync(new Account(account.name, account.type), ContactsContract.AUTHORITY, bundle); } } } } } @Override protected void setSearchMode(boolean flag) { super.setSearchMode(flag); Loading Loading @@ -179,4 +252,8 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment } } } public SwipeRefreshLayout getSwipeRefreshLayout() { return mSwipeRefreshLayout; } } No newline at end of file