ExpandingEntryCardView.java revision 7ce5352a70e8aaf120bf4f7bd05d595f46abb080
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;
267ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jangimport android.text.Spannable;
272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.text.TextUtils;
280cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeBounds;
290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeScroll;
300cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Fade;
310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition;
320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition.TransitionListener;
330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionManager;
340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionSet;
352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.AttributeSet;
362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.Log;
372a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo;
382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.LayoutInflater;
3948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.MotionEvent;
402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.View;
4148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.ViewConfiguration;
422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.ViewGroup;
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;
777ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang        private Spannable mPrimaryContentDescription;
782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Intent mIntent;
79dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Drawable mAlternateIcon;
80dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Intent mAlternateIntent;
81dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final String mAlternateContentDescription;
8248ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        private final boolean mShouldApplyColor;
832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final boolean mIsEditable;
842a4207fb39330e840436215c896cde911489e111Paul Soulos        private final EntryContextMenuInfo mEntryContextMenuInfo;
8548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final Drawable mThirdIcon;
8648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final Intent mThirdIntent;
8748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final String mThirdContentDescription;
8848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        private final int mIconResourceId;
892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
902ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Entry(int id, Drawable mainIcon, String header, String subHeader,
9123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                Drawable subHeaderIcon, String text, Drawable textIcon,
927ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang                Spannable primaryContentDescription, Intent intent,
93dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
942a4207fb39330e840436215c896cde911489e111Paul Soulos                boolean shouldApplyColor, boolean isEditable,
9548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
9648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                String thirdContentDescription, int iconResourceId) {
972ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIcon = mainIcon;
992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mHeader = header;
1002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeader = subHeader;
1012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeaderIcon = subHeaderIcon;
1022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mText = text;
1032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mTextIcon = textIcon;
10423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            mPrimaryContentDescription = primaryContentDescription;
1052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIntent = intent;
106dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIcon = alternateIcon;
107dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIntent = alternateIntent;
108dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateContentDescription = alternateContentDescription;
10948ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            mShouldApplyColor = shouldApplyColor;
1102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIsEditable = isEditable;
1112a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = entryContextMenuInfo;
11248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIcon = thirdIcon;
11348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIntent = thirdIntent;
11448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdContentDescription = thirdContentDescription;
11548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos            mIconResourceId = iconResourceId;
1162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getIcon() {
1192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIcon;
1202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getHeader() {
1232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mHeader;
1242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getSubHeader() {
1272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeader;
1282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getSubHeaderIcon() {
1312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeaderIcon;
1322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public String getText() {
1352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mText;
1362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getTextIcon() {
1392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mTextIcon;
1402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1427ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang        Spannable getPrimaryContentDescription() {
14323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            return mPrimaryContentDescription;
14423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
14523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos
1462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Intent getIntent() {
1472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIntent;
1482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
150dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Drawable getAlternateIcon() {
151dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIcon;
152dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
153dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
154dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Intent getAlternateIntent() {
155dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIntent;
156dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
157dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
158dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        String getAlternateContentDescription() {
159dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateContentDescription;
160dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
161dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
16248ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        boolean shouldApplyColor() {
16348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            return mShouldApplyColor;
16448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        }
16548ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos
1662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        boolean isEditable() {
1672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIsEditable;
1682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
169ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
1702ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        int getId() {
1712ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
172ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos        }
1732a4207fb39330e840436215c896cde911489e111Paul Soulos
1742a4207fb39330e840436215c896cde911489e111Paul Soulos        EntryContextMenuInfo getEntryContextMenuInfo() {
1752a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
1762a4207fb39330e840436215c896cde911489e111Paul Soulos        }
17748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
17848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Drawable getThirdIcon() {
17948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdIcon;
18048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
18148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
18248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Intent getThirdIntent() {
18348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdIntent;
18448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
18548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
18648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        String getThirdContentDescription() {
18748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdContentDescription;
18848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
18948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos
19048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        int getIconResourceId() {
19148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos            return mIconResourceId;
19248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        }
1932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
1942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
195e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    public interface ExpandingEntryCardViewListener {
196e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        void onCollapse(int heightDelta);
1970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        void onExpand(int heightDelta);
198e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    }
199e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell
2002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private View mExpandCollapseButton;
2012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mExpandCollapseTextView;
2022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mTitleTextView;
2032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence mExpandButtonText;
2042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence mCollapseButtonText;
2052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private OnClickListener mOnClickListener;
2062a4207fb39330e840436215c896cde911489e111Paul Soulos    private OnCreateContextMenuListener mOnCreateContextMenuListener;
2072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private boolean mIsExpanded = false;
208691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos    /**
209691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * The max number of entries to show in a collapsed card. If there are less entries passed in,
210691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * then they are all shown.
211691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     */
2122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mCollapsedEntriesCount;
213e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    private ExpandingEntryCardViewListener mListener;
21460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<Entry>> mEntries;
21560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private int mNumEntries = 0;
21660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private boolean mAllEntriesInflated = false;
21760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<View>> mEntryViews;
2182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private LinearLayout mEntriesViewGroup;
219c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private final ImageView mExpandCollapseArrow;
2202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mThemeColor;
2217b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    private ColorFilter mThemeColorFilter;
22289966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos    private boolean mIsAlwaysExpanded;
2230cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    /** The ViewGroup to run the expand/collapse animation on */
2240cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private ViewGroup mAnimationViewGroup;
2256b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private LinearLayout mBadgeContainer;
2266b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private final List<ImageView> mBadges;
22748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos    private final List<Integer> mBadgeIds;
228cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    /**
229cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * List to hold the separators. This saves us from reconstructing every expand/collapse and
230cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * provides a smoother animation.
231cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     */
232cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private List<View> mSeparators;
233ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos    private LinearLayout mContainer;
2342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private final OnClickListener mExpandCollapseButtonListener = new OnClickListener() {
2362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        @Override
2372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public void onClick(View v) {
2382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            if (mIsExpanded) {
2392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                collapse();
2402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            } else {
2412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expand();
2422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
2432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
2442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    };
2452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context) {
2470d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        this(context, null);
2482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context, AttributeSet attrs) {
2512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        super(context, attrs);
2522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater inflater = LayoutInflater.from(context);
2532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        View expandingEntryCardView = inflater.inflate(R.layout.expanding_entry_card_view, this);
2542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup = (LinearLayout)
2552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expandingEntryCardView.findViewById(R.id.content_area_linear_layout);
2562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView = (TextView) expandingEntryCardView.findViewById(R.id.title);
257ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        mContainer = (LinearLayout) expandingEntryCardView.findViewById(R.id.container);
2587b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
2597b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton = inflater.inflate(
2607b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                R.layout.quickcontact_expanding_entry_card_button, this, false);
2617b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseTextView = (TextView) mExpandCollapseButton.findViewById(R.id.text);
262c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        mExpandCollapseArrow = (ImageView) mExpandCollapseButton.findViewById(R.id.arrow);
2637b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton.setOnClickListener(mExpandCollapseButtonListener);
2646b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        mBadgeContainer = (LinearLayout) mExpandCollapseButton.findViewById(R.id.badge_container);
2657b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
2666b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        mBadges = new ArrayList<ImageView>();
26748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        mBadgeIds = new ArrayList<Integer>();
2682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
2712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the Entry list to display.
2722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
2732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param entries The Entry list to display.
2742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
27560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries,
27689966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos            boolean isExpanded, boolean isAlwaysExpanded,
2770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            ExpandingEntryCardViewListener listener, ViewGroup animationViewGroup) {
2782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
2792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = isExpanded;
28089966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsAlwaysExpanded = isAlwaysExpanded;
28189966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        // If isAlwaysExpanded is true, mIsExpanded should be true
28289966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsExpanded |= mIsAlwaysExpanded;
28360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mEntryViews = new ArrayList<List<View>>(entries.size());
2840d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        mEntries = entries;
2856095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNumEntries = 0;
2866095369885edcca566a812b551886e29c7ff8039Brian Attwell        mAllEntriesInflated = false;
28760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (List<Entry> entryList : mEntries) {
28860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mNumEntries += entryList.size();
28960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mEntryViews.add(new ArrayList<View>());
29060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
29160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries);
292cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        // We need a separator between each list, but not after the last one
293cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        if (entries.size() > 1) {
294cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            mSeparators = new ArrayList<>(entries.size() - 1);
295cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        }
296e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        mListener = listener;
2970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        mAnimationViewGroup = animationViewGroup;
2980d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell
2997b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mIsExpanded) {
300c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getCollapseButtonText(), /* duration = */ 0);
30160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
3027b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        } else {
303c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getExpandButtonText(), /* duration = */ 0);
30460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateInitialEntries(layoutInflater);
3052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
3077b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
3082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
3112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the text for the expand button.
3122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
3132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param expandButtonText The expand button text.
3142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
3152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setExpandButtonText(CharSequence expandButtonText) {
3162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mExpandButtonText = expandButtonText;
3172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mExpandCollapseTextView != null && !mIsExpanded) {
3182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mExpandCollapseTextView.setText(expandButtonText);
3192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
3232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the text for the expand button.
3242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
3252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param expandButtonText The expand button text.
3262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
3272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setCollapseButtonText(CharSequence expandButtonText) {
3282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCollapseButtonText = expandButtonText;
3292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mExpandCollapseTextView != null && mIsExpanded) {
3302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mExpandCollapseTextView.setText(mCollapseButtonText);
3312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    @Override
3352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setOnClickListener(OnClickListener listener) {
3362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mOnClickListener = listener;
3372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3392a4207fb39330e840436215c896cde911489e111Paul Soulos    @Override
3402a4207fb39330e840436215c896cde911489e111Paul Soulos    public void setOnCreateContextMenuListener (OnCreateContextMenuListener listener) {
3412a4207fb39330e840436215c896cde911489e111Paul Soulos        mOnCreateContextMenuListener = listener;
3422a4207fb39330e840436215c896cde911489e111Paul Soulos    }
3432a4207fb39330e840436215c896cde911489e111Paul Soulos
3442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void insertEntriesIntoViewGroup() {
3452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup.removeAllViews();
34660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
3472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mIsExpanded) {
348cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            for (int i = 0; i < mEntryViews.size(); i++) {
349cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                List<View> viewList = mEntryViews.get(i);
350cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                if (i > 0) {
351cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
352cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
353cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(viewList.get(0));
354cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
355cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
356cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
357cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
358cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mEntriesViewGroup.addView(separator);
35997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
36060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (View view : viewList) {
36160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                    addEntry(view);
36260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                }
36360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
36460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
365691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // We want to insert mCollapsedEntriesCount entries into the group. extraEntries is the
366691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // number of entries that need to be added that are not the head element of a list
367691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // to reach mCollapsedEntriesCount.
368691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInViewGroup = 0;
369691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntryViews.size();
370691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntryViews.size() && numInViewGroup < mCollapsedEntriesCount;
371691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    i++) {
372691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
37397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (i > 0) {
374cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
375cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
376cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(entryViewList.get(0));
377cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
378cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
379cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
380cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
381cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mEntriesViewGroup.addView(separator);
382691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
383691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                addEntry(entryViewList.get(0));
384691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInViewGroup++;
385691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Insert entries in this list to hit mCollapsedEntriesCount.
386691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                for (int j = 1;
387691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        j < entryViewList.size() && numInViewGroup < mCollapsedEntriesCount &&
388691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        extraEntries > 0;
389691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        j++) {
390691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    addEntry(entryViewList.get(j));
391691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInViewGroup++;
392691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
39397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
3942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
3952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        removeView(mExpandCollapseButton);
39860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mCollapsedEntriesCount < mNumEntries
39989966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos                && mExpandCollapseButton.getParent() == null && !mIsAlwaysExpanded) {
400ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            mContainer.addView(mExpandCollapseButton, -1);
4012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void addEntry(View entry) {
4051321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If no title and the first entry in the group, add extra padding
4061321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (TextUtils.isEmpty(mTitleTextView.getText()) &&
4071321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                mEntriesViewGroup.getChildCount() == 0) {
4081321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            entry.setPadding(entry.getPaddingLeft(),
409568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
410568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
411568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
4121321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_null_title_top_extra_padding),
4131321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    entry.getPaddingRight(),
4141321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    entry.getPaddingBottom());
4151321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
4162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup.addView(entry);
4172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
419cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private View generateSeparator(View entry) {
4200cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        View separator = new View(getContext());
421ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        Resources res = getResources();
422ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
423ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        separator.setBackgroundColor(res.getColor(
4240cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                R.color.expanding_entry_card_item_separator_color));
425ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
426ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                ViewGroup.LayoutParams.MATCH_PARENT,
427ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_separator_height));
4280cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // The separator is aligned with the text in the entry. This is offset by a default
4290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // margin. If there is an icon present, the icon's width and margin are added
430ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        int marginStart = res.getDimensionPixelSize(
4310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                R.dimen.expanding_entry_card_item_padding_start);
4320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ImageView entryIcon = (ImageView) entry.findViewById(R.id.icon);
43397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        if (entryIcon.getVisibility() == View.VISIBLE) {
4340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            int imageWidthAndMargin =
435ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_icon_width) +
436ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_image_spacing);
4370cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            marginStart += imageWidthAndMargin;
4380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        }
43997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        layoutParams.setMarginStart(marginStart);
4400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        separator.setLayoutParams(layoutParams);
441cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        return separator;
4420cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    }
4430cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
4442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getExpandButtonText() {
4452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (!TextUtils.isEmpty(mExpandButtonText)) {
4462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mExpandButtonText;
4472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
4482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            // Default to "See more".
4492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return getResources().getText(R.string.expanding_entry_card_view_see_more);
4502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getCollapseButtonText() {
4542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (!TextUtils.isEmpty(mCollapseButtonText)) {
4552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mCollapseButtonText;
4562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
4572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            // Default to "See less".
4582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return getResources().getText(R.string.expanding_entry_card_view_see_less);
4592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4620d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell    /**
46360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates the initial entries to be shown.
4640d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell     */
46560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateInitialEntries(LayoutInflater layoutInflater) {
46660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        // If the number of collapsed entries equals total entries, inflate all
46760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mCollapsedEntriesCount == mNumEntries) {
46860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
46960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
47060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            // Otherwise inflate the top entry from each list
471691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // extraEntries is used to add extra entries until mCollapsedEntriesCount is reached.
472691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInflated = 0;
473691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntries.size();
474691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntries.size() && numInflated < mCollapsedEntriesCount; i++) {
475691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<Entry> entryList = mEntries.get(i);
476691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
477691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos
478691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                entryViewList.add(createEntryView(layoutInflater, entryList.get(0),
47997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                        /* showIcon = */ View.VISIBLE));
480691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInflated++;
481691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Inflate entries in this list to hit mCollapsedEntriesCount.
482691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                for (int j = 1; j < entryList.size() && numInflated < mCollapsedEntriesCount &&
483691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                        extraEntries > 0; j++) {
484691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    entryViewList.add(createEntryView(layoutInflater, entryList.get(j),
48543e0dead719568ed610f9f111f6e7614368445efPaul Soulos                            /* showIcon = */ View.INVISIBLE));
486691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInflated++;
487691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
488691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
48960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
49060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
49160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    }
49260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
49360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    /**
49460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates all entries.
49560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     */
49660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateAllEntries(LayoutInflater layoutInflater) {
49760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mAllEntriesInflated) {
49860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            return;
49960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
50060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (int i = 0; i < mEntries.size(); i++) {
50160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<Entry> entryList = mEntries.get(i);
50260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<View> viewList = mEntryViews.get(i);
50360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            for (int j = viewList.size(); j < entryList.size(); j++) {
50497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final int iconVisibility;
50597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final Entry entry = entryList.get(j);
50697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // If the entry does not have an icon, mark gone. Else if it has an icon, show
50797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // for the first Entry in the list only
50897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (entry.getIcon() == null) {
50997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.GONE;
51097ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else if (j == 0) {
51197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.VISIBLE;
51297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else {
51397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.INVISIBLE;
51497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
51597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                viewList.add(createEntryView(layoutInflater, entry, iconVisibility));
51660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
5172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
51860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mAllEntriesInflated = true;
5192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
5202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
5217b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void setColorAndFilter(int color, ColorFilter colorFilter) {
5227b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColor = color;
5237b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColorFilter = colorFilter;
5247b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
5257b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
5267b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5276095369885edcca566a812b551886e29c7ff8039Brian Attwell    public void setEntryHeaderColor(int color) {
5286095369885edcca566a812b551886e29c7ff8039Brian Attwell        if (mEntries != null) {
5296095369885edcca566a812b551886e29c7ff8039Brian Attwell            for (List<View> entryList : mEntryViews) {
5306095369885edcca566a812b551886e29c7ff8039Brian Attwell                for (View entryView : entryList) {
5316095369885edcca566a812b551886e29c7ff8039Brian Attwell                    TextView header = (TextView) entryView.findViewById(R.id.header);
5326095369885edcca566a812b551886e29c7ff8039Brian Attwell                    if (header != null) {
5336095369885edcca566a812b551886e29c7ff8039Brian Attwell                        header.setTextColor(color);
5346095369885edcca566a812b551886e29c7ff8039Brian Attwell                    }
5356095369885edcca566a812b551886e29c7ff8039Brian Attwell                }
5366095369885edcca566a812b551886e29c7ff8039Brian Attwell            }
5376095369885edcca566a812b551886e29c7ff8039Brian Attwell        }
5386095369885edcca566a812b551886e29c7ff8039Brian Attwell    }
5396095369885edcca566a812b551886e29c7ff8039Brian Attwell
5407b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    /**
5417b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * The ColorFilter is passed in along with the color so that a new one only needs to be created
5427b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * once for the entire activity.
5437b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 1. Title
5447b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 2. Entry icons
5457b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 3. Expand/Collapse Text
5467b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 4. Expand/Collapse Button
5477b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     */
5487b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void applyColor() {
5497b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mThemeColor != 0 && mThemeColorFilter != null) {
5507b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Title
5517b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mTitleTextView != null) {
5527b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                mTitleTextView.setTextColor(mThemeColor);
5537b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
5547b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5557b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Entry icons
5567b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mEntries != null) {
55760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (List<Entry> entryList : mEntries) {
55860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                    for (Entry entry : entryList) {
55948ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                        if (entry.shouldApplyColor()) {
56048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            Drawable icon = entry.getIcon();
56148ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            if (icon != null) {
56248ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                                icon.setColorFilter(mThemeColorFilter);
56348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            }
56460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                        }
565dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        Drawable alternateIcon = entry.getAlternateIcon();
566dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        if (alternateIcon != null) {
567dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                            alternateIcon.setColorFilter(mThemeColorFilter);
568dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        }
56948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        Drawable thirdIcon = entry.getThirdIcon();
57048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        if (thirdIcon != null) {
57148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                            thirdIcon.setColorFilter(mThemeColorFilter);
57248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        }
573eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    }
5747b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                }
5757b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
5767b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5777b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Expand/Collapse
5787b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            mExpandCollapseTextView.setTextColor(mThemeColor);
579c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            mExpandCollapseArrow.setColorFilter(mThemeColorFilter);
5807b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        }
5817b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
5827b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5832a4207fb39330e840436215c896cde911489e111Paul Soulos    private View createEntryView(LayoutInflater layoutInflater, final Entry entry,
5842a4207fb39330e840436215c896cde911489e111Paul Soulos            int iconVisibility) {
5852a4207fb39330e840436215c896cde911489e111Paul Soulos        final EntryView view = (EntryView) layoutInflater.inflate(
5862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                R.layout.expanding_entry_card_item, this, false);
5872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
5882a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setContextMenuInfo(entry.getEntryContextMenuInfo());
58923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        if (!TextUtils.isEmpty(entry.getPrimaryContentDescription())) {
59023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            view.setContentDescription(entry.getPrimaryContentDescription());
59123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
592ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
593dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView icon = (ImageView) view.findViewById(R.id.icon);
59497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        icon.setVisibility(iconVisibility);
595eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (entry.getIcon() != null) {
596eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            icon.setImageDrawable(entry.getIcon());
597eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
598dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView header = (TextView) view.findViewById(R.id.header);
59903ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getHeader())) {
6002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setText(entry.getHeader());
6012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setVisibility(View.GONE);
6032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
605dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView subHeader = (TextView) view.findViewById(R.id.sub_header);
60603ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getSubHeader())) {
6072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setText(entry.getSubHeader());
6082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setVisibility(View.GONE);
6102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
612dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header);
6132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getSubHeaderIcon() != null) {
6142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setImageDrawable(entry.getSubHeaderIcon());
6152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setVisibility(View.GONE);
6172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
619dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView text = (TextView) view.findViewById(R.id.text);
62003ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getText())) {
6212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setText(entry.getText());
6222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setVisibility(View.GONE);
6242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
626dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text);
6272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getTextIcon() != null) {
6282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setImageDrawable(entry.getTextIcon());
6292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setVisibility(View.GONE);
6312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
6332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getIntent() != null) {
6347d22b94ce50f7a65dd89d4533f2aa3a3392e7972Paul Soulos            view.setOnClickListener(mOnClickListener);
6352ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            view.setTag(new EntryTag(entry.getId(), entry.getIntent()));
6362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
638a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        if (entry.getIntent() == null && entry.getEntryContextMenuInfo() == null) {
639a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            // Remove the click effect
640a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            view.setBackground(null);
641a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        }
642a42ef76251778161d27bc07db214b8c81720e476Paul Soulos
643ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // If only the header is visible, add a top margin to match icon's top margin.
644ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // Also increase the space below the header for visual comfort.
6454b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        if (header.getVisibility() == View.VISIBLE && subHeader.getVisibility() == View.GONE &&
6464b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                text.getVisibility() == View.GONE) {
6474b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            RelativeLayout.LayoutParams headerLayoutParams =
6484b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                    (RelativeLayout.LayoutParams) header.getLayoutParams();
6494b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            headerLayoutParams.topMargin = (int) (getResources().getDimension(
650ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_top));
651ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            headerLayoutParams.bottomMargin += (int) (getResources().getDimension(
652ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_bottom));
6534b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            header.setLayoutParams(headerLayoutParams);
6544b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        }
6554b943553afdb7286b33e4bc2481431e816c57967Paul Soulos
656edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // Adjust the top padding size for entries with an invisible icon. The padding depends on
657edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // if there is a sub header or text section
658edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        if (iconVisibility == View.INVISIBLE &&
659edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                (!TextUtils.isEmpty(entry.getSubHeader()) || !TextUtils.isEmpty(entry.getText()))) {
660edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos            view.setPaddingRelative(view.getPaddingStart(),
661edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    getResources().getDimensionPixelSize(
662edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                            R.dimen.expanding_entry_card_item_no_icon_margin_top),
663edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingEnd(),
664edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingBottom());
665edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        } else if (iconVisibility == View.INVISIBLE &&  TextUtils.isEmpty(entry.getSubHeader())
666edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                && TextUtils.isEmpty(entry.getText())) {
667ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            view.setPaddingRelative(view.getPaddingStart(), 0, view.getPaddingEnd(),
668ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    view.getPaddingBottom());
669ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        }
670ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
67148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate);
67248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        final ImageView thirdIcon = (ImageView) view.findViewById(R.id.third_icon);
67348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
67448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
67548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setImageDrawable(entry.getAlternateIcon());
67648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setOnClickListener(mOnClickListener);
67748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent()));
67848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setVisibility(View.VISIBLE);
67948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setContentDescription(entry.getAlternateContentDescription());
68048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
68148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
68248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        if (entry.getThirdIcon() != null && entry.getThirdIntent() != null) {
68348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setImageDrawable(entry.getThirdIcon());
68448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setOnClickListener(mOnClickListener);
68548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setTag(new EntryTag(entry.getId(), entry.getThirdIntent()));
68648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setVisibility(View.VISIBLE);
68748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setContentDescription(entry.getThirdContentDescription());
68848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
68948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
69048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        // Set a custom touch listener for expanding the extra icon touch areas
69148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        view.setOnTouchListener(new EntryTouchListener(view, alternateIcon, thirdIcon));
6922a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
6932a4207fb39330e840436215c896cde911489e111Paul Soulos
6942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return view;
6952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
6962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
697c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private void updateExpandCollapseButton(CharSequence buttonText, long duration) {
698c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        if (mIsExpanded) {
699c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
700c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 180);
701c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
702c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
7032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
704c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
705c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 0);
706c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
707c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
7082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
709c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateBadges();
710c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos
7112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mExpandCollapseTextView.setText(buttonText);
7122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
7132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7146b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    private void updateBadges() {
7156b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        if (mIsExpanded) {
7166b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            mBadgeContainer.removeAllViews();
7176b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        } else {
7186b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            // Inflate badges if not yet created
7196b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            if (mBadges.size() < mEntries.size() - mCollapsedEntriesCount) {
7206b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                for (int i = mCollapsedEntriesCount; i < mEntries.size(); i++) {
7216b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    Drawable badgeDrawable = mEntries.get(i).get(0).getIcon();
72248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    int badgeResourceId = mEntries.get(i).get(0).getIconResourceId();
72348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    // Do not add the same badge twice
72448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    if (badgeResourceId != 0 && mBadgeIds.contains(badgeResourceId)) {
72548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                        continue;
72648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    }
7276b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    if (badgeDrawable != null) {
7286b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        ImageView badgeView = new ImageView(getContext());
7296b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        LinearLayout.LayoutParams badgeViewParams = new LinearLayout.LayoutParams(
7306b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                (int) getResources().getDimension(
7316b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                        R.dimen.expanding_entry_card_item_icon_width),
7326b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                (int) getResources().getDimension(
7336b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                        R.dimen.expanding_entry_card_item_icon_height));
7346b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeViewParams.setMarginEnd((int) getResources().getDimension(
7356b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                                R.dimen.expanding_entry_card_badge_separator_margin));
7366b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeView.setLayoutParams(badgeViewParams);
7376b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        badgeView.setImageDrawable(badgeDrawable);
7386b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                        mBadges.add(badgeView);
73948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                        mBadgeIds.add(badgeResourceId);
7406b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                    }
7416b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                }
7426b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            }
7436b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            mBadgeContainer.removeAllViews();
7446b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            for (ImageView badge : mBadges) {
7456b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos                mBadgeContainer.addView(badge);
7466b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos            }
7476b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos        }
7486b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos    }
7496b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos
7502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void expand() {
7510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ChangeBounds boundsTransition = new ChangeBounds();
7520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.setDuration(DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
7530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7540cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        Fade fadeIn = new Fade(Fade.IN);
7550cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setDuration(DURATION_EXPAND_ANIMATION_FADE_IN);
7560cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setStartDelay(DELAY_EXPAND_ANIMATION_FADE_IN);
7570cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7580cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionSet transitionSet = new TransitionSet();
7590cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(boundsTransition);
7600cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(fadeIn);
7610cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7624cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos        transitionSet.excludeTarget(R.id.text, /* exclude = */ true);
7634cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos
7640cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
7650cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                this : mAnimationViewGroup;
7660cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7670cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addListener(new TransitionListener() {
7680cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7690cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionStart(Transition transition) {
7700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                // The listener is used to turn off suppressing, the proper delta is not necessary
7710cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                mListener.onExpand(0);
7720cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7730cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionEnd(Transition transition) {
7760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7780cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7790cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionCancel(Transition transition) {
7800cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7810cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7820cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7830cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionPause(Transition transition) {
7840cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7850cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7860cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7870cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionResume(Transition transition) {
7880cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7890cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        });
7900cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7910cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet);
7922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = true;
7940d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        // In order to insert new entries, we may need to inflate them for the first time
79560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        inflateAllEntries(LayoutInflater.from(getContext()));
7962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
797c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateExpandCollapseButton(getCollapseButtonText(),
798c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
7992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void collapse() {
8020cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final int startingHeight = mEntriesViewGroup.getMeasuredHeight();
8032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = false;
804c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateExpandCollapseButton(getExpandButtonText(),
805c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
8062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8070cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ChangeBounds boundsTransition = new ChangeBounds();
8080cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
8092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8100cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ChangeScroll scrollTransition = new ChangeScroll();
8110cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        scrollTransition.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
8120cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8130cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionSet transitionSet = new TransitionSet();
8140cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(boundsTransition);
8150cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(scrollTransition);
8160cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
817c23508e6e4740d798147f15c8ce1dff3395079bdPaul Soulos        transitionSet.excludeTarget(R.id.text, /* exclude = */ true);
818c23508e6e4740d798147f15c8ce1dff3395079bdPaul Soulos
8190cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
8200cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                this : mAnimationViewGroup;
8210cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8220cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.addListener(new TransitionListener() {
8232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            @Override
8240cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionStart(Transition transition) {
8250cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                /*
8260cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 * onTransitionStart is called after the view hierarchy has been changed but before
8270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 * the animation begins.
8280cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                 */
8290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                int finishingHeight = mEntriesViewGroup.getMeasuredHeight();
8300cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                mListener.onCollapse(startingHeight - finishingHeight);
8312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
8320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionEnd(Transition transition) {
8350cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            @Override
8380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionCancel(Transition transition) {
8390cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8410cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8420cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionPause(Transition transition) {
8430cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8440cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8450cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8460cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionResume(Transition transition) {
8472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
8482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        });
8490cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8500cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet);
8510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        insertEntriesIntoViewGroup();
8532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Returns whether the view is currently in its expanded state.
8572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public boolean isExpanded() {
8592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return mIsExpanded;
8602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the title text of this ExpandingEntryCardView.
8642fa690807a94708384789b211965bfc75b5ac38ePaul Soulos     * @param title The title to set. A null title will result in the title being removed.
8652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setTitle(String title) {
8672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mTitleTextView == null) {
8682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            Log.e(TAG, "mTitleTextView is null");
8692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
8702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView.setText(title);
8711321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        mTitleTextView.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
8721321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        findViewById(R.id.title_separator).setVisibility(TextUtils.isEmpty(title) ?
8731321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                View.GONE : View.VISIBLE);
8741321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If the title is set after children have been added, reset the top entry's padding to
8751321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the default. Else if the title is cleared after children have been added, set
8761321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the extra top padding
8771321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
8781321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
8791321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
8801321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
8811321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top),
8821321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
8831321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingBottom());
8841321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        } else if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
8851321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
8861321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
8871321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
8881321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
8891321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            getResources().getDimensionPixelSize(
8901321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                                    R.dimen.expanding_entry_card_null_title_top_extra_padding),
8911321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
8921321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingBottom());
8931321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
8942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
895eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
896eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    public boolean shouldShow() {
897eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        return mEntries != null && mEntries.size() > 0;
898eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
8992a4207fb39330e840436215c896cde911489e111Paul Soulos
9002a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryView extends RelativeLayout {
9012a4207fb39330e840436215c896cde911489e111Paul Soulos        private EntryContextMenuInfo mEntryContextMenuInfo;
9022a4207fb39330e840436215c896cde911489e111Paul Soulos
9032a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context) {
9042a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context);
9052a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9062a4207fb39330e840436215c896cde911489e111Paul Soulos
9072a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context, AttributeSet attrs) {
9082a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context, attrs);
9092a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9102a4207fb39330e840436215c896cde911489e111Paul Soulos
9112a4207fb39330e840436215c896cde911489e111Paul Soulos        public void setContextMenuInfo(EntryContextMenuInfo info) {
9122a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = info;
9132a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9142a4207fb39330e840436215c896cde911489e111Paul Soulos
9152a4207fb39330e840436215c896cde911489e111Paul Soulos        @Override
9162a4207fb39330e840436215c896cde911489e111Paul Soulos        protected ContextMenuInfo getContextMenuInfo() {
9172a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
9182a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9192a4207fb39330e840436215c896cde911489e111Paul Soulos    }
9202a4207fb39330e840436215c896cde911489e111Paul Soulos
9212a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryContextMenuInfo implements ContextMenuInfo {
9222a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyText;
9232a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyLabel;
92497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final String mMimeType;
92597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final long mId;
92697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final boolean mIsSuperPrimary;
9272a4207fb39330e840436215c896cde911489e111Paul Soulos
92897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public EntryContextMenuInfo(String copyText, String copyLabel, String mimeType, long id,
92997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                boolean isSuperPrimary) {
9302a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyText = copyText;
9312a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyLabel = copyLabel;
93297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mMimeType = mimeType;
93397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mId = id;
93497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mIsSuperPrimary = isSuperPrimary;
9352a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9362a4207fb39330e840436215c896cde911489e111Paul Soulos
9372a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyText() {
9382a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyText;
9392a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9402a4207fb39330e840436215c896cde911489e111Paul Soulos
9412a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyLabel() {
9422a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyLabel;
9432a4207fb39330e840436215c896cde911489e111Paul Soulos        }
94497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
94597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public String getMimeType() {
94697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mMimeType;
94797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
94897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
94997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public long getId() {
95097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mId;
95197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
95297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
95397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public boolean isSuperPrimary() {
95497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mIsSuperPrimary;
95597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
9562a4207fb39330e840436215c896cde911489e111Paul Soulos    }
9572ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9582ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    static final class EntryTag {
9592ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final int mId;
9602ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final Intent mIntent;
9612ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9622ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public EntryTag(int id, Intent intent) {
9632ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
9642ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mIntent = intent;
9652ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9662ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9672ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public int getId() {
9682ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
9692ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9702ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9712ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Intent getIntent() {
9722ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mIntent;
9732ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9742ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    }
97548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
97648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    /**
97748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * This custom touch listener increases the touch area for the second and third icons, if
97848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * they are present. This is necessary to maintain other properties on an entry view, like
97948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * using a top padding on entry. Based off of {@link android.view.TouchDelegate}
98048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     */
98148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    private static final class EntryTouchListener implements View.OnTouchListener {
98248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final View mEntry;
98348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final ImageView mAlternateIcon;
98448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final ImageView mThirdIcon;
98548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /** mTouchedView locks in a view on touch down */
98648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private View mTouchedView;
98748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /** mSlop adds some space to account for touches that are just outside the hit area */
98848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private int mSlop;
98948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
99048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        public EntryTouchListener(View entry, ImageView alternateIcon, ImageView thirdIcon) {
99148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mEntry = entry;
99248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mAlternateIcon = alternateIcon;
99348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIcon = thirdIcon;
99448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mSlop = ViewConfiguration.get(entry.getContext()).getScaledTouchSlop();
99548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
99648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
99748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        @Override
99848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        public boolean onTouch(View v, MotionEvent event) {
99948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            View touchedView = mTouchedView;
100048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean sendToTouched = false;
100148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean hit = true;
100248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean handled = false;
100348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
100448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            switch (event.getAction()) {
100548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_DOWN:
100648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    if (hitThirdIcon(event)) {
100748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mThirdIcon;
100848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = true;
100948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    } else if (hitAlternateIcon(event)) {
101048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mAlternateIcon;
101148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = true;
101248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    } else {
101348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mEntry;
101448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = false;
101548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    }
101648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    touchedView = mTouchedView;
101748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
101848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_UP:
101948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_MOVE:
102048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    sendToTouched = mTouchedView != null && mTouchedView != mEntry;
102148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    if (sendToTouched) {
102248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        final Rect slopBounds = new Rect();
102348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        touchedView.getHitRect(slopBounds);
102448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        slopBounds.inset(-mSlop, -mSlop);
102548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        if (!slopBounds.contains((int) event.getX(), (int) event.getY())) {
102648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                            hit = false;
102748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        }
102848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    }
102948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
103048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_CANCEL:
103148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    sendToTouched = mTouchedView != null && mTouchedView != mEntry;
103248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    mTouchedView = null;
103348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
103448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
103548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            if (sendToTouched) {
103648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                if (hit) {
103748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    event.setLocation(touchedView.getWidth() / 2, touchedView.getHeight() / 2);
103848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                } else {
103948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    // Offset event coordinates to be outside the target view (in case it does
104048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    // something like tracking pressed state)
104148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    event.setLocation(-(mSlop * 2), -(mSlop * 2));
104248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                }
104348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                handled = touchedView.dispatchTouchEvent(event);
104448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
104548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return handled;
104648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
104748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
104848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private boolean hitThirdIcon(MotionEvent event) {
104948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            if (mEntry.isLayoutRtl()) {
105048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mThirdIcon.getVisibility() == View.VISIBLE &&
105148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() < mThirdIcon.getRight();
105248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            } else {
105348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mThirdIcon.getVisibility() == View.VISIBLE &&
105448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() > mThirdIcon.getLeft();
105548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
105648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
105748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
105848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /**
105948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos         * Should be used after checking if third icon was hit
106048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos         */
106148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private boolean hitAlternateIcon(MotionEvent event) {
106248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            // LayoutParams used to add the start margin to the touch area
106348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            final RelativeLayout.LayoutParams alternateIconParams =
106448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    (RelativeLayout.LayoutParams) mAlternateIcon.getLayoutParams();
106548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            if (mEntry.isLayoutRtl()) {
106648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mAlternateIcon.getVisibility() == View.VISIBLE &&
106748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() < mAlternateIcon.getRight() + alternateIconParams.rightMargin;
106848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            } else {
106948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mAlternateIcon.getVisibility() == View.VISIBLE &&
107048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() > mAlternateIcon.getLeft() - alternateIconParams.leftMargin;
107148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
107248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
107348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    }
10742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos}
1075