Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f471a82d authored by Daisuke Miyakawa's avatar Daisuke Miyakawa Committed by Android (Google) Code Review
Browse files

Merge "Introduce a "loading" view for phove favorite"

parents 8ca93ed0 90f40d01
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 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.
-->

<!-- "Loading" text with a spinner, which is used in PhoneFavorite screen -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal"
    android:gravity="left|center_vertical">

    <ProgressBar
        android:indeterminate="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progress_spinner"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/contact_list_loading"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_marginLeft="4dip" />

</LinearLayout>
+1 −1
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment
        final ContactListFilter filter = getFilter();
        if (filter != null && !isSearchMode()) {
            final boolean shouldShowHeader = AccountFilterUtil.updateAccountFilterTitleForPeople(
                    mAccountFilterHeader, filter, false, false);
                    mAccountFilterHeader, filter, false);
            mAccountFilterHeader.setVisibility(shouldShowHeader ? View.VISIBLE : View.GONE);
        } else {
            mAccountFilterHeader.setVisibility(View.GONE);
+34 −6
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import com.android.contacts.util.AccountFilterUtil;
import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
@@ -34,6 +33,8 @@ import android.database.Cursor;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Directory;
import android.provider.Settings;
@@ -132,7 +133,8 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
            if (DEBUG) Log.d(TAG, "AllContactsLoaderListener#onLoadFinished");
            mAllContactsAdapter.changeCursor(0, data);
            updateFilterHeaderView();
            mAccountFilterHeaderContainer.setVisibility(View.VISIBLE);
            mHandler.removeMessages(MESSAGE_SHOW_LOADING_EFFECT);
            mLoadingView.setVisibility(View.VISIBLE);
        }

        @Override
@@ -202,6 +204,19 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        }
    }

    private static final int MESSAGE_SHOW_LOADING_EFFECT = 1;
    private static final int LOADING_EFFECT_DELAY = 500;  // ms
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_SHOW_LOADING_EFFECT:
                    mLoadingView.setVisibility(View.VISIBLE);
                    break;
            }
        }
    };

    private Listener mListener;
    private PhoneFavoriteMergedAdapter mAdapter;
    private ContactTileAdapter mContactTileAdapter;
@@ -229,6 +244,12 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
    private FrameLayout mAccountFilterHeaderContainer;
    private View mAccountFilterHeader;

    /**
     * Layout used when contacts load is slower than expected and thus "loading" view should be
     * shown.
     */
    private View mLoadingView;

    private final ContactTileView.Listener mContactTileAdapterListener =
            new ContactTileAdapterListener();
    private final LoaderManager.LoaderCallbacks<Cursor> mContactTileLoaderListener =
@@ -323,10 +344,12 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
                mListView, false);
        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
        mAccountFilterHeaderContainer.addView(mAccountFilterHeader);
        mAccountFilterHeaderContainer.setVisibility(View.GONE);

        mLoadingView = inflater.inflate(R.layout.phone_loading_contacts, mListView, false);

        mAdapter = new PhoneFavoriteMergedAdapter(getActivity(),
                mContactTileAdapter, mAccountFilterHeaderContainer, mAllContactsAdapter);
                mContactTileAdapter, mAccountFilterHeaderContainer, mAllContactsAdapter,
                mLoadingView);

        mListView.setAdapter(mAdapter);

@@ -411,6 +434,12 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
        // be called, on which we'll check if "all" contacts should be reloaded again or not.
        getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);

        // Delay showing "loading" view until certain amount of time so that users won't see
        // instant flash of the view when the contacts load is fast enough.
        // This will be kept shown until both tile and all sections are loaded.
        mLoadingView.setVisibility(View.INVISIBLE);
        mHandler.sendEmptyMessageDelayed(MESSAGE_SHOW_LOADING_EFFECT, LOADING_EFFECT_DELAY);
    }

    @Override
