ExpandingEntryCardView.java revision cc5ec22992ee61d130cb2ee99a038fb1761b8d35
12d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos/*
22d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Copyright (C) 2014 The Android Open Source Project
32d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos *
42d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Licensed under the Apache License, Version 2.0 (the "License");
52d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * you may not use this file except in compliance with the License.
62d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * You may obtain a copy of the License at
72d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos *
82d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos *      http://www.apache.org/licenses/LICENSE-2.0
92d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos *
102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Unless required by applicable law or agreed to in writing, software
112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * distributed under the License is distributed on an "AS IS" BASIS,
122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * See the License for the specific language governing permissions and
142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * limitations under the License.
152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */
162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulospackage com.android.contacts.quickcontact;
172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
18c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulosimport android.animation.ObjectAnimator;
192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Context;
202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Intent;
212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.res.Resources;
227b0b0ce616c6c2fa149918c112128388712f5657Paul Soulosimport android.graphics.ColorFilter;
23dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.graphics.Rect;
242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.graphics.drawable.Drawable;
25ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulosimport android.support.v7.widget.CardView;
262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.text.TextUtils;
270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeBounds;
280cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeScroll;
290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Fade;
300cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition;
310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition.TransitionListener;
320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionManager;
330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionSet;
342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.AttributeSet;
352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.Log;
362a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo;
372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.LayoutInflater;
38dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.view.TouchDelegate;
392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.View;
402a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.View.OnCreateContextMenuListener;
412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.ViewGroup;
42ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulosimport android.widget.FrameLayout;
432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.ImageView;
442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.LinearLayout;
454b943553afdb7286b33e4bc2481431e816c57967Paul Soulosimport android.widget.RelativeLayout;
462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.TextView;
472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
480cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport com.android.contacts.R;
490cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList;
512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.List;
522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos/**
542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Display entries in a LinearLayout that can be expanded to show all entries.
552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */
56ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulospublic class ExpandingEntryCardView extends CardView {
572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private static final String TAG = "ExpandingEntryCardView";
590cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private static final int DURATION_EXPAND_ANIMATION_FADE_IN = 200;
600cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private static final int DELAY_EXPAND_ANIMATION_FADE_IN = 100;
610cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
620cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    public static final int DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS = 300;
630cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    public static final int DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS = 300;
642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Entry data.
672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public static final class Entry {
692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
702ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final int mId;
712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mIcon;
722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mHeader;
732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mSubHeader;
742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mSubHeaderIcon;
752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mText;
762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mTextIcon;
772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Intent mIntent;
78dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Drawable mAlternateIcon;
79dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Intent mAlternateIntent;
80dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final String mAlternateContentDescription;
8148ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        private final boolean mShouldApplyColor;
822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final boolean mIsEditable;
832a4207fb39330e840436215c896cde911489e111Paul Soulos        private final EntryContextMenuInfo mEntryContextMenuInfo;
842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
852ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Entry(int id, Drawable icon, String header, String subHeader, String text,
86dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                Intent intent, Drawable alternateIcon, Intent alternateIntent,
87dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                String alternateContentDescription, boolean shouldApplyColor,
882a4207fb39330e840436215c896cde911489e111Paul Soulos                boolean isEditable, EntryContextMenuInfo entryContextMenuInfo) {
892ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            this(id, icon, header, subHeader, null, text, null, intent, alternateIcon,
902a4207fb39330e840436215c896cde911489e111Paul Soulos                    alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
912a4207fb39330e840436215c896cde911489e111Paul Soulos                    entryContextMenuInfo);
922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
942ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Entry(int id, Drawable mainIcon, String header, String subHeader,
952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
96dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
972a4207fb39330e840436215c896cde911489e111Paul Soulos                boolean shouldApplyColor, boolean isEditable,
982a4207fb39330e840436215c896cde911489e111Paul Soulos                EntryContextMenuInfo entryContextMenuInfo) {
992ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
1002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIcon = mainIcon;
1012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mHeader = header;
1022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeader = subHeader;
1032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeaderIcon = subHeaderIcon;
1042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mText = text;
1052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mTextIcon = textIcon;
1062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIntent = intent;
107dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIcon = alternateIcon;
108dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIntent = alternateIntent;
109dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateContentDescription = alternateContentDescription;
11048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            mShouldApplyColor = shouldApplyColor;
1112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIsEditable = isEditable;
1122a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = entryContextMenuInfo;
1132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getIcon() {
1162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIcon;
1172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getHeader() {
1202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mHeader;
1212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getSubHeader() {
1242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeader;
1252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getSubHeaderIcon() {
1282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeaderIcon;
1292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public String getText() {
1322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mText;
1332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getTextIcon() {
1362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mTextIcon;
1372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Intent getIntent() {
1402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIntent;
1412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
143dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Drawable getAlternateIcon() {
144dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIcon;
145dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
146dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
147dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Intent getAlternateIntent() {
148dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIntent;
149dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
150dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
151dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        String getAlternateContentDescription() {
152dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateContentDescription;
153dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
154dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
15548ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        boolean shouldApplyColor() {
15648ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            return mShouldApplyColor;
15748ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        }
15848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos
1592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        boolean isEditable() {
1602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIsEditable;
1612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
162ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
1632ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        int getId() {
1642ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
165ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos        }
1662a4207fb39330e840436215c896cde911489e111Paul Soulos
1672a4207fb39330e840436215c896cde911489e111Paul Soulos        EntryContextMenuInfo getEntryContextMenuInfo() {
1682a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
1692a4207fb39330e840436215c896cde911489e111Paul Soulos        }
1702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
1712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
172e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    public interface ExpandingEntryCardViewListener {
173e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        void onCollapse(int heightDelta);
1740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        void onExpand(int heightDelta);
175e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    }
176e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell
1772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private View mExpandCollapseButton;
1782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mExpandCollapseTextView;
1792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mTitleTextView;
1802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence mExpandButtonText;
1812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence mCollapseButtonText;
1822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private OnClickListener mOnClickListener;
1832a4207fb39330e840436215c896cde911489e111Paul Soulos    private OnCreateContextMenuListener mOnCreateContextMenuListener;
1842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private boolean mIsExpanded = false;
185691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos    /**
186691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * The max number of entries to show in a collapsed card. If there are less entries passed in,
187691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * then they are all shown.
188691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     */
1892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mCollapsedEntriesCount;
190e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    private ExpandingEntryCardViewListener mListener;
19160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<Entry>> mEntries;
19260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private int mNumEntries = 0;
19360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private boolean mAllEntriesInflated = false;
19460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<View>> mEntryViews;
1952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private LinearLayout mEntriesViewGroup;
196c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private final ImageView mExpandCollapseArrow;
1972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mThemeColor;
1987b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    private ColorFilter mThemeColorFilter;
19989966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos    private boolean mIsAlwaysExpanded;
2000cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    /** The ViewGroup to run the expand/collapse animation on */
2010cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private ViewGroup mAnimationViewGroup;
2026b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private LinearLayout mBadgeContainer;
2036b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private final List<ImageView> mBadges;
204cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    /**
205cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * List to hold the separators. This saves us from reconstructing every expand/collapse and
206cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * provides a smoother animation.
207cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     */
208cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private List<View> mSeparators;
209ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos    private LinearLayout mContainer;
2102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private final OnClickListener mExpandCollapseButtonListener = new OnClickListener() {
2122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        @Override
2132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public void onClick(View v) {
2142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            if (mIsExpanded) {
2152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                collapse();
2162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            } else {
2172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expand();
2182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
2192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
2202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    };
2212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context) {
2230d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        this(context, null);
2242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context, AttributeSet attrs) {
2272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        super(context, attrs);
2282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater inflater = LayoutInflater.from(context);
2292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        View expandingEntryCardView = inflater.inflate(R.layout.expanding_entry_card_view, this);
2302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup = (LinearLayout)
2312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expandingEntryCardView.findViewById(R.id.content_area_linear_layout);
2322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView = (TextView) expandingEntryCardView.findViewById(R.id.title);
233ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        mContainer = (LinearLayout) expandingEntryCardView.findViewById(R.id.container);
2347b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
2357b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton = inflater.inflate(
2367b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                R.layout.quickcontact_expanding_entry_card_button, this, false);
2377b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseTextView = (TextView) mExpandCollapseButton.findViewById(R.id.text);
238c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        mExpandCollapseArrow = (ImageView) mExpandCollapseButton.findViewById(R.id.arrow);
2397b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton.setOnClickListener(mExpandCollapseButtonListener);
2406b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        mBadgeContainer = (LinearLayout) mExpandCollapseButton.findViewById(R.id.badge_container);
2417b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
2426b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        mBadges = new ArrayList<ImageView>();
2432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
2462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the Entry list to display.
2472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
2482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param entries The Entry list to display.
2492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
25060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries,
25189966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos            boolean isExpanded, boolean isAlwaysExpanded,
2520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            ExpandingEntryCardViewListener listener, ViewGroup animationViewGroup) {
2532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
2542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = isExpanded;
25589966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsAlwaysExpanded = isAlwaysExpanded;
25689966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        // If isAlwaysExpanded is true, mIsExpanded should be true
25789966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsExpanded |= mIsAlwaysExpanded;
25860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mEntryViews = new ArrayList<List<View>>(entries.size());
2590d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        mEntries = entries;
2606095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNumEntries = 0;
2616095369885edcca566a812b551886e29c7ff8039Brian Attwell        mAllEntriesInflated = false;
26260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (List<Entry> entryList : mEntries) {
26360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mNumEntries += entryList.size();
26460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mEntryViews.add(new ArrayList<View>());
26560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
26660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries);
267cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        // We need a separator between each list, but not after the last one
268cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        if (entries.size() > 1) {
269cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            mSeparators = new ArrayList<>(entries.size() - 1);
270cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        }
271e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        mListener = listener;
2720cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        mAnimationViewGroup = animationViewGroup;
2730d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell
2747b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mIsExpanded) {
275c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getCollapseButtonText(), /* duration = */ 0);
27660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
2777b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        } else {
278c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getExpandButtonText(), /* duration = */ 0);
27960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateInitialEntries(layoutInflater);
2802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
2812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
2827b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
2832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
2862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the text for the expand button.
2872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
2882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param expandButtonText The expand button text.
2892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
2902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setExpandButtonText(CharSequence expandButtonText) {
2912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mExpandButtonText = expandButtonText;
2922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mExpandCollapseTextView != null && !mIsExpanded) {
2932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mExpandCollapseTextView.setText(expandButtonText);
2942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
2952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
2982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the text for the expand button.
2992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
3002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param expandButtonText The expand button text.
3012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
3022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setCollapseButtonText(CharSequence expandButtonText) {
3032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCollapseButtonText = expandButtonText;
3042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mExpandCollapseTextView != null && mIsExpanded) {
3052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mExpandCollapseTextView.setText(mCollapseButtonText);
3062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    @Override
3102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setOnClickListener(OnClickListener listener) {
3112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mOnClickListener = listener;
3122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3142a4207fb39330e840436215c896cde911489e111Paul Soulos    @Override
3152a4207fb39330e840436215c896cde911489e111Paul Soulos    public void setOnCreateContextMenuListener (OnCreateContextMenuListener listener) {
3162a4207fb39330e840436215c896cde911489e111Paul Soulos        mOnCreateContextMenuListener = listener;
3172a4207fb39330e840436215c896cde911489e111Paul Soulos    }
3182a4207fb39330e840436215c896cde911489e111Paul Soulos
3192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void insertEntriesIntoViewGroup() {
3202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup.removeAllViews();
32160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
3222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mIsExpanded) {
323cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            for (int i = 0; i < mEntryViews.size(); i++) {
324cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                List<View> viewList = mEntryViews.get(i);
325cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                if (i > 0) {
326cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
327cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
328cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(viewList.get(0));
329cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
330cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
331cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
332cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
333cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mEntriesViewGroup.addView(separator);
33497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
33560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (View view : viewList) {
33660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                    addEntry(view);
33760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                }
33860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
33960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
340691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // We want to insert mCollapsedEntriesCount entries into the group. extraEntries is the
341691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // number of entries that need to be added that are not the head element of a list
342691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // to reach mCollapsedEntriesCount.
343691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInViewGroup = 0;
344691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntryViews.size();
345691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntryViews.size() && numInViewGroup < mCollapsedEntriesCount;
346691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    i++) {
347691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
34897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (i > 0) {
349cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
350cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
351cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(entryViewList.get(0));
352cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
353cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
354cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
355cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
356cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mEntriesViewGroup.addView(separator);
357691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
358691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                addEntry(entryViewList.get(0));
359691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInViewGroup++;
360691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Insert entries in this list to hit mCollapsedEntriesCount.
361691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                for (int j = 1;
362691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        j < entryViewList.size() && numInViewGroup < mCollapsedEntriesCount &&
363691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        extraEntries > 0;
364691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        j++) {
365691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    addEntry(entryViewList.get(j));
366691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInViewGroup++;
367691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
36897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
3692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
3702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        removeView(mExpandCollapseButton);
37360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mCollapsedEntriesCount < mNumEntries
37489966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos                && mExpandCollapseButton.getParent() == null && !mIsAlwaysExpanded) {
375ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            mContainer.addView(mExpandCollapseButton, -1);
3762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void addEntry(View entry) {
3801321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If no title and the first entry in the group, add extra padding
3811321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (TextUtils.isEmpty(mTitleTextView.getText()) &&
3821321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                mEntriesViewGroup.getChildCount() == 0) {
3831321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            entry.setPadding(entry.getPaddingLeft(),
384568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
385568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
386568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
3871321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_null_title_top_extra_padding),
3881321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    entry.getPaddingRight(),
3891321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    entry.getPaddingBottom());
3901321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
3912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup.addView(entry);
3922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
394cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private View generateSeparator(View entry) {
3950cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        View separator = new View(getContext());
396ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        Resources res = getResources();
397ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
398ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        separator.setBackgroundColor(res.getColor(
3990cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                R.color.expanding_entry_card_item_separator_color));
400ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
401ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                ViewGroup.LayoutParams.MATCH_PARENT,
402ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_separator_height));
4030cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // The separator is aligned with the text in the entry. This is offset by a default
4040cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // margin. If there is an icon present, the icon's width and margin are added
405ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        int marginStart = res.getDimensionPixelSize(
4060cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                R.dimen.expanding_entry_card_item_padding_start);
4070cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ImageView entryIcon = (ImageView) entry.findViewById(R.id.icon);
40897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        if (entryIcon.getVisibility() == View.VISIBLE) {
4090cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            int imageWidthAndMargin =
410ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_icon_width) +
411ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_image_spacing);
4120cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            marginStart += imageWidthAndMargin;
4130cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        }
41497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        layoutParams.setMarginStart(marginStart);
4150cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        separator.setLayoutParams(layoutParams);
416cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        return separator;
4170cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    }
4180cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
4192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getExpandButtonText() {
4202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (!TextUtils.isEmpty(mExpandButtonText)) {
4212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mExpandButtonText;
4222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
4232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            // Default to "See more".
4242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return getResources().getText(R.string.expanding_entry_card_view_see_more);
4252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getCollapseButtonText() {
4292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (!TextUtils.isEmpty(mCollapseButtonText)) {
4302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mCollapseButtonText;
4312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
4322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            // Default to "See less".
4332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return getResources().getText(R.string.expanding_entry_card_view_see_less);
4342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4370d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell    /**
43860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates the initial entries to be shown.
4390d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell     */
44060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateInitialEntries(LayoutInflater layoutInflater) {
44160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        // If the number of collapsed entries equals total entries, inflate all
44260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mCollapsedEntriesCount == mNumEntries) {
44360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
44460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
44560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            // Otherwise inflate the top entry from each list
446691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // extraEntries is used to add extra entries until mCollapsedEntriesCount is reached.
447691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInflated = 0;
448691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntries.size();
449691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntries.size() && numInflated < mCollapsedEntriesCount; i++) {
450691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<Entry> entryList = mEntries.get(i);
451691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
452691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos
453691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                entryViewList.add(createEntryView(layoutInflater, entryList.get(0),
45497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                        /* showIcon = */ View.VISIBLE));
455691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInflated++;
456691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Inflate entries in this list to hit mCollapsedEntriesCount.
457691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                for (int j = 1; j < entryList.size() && numInflated < mCollapsedEntriesCount &&
458691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        extraEntries > 0; j++) {
459691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    entryViewList.add(createEntryView(layoutInflater, entryList.get(j),
46043e0dead719568ed610f9f111f6e7614368445efPaul Soulos                            /* showIcon = */ View.INVISIBLE));
461691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInflated++;
462691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
463691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
46460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
46560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
46660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    }
46760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
46860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    /**
46960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates all entries.
47060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     */
47160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateAllEntries(LayoutInflater layoutInflater) {
47260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mAllEntriesInflated) {
47360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            return;
47460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
47560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (int i = 0; i < mEntries.size(); i++) {
47660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<Entry> entryList = mEntries.get(i);
47760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<View> viewList = mEntryViews.get(i);
47860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            for (int j = viewList.size(); j < entryList.size(); j++) {
47997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final int iconVisibility;
48097ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final Entry entry = entryList.get(j);
48197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // If the entry does not have an icon, mark gone. Else if it has an icon, show
48297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // for the first Entry in the list only
48397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (entry.getIcon() == null) {
48497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.GONE;
48597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else if (j == 0) {
48697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.VISIBLE;
48797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else {
48897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.INVISIBLE;
48997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
49097ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                viewList.add(createEntryView(layoutInflater, entry, iconVisibility));
49160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
4922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
49360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mAllEntriesInflated = true;
4942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4967b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void setColorAndFilter(int color, ColorFilter colorFilter) {
4977b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColor = color;
4987b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColorFilter = colorFilter;
4997b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
5007b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
5017b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5026095369885edcca566a812b551886e29c7ff8039Brian Attwell    public void setEntryHeaderColor(int color) {
5036095369885edcca566a812b551886e29c7ff8039Brian Attwell        if (mEntries != null) {
5046095369885edcca566a812b551886e29c7ff8039Brian Attwell            for (List<View> entryList : mEntryViews) {
5056095369885edcca566a812b551886e29c7ff8039Brian Attwell                for (View entryView : entryList) {
5066095369885edcca566a812b551886e29c7ff8039Brian Attwell                    TextView header = (TextView) entryView.findViewById(R.id.header);
5076095369885edcca566a812b551886e29c7ff8039Brian Attwell                    if (header != null) {
5086095369885edcca566a812b551886e29c7ff8039Brian Attwell                        header.setTextColor(color);
5096095369885edcca566a812b551886e29c7ff8039Brian Attwell                    }
5106095369885edcca566a812b551886e29c7ff8039Brian Attwell                }
5116095369885edcca566a812b551886e29c7ff8039Brian Attwell            }
5126095369885edcca566a812b551886e29c7ff8039Brian Attwell        }
5136095369885edcca566a812b551886e29c7ff8039Brian Attwell    }
5146095369885edcca566a812b551886e29c7ff8039Brian Attwell
5157b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    /**
5167b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * The ColorFilter is passed in along with the color so that a new one only needs to be created
5177b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * once for the entire activity.
5187b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 1. Title
5197b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 2. Entry icons
5207b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 3. Expand/Collapse Text
5217b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 4. Expand/Collapse Button
5227b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     */
5237b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void applyColor() {
5247b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mThemeColor != 0 && mThemeColorFilter != null) {
5257b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Title
5267b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mTitleTextView != null) {
5277b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                mTitleTextView.setTextColor(mThemeColor);
5287b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
5297b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5307b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Entry icons
5317b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mEntries != null) {
53260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (List<Entry> entryList : mEntries) {
53360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                    for (Entry entry : entryList) {
53448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                        if (entry.shouldApplyColor()) {
53548ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            Drawable icon = entry.getIcon();
53648ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            if (icon != null) {
53748ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                                icon.setColorFilter(mThemeColorFilter);
53848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            }
53960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                        }
540dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        Drawable alternateIcon = entry.getAlternateIcon();
541dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        if (alternateIcon != null) {
542dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                            alternateIcon.setColorFilter(mThemeColorFilter);
543dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        }
544eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    }
5457b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                }
5467b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
5477b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5487b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Expand/Collapse
5497b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            mExpandCollapseTextView.setTextColor(mThemeColor);
550c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            mExpandCollapseArrow.setColorFilter(mThemeColorFilter);
5517b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        }
5527b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
5537b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5542a4207fb39330e840436215c896cde911489e111Paul Soulos    private View createEntryView(LayoutInflater layoutInflater, final Entry entry,
5552a4207fb39330e840436215c896cde911489e111Paul Soulos            int iconVisibility) {
5562a4207fb39330e840436215c896cde911489e111Paul Soulos        final EntryView view = (EntryView) layoutInflater.inflate(
5572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                R.layout.expanding_entry_card_item, this, false);
5582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
5592a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setContextMenuInfo(entry.getEntryContextMenuInfo());
560ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
561dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView icon = (ImageView) view.findViewById(R.id.icon);
56297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        icon.setVisibility(iconVisibility);
563eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (entry.getIcon() != null) {
564eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            icon.setImageDrawable(entry.getIcon());
565eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
566dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView header = (TextView) view.findViewById(R.id.header);
56703ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getHeader())) {
5682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setText(entry.getHeader());
5692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
5702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setVisibility(View.GONE);
5712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
5722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
573dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView subHeader = (TextView) view.findViewById(R.id.sub_header);
57403ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getSubHeader())) {
5752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setText(entry.getSubHeader());
5762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
5772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setVisibility(View.GONE);
5782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
5792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
580dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header);
5812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getSubHeaderIcon() != null) {
5822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setImageDrawable(entry.getSubHeaderIcon());
5832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
5842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setVisibility(View.GONE);
5852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
5862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
587dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView text = (TextView) view.findViewById(R.id.text);
58803ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getText())) {
5892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setText(entry.getText());
5902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
5912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setVisibility(View.GONE);
5922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
5932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
594dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text);
5952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getTextIcon() != null) {
5962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setImageDrawable(entry.getTextIcon());
5972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
5982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setVisibility(View.GONE);
5992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
6012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getIntent() != null) {
6027d22b94ce50f7a65dd89d4533f2aa3a3392e7972Paul Soulos            view.setOnClickListener(mOnClickListener);
6032ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            view.setTag(new EntryTag(entry.getId(), entry.getIntent()));
6042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
606a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        if (entry.getIntent() == null && entry.getEntryContextMenuInfo() == null) {
607a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            // Remove the click effect
608a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            view.setBackground(null);
609a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        }
610a42ef76251778161d27bc07db214b8c81720e476Paul Soulos
611ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // If only the header is visible, add a top margin to match icon's top margin.
612ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // Also increase the space below the header for visual comfort.
6134b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        if (header.getVisibility() == View.VISIBLE && subHeader.getVisibility() == View.GONE &&
6144b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                text.getVisibility() == View.GONE) {
6154b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            RelativeLayout.LayoutParams headerLayoutParams =
6164b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                    (RelativeLayout.LayoutParams) header.getLayoutParams();
6174b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            headerLayoutParams.topMargin = (int) (getResources().getDimension(
618ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_top));
619ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            headerLayoutParams.bottomMargin += (int) (getResources().getDimension(
620ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_bottom));
6214b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            header.setLayoutParams(headerLayoutParams);
6224b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        }
6234b943553afdb7286b33e4bc2481431e816c57967Paul Soulos
624dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate);
625dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
626dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            alternateIcon.setImageDrawable(entry.getAlternateIcon());
627dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            alternateIcon.setOnClickListener(mOnClickListener);
6282ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent()));
629dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            alternateIcon.setVisibility(View.VISIBLE);
630dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            alternateIcon.setContentDescription(entry.getAlternateContentDescription());
631dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
632891bd2bad8de331a089466777cd054674261a969Paul Soulos            // Expand the clickable area for alternate icon to be top to bottom and to end edge
633dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            // of the entry view
634dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            view.post(new Runnable() {
635dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                @Override
636dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                public void run() {
637dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    final Rect alternateIconRect = new Rect();
638dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    alternateIcon.getHitRect(alternateIconRect);
639891bd2bad8de331a089466777cd054674261a969Paul Soulos
640891bd2bad8de331a089466777cd054674261a969Paul Soulos                    alternateIconRect.bottom = view.getHeight();
641891bd2bad8de331a089466777cd054674261a969Paul Soulos                    alternateIconRect.top = 0;
642714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos                    if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
643891bd2bad8de331a089466777cd054674261a969Paul Soulos                        alternateIconRect.left = 0;
644714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos                    } else {
645891bd2bad8de331a089466777cd054674261a969Paul Soulos                        alternateIconRect.right = view.getWidth();
646714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos                    }
647dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    final TouchDelegate touchDelegate =
648dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                            new TouchDelegate(alternateIconRect, alternateIcon);
649dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    view.setTouchDelegate(touchDelegate);
650dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                }
651dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            });
652dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
653dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
654edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // Adjust the top padding size for entries with an invisible icon. The padding depends on
655edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // if there is a sub header or text section
656edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        if (iconVisibility == View.INVISIBLE &&
657edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                (!TextUtils.isEmpty(entry.getSubHeader()) || !TextUtils.isEmpty(entry.getText()))) {
658edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos            view.setPaddingRelative(view.getPaddingStart(),
659edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    getResources().getDimensionPixelSize(
660edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                            R.dimen.expanding_entry_card_item_no_icon_margin_top),
661edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingEnd(),
662edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingBottom());
663edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        } else if (iconVisibility == View.INVISIBLE &&  TextUtils.isEmpty(entry.getSubHeader())
664edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                && TextUtils.isEmpty(entry.getText())) {
665ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            view.setPaddingRelative(view.getPaddingStart(), 0, view.getPaddingEnd(),
666ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    view.getPaddingBottom());
667ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        }
668ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
6692a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
6702a4207fb39330e840436215c896cde911489e111Paul Soulos
6712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return view;
6722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
6732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
674c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private void updateExpandCollapseButton(CharSequence buttonText, long duration) {
675c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        if (mIsExpanded) {
676c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
677c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 180);
678c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
679c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
6802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
681c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
682c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 0);
683c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
684c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
6852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
686c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateBadges();
687c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos
6882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mExpandCollapseTextView.setText(buttonText);
6892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
6902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
6916b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private void updateBadges() {
6926b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        if (mIsExpanded) {
6936b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            mBadgeContainer.removeAllViews();
6946b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        } else {
6956b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            // Inflate badges if not yet created
6966b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            if (mBadges.size() < mEntries.size() - mCollapsedEntriesCount) {
6976b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                for (int i = mCollapsedEntriesCount; i < mEntries.size(); i++) {
6986b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    Drawable badgeDrawable = mEntries.get(i).get(0).getIcon();
6996b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    if (badgeDrawable != null) {
7006b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        ImageView badgeView = new ImageView(getContext());
7016b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        LinearLayout.LayoutParams badgeViewParams = new LinearLayout.LayoutParams(
7026b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                (int) getResources().getDimension(
7036b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                        R.dimen.expanding_entry_card_item_icon_width),
7046b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                (int) getResources().getDimension(
7056b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                        R.dimen.expanding_entry_card_item_icon_height));
7066b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeViewParams.setMarginEnd((int) getResources().getDimension(
7076b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                R.dimen.expanding_entry_card_badge_separator_margin));
7086b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeView.setLayoutParams(badgeViewParams);
7096b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeView.setImageDrawable(badgeDrawable);
7106b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        mBadges.add(badgeView);
7116b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    }
7126b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                }
7136b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            }
7146b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            mBadgeContainer.removeAllViews();
7156b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            for (ImageView badge : mBadges) {
7166b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                mBadgeContainer.addView(badge);
7176b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            }
7186b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        }
7196b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    }
7206b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos
7212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void expand() {
7220cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ChangeBounds boundsTransition = new ChangeBounds();
7230cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.setDuration(DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
7240cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7250cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        Fade fadeIn = new Fade(Fade.IN);
7260cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setDuration(DURATION_EXPAND_ANIMATION_FADE_IN);
7270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setStartDelay(DELAY_EXPAND_ANIMATION_FADE_IN);
7280cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionSet transitionSet = new TransitionSet();
7300cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(boundsTransition);
7310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(fadeIn);
7320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
7340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                this : mAnimationViewGroup;
7350cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addListener(new TransitionListener() {
7370cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionStart(Transition transition) {
7390cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                // The listener is used to turn off suppressing, the proper delta is not necessary
7400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                mListener.onExpand(0);
7410cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7420cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7430cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7440cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionEnd(Transition transition) {
7450cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7460cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7470cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7480cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionCancel(Transition transition) {
7490cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7500cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionPause(Transition transition) {
7530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7540cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7550cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7560cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionResume(Transition transition) {
7570cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7580cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        });
7590cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7600cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet);
7612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = true;
7630d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        // In order to insert new entries, we may need to inflate them for the first time
76460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        inflateAllEntries(LayoutInflater.from(getContext()));
7652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
766c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateExpandCollapseButton(getCollapseButtonText(),
767c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
7682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
7692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void collapse() {
7710cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final int startingHeight = mEntriesViewGroup.getMeasuredHeight();
7722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = false;
773c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateExpandCollapseButton(getExpandButtonText(),
774c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
7752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ChangeBounds boundsTransition = new ChangeBounds();
7770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
7782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7790cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ChangeScroll scrollTransition = new ChangeScroll();
7800cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        scrollTransition.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
7810cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7820cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionSet transitionSet = new TransitionSet();
7830cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(boundsTransition);
7840cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(scrollTransition);
7850cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7860cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
7870cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                this : mAnimationViewGroup;
7880cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7890cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.addListener(new TransitionListener() {
7902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            @Override
7910cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionStart(Transition transition) {
7920cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                /*
7930cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 * onTransitionStart is called after the view hierarchy has been changed but before
7940cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 * the animation begins.
7950cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 */
7960cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                int finishingHeight = mEntriesViewGroup.getMeasuredHeight();
7970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                mListener.onCollapse(startingHeight - finishingHeight);
7982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
7990cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8000cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8010cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionEnd(Transition transition) {
8020cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8030cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            @Override
8050cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionCancel(Transition transition) {
8060cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8070cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8080cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8090cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionPause(Transition transition) {
8100cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8110cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8120cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8130cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionResume(Transition transition) {
8142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
8152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        });
8160cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8170cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet);
8180cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8190cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        insertEntriesIntoViewGroup();
8202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Returns whether the view is currently in its expanded state.
8242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public boolean isExpanded() {
8262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return mIsExpanded;
8272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the title text of this ExpandingEntryCardView.
8312fa690807a94708384789b211965bfc75b5ac38ePaul Soulos     * @param title The title to set. A null title will result in the title being removed.
8322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setTitle(String title) {
8342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mTitleTextView == null) {
8352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            Log.e(TAG, "mTitleTextView is null");
8362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
8372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView.setText(title);
8381321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        mTitleTextView.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
8391321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        findViewById(R.id.title_separator).setVisibility(TextUtils.isEmpty(title) ?
8401321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                View.GONE : View.VISIBLE);
8411321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If the title is set after children have been added, reset the top entry's padding to
8421321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the default. Else if the title is cleared after children have been added, set
8431321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the extra top padding
8441321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
8451321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
8461321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
8471321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
8481321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top),
8491321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
8501321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingBottom());
8511321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        } else if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
8521321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
8531321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
8541321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
8551321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
8561321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            getResources().getDimensionPixelSize(
8571321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                                    R.dimen.expanding_entry_card_null_title_top_extra_padding),
8581321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
8591321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingBottom());
8601321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
8612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
862eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
863eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    public boolean shouldShow() {
864eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        return mEntries != null && mEntries.size() > 0;
865eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
8662a4207fb39330e840436215c896cde911489e111Paul Soulos
8672a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryView extends RelativeLayout {
8682a4207fb39330e840436215c896cde911489e111Paul Soulos        private EntryContextMenuInfo mEntryContextMenuInfo;
8692a4207fb39330e840436215c896cde911489e111Paul Soulos
8702a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context) {
8712a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context);
8722a4207fb39330e840436215c896cde911489e111Paul Soulos        }
8732a4207fb39330e840436215c896cde911489e111Paul Soulos
8742a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context, AttributeSet attrs) {
8752a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context, attrs);
8762a4207fb39330e840436215c896cde911489e111Paul Soulos        }
8772a4207fb39330e840436215c896cde911489e111Paul Soulos
8782a4207fb39330e840436215c896cde911489e111Paul Soulos        public void setContextMenuInfo(EntryContextMenuInfo info) {
8792a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = info;
8802a4207fb39330e840436215c896cde911489e111Paul Soulos        }
8812a4207fb39330e840436215c896cde911489e111Paul Soulos
8822a4207fb39330e840436215c896cde911489e111Paul Soulos        @Override
8832a4207fb39330e840436215c896cde911489e111Paul Soulos        protected ContextMenuInfo getContextMenuInfo() {
8842a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
8852a4207fb39330e840436215c896cde911489e111Paul Soulos        }
8862a4207fb39330e840436215c896cde911489e111Paul Soulos    }
8872a4207fb39330e840436215c896cde911489e111Paul Soulos
8882a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryContextMenuInfo implements ContextMenuInfo {
8892a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyText;
8902a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyLabel;
8912a4207fb39330e840436215c896cde911489e111Paul Soulos
8922a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryContextMenuInfo(String copyText, String copyLabel) {
8932a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyText = copyText;
8942a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyLabel = copyLabel;
8952a4207fb39330e840436215c896cde911489e111Paul Soulos        }
8962a4207fb39330e840436215c896cde911489e111Paul Soulos
8972a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyText() {
8982a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyText;
8992a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9002a4207fb39330e840436215c896cde911489e111Paul Soulos
9012a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyLabel() {
9022a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyLabel;
9032a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9042a4207fb39330e840436215c896cde911489e111Paul Soulos    }
9052ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9062ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    static final class EntryTag {
9072ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final int mId;
9082ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final Intent mIntent;
9092ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9102ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public EntryTag(int id, Intent intent) {
9112ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
9122ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mIntent = intent;
9132ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9142ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9152ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public int getId() {
9162ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
9172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9192ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Intent getIntent() {
9202ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mIntent;
9212ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9222ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    }
9232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos}
924