@@ -502,8 +531,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        if (mAccountFilterHeader == null || mAllContactsAdapter == null || filter == null) {
            return;
        }
        AccountFilterUtil.updateAccountFilterTitleForPhone(
                mAccountFilterHeader, filter, mAllContactsAdapter.isLoading(), true);
        AccountFilterUtil.updateAccountFilterTitleForPhone(mAccountFilterHeader, filter, true);
    }

    public ContactListFilter getFilter() {
+101 −32
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
    private final ContactTileAdapter mContactTileAdapter;
    private final ContactEntryListAdapter mContactEntryListAdapter;
    private final View mAccountFilterHeaderContainer;
    private final View mLoadingView;

    private final int mItemPaddingLeft;
    private final int mItemPaddingRight;
@@ -56,7 +57,8 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
    public PhoneFavoriteMergedAdapter(Context context,
            ContactTileAdapter contactTileAdapter,
            View accountFilterHeaderContainer,
            ContactEntryListAdapter contactEntryListAdapter) {
            ContactEntryListAdapter contactEntryListAdapter,
            View loadingView) {
        Resources resources = context.getResources();
        mItemPaddingLeft = resources.getDimensionPixelSize(R.dimen.detail_item_side_margin);
        mItemPaddingRight = resources.getDimensionPixelSize(R.dimen.list_visible_scrollbar_padding);
@@ -70,6 +72,8 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
        mObserver = new CustomDataSetObserver();
        mContactTileAdapter.registerDataSetObserver(mObserver);
        mContactEntryListAdapter.registerDataSetObserver(mObserver);

        mLoadingView = loadingView;
    }

    @Override
@@ -77,9 +81,12 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
        final int contactTileAdapterCount = mContactTileAdapter.getCount();
        final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
        if (mContactEntryListAdapter.isLoading()) {
            // Hide "all" contacts during its being loaded.
            return contactTileAdapterCount + 1;
            // Hide "all" contacts during its being loaded. Instead show "loading" view.
            //
            // "+2" for mAccountFilterHeaderContainer and mLoadingView
            return contactTileAdapterCount + 2;
        } else {
            // "+1" for mAccountFilterHeaderContainer
            return contactTileAdapterCount + contactEntryListAdapterCount + 1;
        }
    }
@@ -88,15 +95,20 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
    public Object getItem(int position) {
        final int contactTileAdapterCount = mContactTileAdapter.getCount();
        final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
        if (position < contactTileAdapterCount) {
        if (position < contactTileAdapterCount) {  // For "tile" and "frequent" sections
            return mContactTileAdapter.getItem(position);
        } else if (position == contactTileAdapterCount) {
        } else if (position == contactTileAdapterCount) {  // For "all" section's account header
            return mAccountFilterHeaderContainer;
        } else {  // For "all" section
            if (mContactEntryListAdapter.isLoading()) {  // "All" section is being loaded.
                return mLoadingView;
            } else {
                // "-1" for mAccountFilterHeaderContainer
                final int localPosition = position - contactTileAdapterCount - 1;
                return mContactTileAdapter.getItem(localPosition);
            }
        }
    }

    @Override
    public long getItemId(int position) {
@@ -105,27 +117,65 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn

    @Override
    public int getViewTypeCount() {
        // "+2" for mAccountFilterHeaderContainer and mLoadingView
        return (mContactTileAdapter.getViewTypeCount()
                + mContactEntryListAdapter.getViewTypeCount()
                + 1);
                + 2);
    }

    @Override
    public int getItemViewType(int position) {
        final int contactTileAdapterCount = mContactTileAdapter.getCount();
        final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
        if (position < contactTileAdapterCount) {
        // There should be four kinds of types that are usually used, and one more exceptional
        // type (IGNORE_ITEM_VIEW_TYPE), which sometimes comes from mContactTileAdapter.
        //
        // The four ordinary view types have the index equal to or more than 0, and less than
        // mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount() + 2.
        // (See also this class's getViewTypeCount())
        //
        // We have those values for:
        // - The view types mContactTileAdapter originally has
        // - The view types mContactEntryListAdapter originally has
        // - mAccountFilterHeaderContainer ("all" section's account header), and
        // - mLoadingView
        //
        // Those types should not be mixed, so we have a different range for each kinds of types:
        // - Types for mContactTileAdapter ("tile" and "frequent" sections)
        //   They should have the index, >=0 and <mContactTileAdapter.getViewTypeCount()
        //
        // - Types for mContactEntryListAdapter ("all" sections)
        //   They should have the index, >=mContactTileAdapter.getViewTypeCount() and
        //   <(mContactTileAdapter.getViewTypeCount() + mContactEntryListAdapter.getViewTypeCount())
        //
        // - Type for "all" section's account header
        //   It should have the exact index
        //   mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount()
        //
        // - Type for "loading" view used during "all" section is being loaded.
        //   It should have the exact index
        //   mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount() + 1
        //
        // As an exception, IGNORE_ITEM_VIEW_TYPE (-1) will be remained as is, which will be used
        // by framework's Adapter implementation and thus should be left as is.
        if (position < contactTileAdapterCount) {  // For "tile" and "frequent" sections
            return mContactTileAdapter.getItemViewType(position);
        } else if (position == contactTileAdapterCount) {
        } else if (position == contactTileAdapterCount) {  // For "all" section's account header
            return mContactTileAdapter.getViewTypeCount()
                    + mContactEntryListAdapter.getViewTypeCount();
        } else {  // For "all" section
            if (mContactEntryListAdapter.isLoading()) {  // "All" section is being loaded.
                return mContactTileAdapter.getViewTypeCount()
                        + mContactEntryListAdapter.getViewTypeCount() + 1;
            } else {
                // "-1" for mAccountFilterHeaderContainer
                final int localPosition = position - contactTileAdapterCount - 1;
                final int type = mContactEntryListAdapter.getItemViewType(localPosition);
                // IGNORE_ITEM_VIEW_TYPE must be handled differently.
                return (type < 0) ? type : type + mContactTileAdapter.getViewTypeCount();
            }
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
@@ -134,7 +184,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn

        // Obtain a View relevant for that position, and adjust its horizontal padding. Each
        // View has different implementation, so we use different way to control those padding.
        if (position < contactTileAdapterCount) {
        if (position < contactTileAdapterCount) {  // For "tile" and "frequent" sections
            final View view = mContactTileAdapter.getView(position, convertView, parent);
            final int frequentHeaderPosition = mContactTileAdapter.getFrequentHeaderPosition();
            if (position < frequentHeaderPosition) {  // "starred" contacts
@@ -153,13 +203,21 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
                child.setLayoutParams(params);
            }
            return view;
        } else if (position == contactTileAdapterCount) {
        } else if (position == contactTileAdapterCount) {  // For "all" section's account header
            mAccountFilterHeaderContainer.setPadding(mItemPaddingLeft,
                    mAccountFilterHeaderContainer.getPaddingTop(),
                    mItemPaddingRight,
                    mAccountFilterHeaderContainer.getPaddingBottom());
            return mAccountFilterHeaderContainer;
        } else {  // For "all" section
            if (mContactEntryListAdapter.isLoading()) {  // "All" section is being loaded.
                mLoadingView.setPadding(mItemPaddingLeft,
                        mLoadingView.getPaddingTop(),
                        mItemPaddingRight,
                        mLoadingView.getPaddingBottom());
                return mLoadingView;
            } else {
                // "-1" for mAccountFilterHeaderContainer
                final int localPosition = position - contactTileAdapterCount - 1;
                final ContactListItemView itemView = (ContactListItemView)
                        mContactEntryListAdapter.getView(localPosition, convertView, null);
@@ -169,10 +227,15 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
                return itemView;
            }
        }
    }

    @Override
    public boolean areAllItemsEnabled() {
        return (mContactTileAdapter.areAllItemsEnabled()
        // If "all" section is being loaded we'll show mLoadingView, which is not enabled.
        // Otherwise check the all the other components in the ListView and return appropriate
        // result.
        return !mContactEntryListAdapter.isLoading()
                && (mContactTileAdapter.areAllItemsEnabled()
                && mAccountFilterHeaderContainer.isEnabled()
                && mContactEntryListAdapter.areAllItemsEnabled());
    }
@@ -181,16 +244,21 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
    public boolean isEnabled(int position) {
        final int contactTileAdapterCount = mContactTileAdapter.getCount();
        final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount();
        if (position < contactTileAdapterCount) {
        if (position < contactTileAdapterCount) {  // For "tile" and "frequent" sections
            return mContactTileAdapter.isEnabled(position);
        } else if (position == contactTileAdapterCount) {
        } else if (position == contactTileAdapterCount) {  // For "all" section's account header
            // This will be handled by View's onClick event instead of ListView's onItemClick event.
            return false;
        } else {  // For "all" section
            if (mContactEntryListAdapter.isLoading()) {  // "All" section is being loaded.
                return false;
            } else {
                // "-1" for mAccountFilterHeaderContainer
                final int localPosition = position - contactTileAdapterCount - 1;
                return mContactEntryListAdapter.isEnabled(localPosition);
            }
        }
    }

    @Override
    public int getPositionForSection(int sectionIndex) {
@@ -205,6 +273,7 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn
        if (position <= contactTileAdapterCount) {
            return 0;
        } else {
            // "-1" for mAccountFilterHeaderContainer
            final int localPosition = position - contactTileAdapterCount - 1;
            return mContactEntryListAdapter.getSectionForPosition(localPosition);
        }
+1 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactE
            return;
        }
        final boolean shouldShowHeader = AccountFilterUtil.updateAccountFilterTitleForPhone(
                mAccountFilterHeader, filter, false, false);
                mAccountFilterHeader, filter, false);
        if (shouldShowHeader) {
            mPaddingView.setVisibility(View.GONE);
            mAccountFilterHeader.setVisibility(View.VISIBLE);
Loading