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
18245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.animation.Animator;
19245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.animation.Animator.AnimatorListener;
20245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.animation.AnimatorSet;
21c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulosimport android.animation.ObjectAnimator;
225f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunnimport android.app.Activity;
232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Context;
242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Intent;
252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.res.Resources;
267b0b0ce616c6c2fa149918c112128388712f5657Paul Soulosimport android.graphics.ColorFilter;
27dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.graphics.Rect;
282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.graphics.drawable.Drawable;
295f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunnimport android.os.Bundle;
30ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulosimport android.support.v7.widget.CardView;
317ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jangimport android.text.Spannable;
322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.text.TextUtils;
330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeBounds;
340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Fade;
350cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition;
360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition.TransitionListener;
370cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionManager;
380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionSet;
392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.AttributeSet;
402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.Log;
41245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.util.Property;
422a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo;
432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.LayoutInflater;
4448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.MotionEvent;
452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.View;
4648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.ViewConfiguration;
472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.ViewGroup;
482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.ImageView;
492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.LinearLayout;
504b943553afdb7286b33e4bc2481431e816c57967Paul Soulosimport android.widget.RelativeLayout;
512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.TextView;
522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport com.android.contacts.R;
5469c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.dialog.CallSubjectDialog;
550cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList;
572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.List;
582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos/**
602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Display entries in a LinearLayout that can be expanded to show all entries.
612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */
62ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulospublic class ExpandingEntryCardView extends CardView {
632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private static final String TAG = "ExpandingEntryCardView";
650cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private static final int DURATION_EXPAND_ANIMATION_FADE_IN = 200;
66245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    private static final int DURATION_COLLAPSE_ANIMATION_FADE_OUT = 75;
670cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private static final int DELAY_EXPAND_ANIMATION_FADE_IN = 100;
680cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
690cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    public static final int DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS = 300;
700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    public static final int DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS = 300;
712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
72245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    private static final Property<View, Integer> VIEW_LAYOUT_HEIGHT_PROPERTY =
73245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            new Property<View, Integer>(Integer.class, "height") {
74245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                @Override
75245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                public void set(View view, Integer height) {
76245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
77245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                            view.getLayoutParams();
78245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    params.height = height;
79245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    view.setLayoutParams(params);
80245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                }
81245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
82245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                @Override
83245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                public Integer get(View view) {
84245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    return view.getLayoutParams().height;
85245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                }
86245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            };
87245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Entry data.
902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public static final class Entry {
925f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        // No action when clicking a button is specified.
935f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        public static final int ACTION_NONE = 1;
945f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        // Button action is an intent.
955f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        public static final int ACTION_INTENT = 2;
965f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        // Button action will open the call with subject dialog.
975f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        public static final int ACTION_CALL_WITH_SUBJECT = 3;
982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
992ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final int mId;
1002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mIcon;
1012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mHeader;
1022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mSubHeader;
1032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mSubHeaderIcon;
1042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final String mText;
1052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Drawable mTextIcon;
1067ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang        private Spannable mPrimaryContentDescription;
1072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final Intent mIntent;
108dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Drawable mAlternateIcon;
109dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        private final Intent mAlternateIntent;
1105da55ff837f57a63b409cd495cc25f61ed6fd709Wenyi Wang        private Spannable mAlternateContentDescription;
11148ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        private final boolean mShouldApplyColor;
1122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        private final boolean mIsEditable;
1132a4207fb39330e840436215c896cde911489e111Paul Soulos        private final EntryContextMenuInfo mEntryContextMenuInfo;
11448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final Drawable mThirdIcon;
11548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final Intent mThirdIntent;
11648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final String mThirdContentDescription;
11748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        private final int mIconResourceId;
1185f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        private final int mThirdAction;
1195f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        private final Bundle mThirdExtras;
120d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai        private final boolean mShouldApplyThirdIconColor;
1212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1222ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Entry(int id, Drawable mainIcon, String header, String subHeader,
12323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                Drawable subHeaderIcon, String text, Drawable textIcon,
1247ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang                Spannable primaryContentDescription, Intent intent,
1255da55ff837f57a63b409cd495cc25f61ed6fd709Wenyi Wang                Drawable alternateIcon, Intent alternateIntent,
1265da55ff837f57a63b409cd495cc25f61ed6fd709Wenyi Wang                Spannable alternateContentDescription, boolean shouldApplyColor, boolean isEditable,
12748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent,
1285f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                String thirdContentDescription, int thirdAction, Bundle thirdExtras,
129d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai                boolean shouldApplyThirdIconColor, int iconResourceId) {
1302ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
1312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIcon = mainIcon;
1322d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mHeader = header;
1332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeader = subHeader;
1342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mSubHeaderIcon = subHeaderIcon;
1352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mText = text;
1362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mTextIcon = textIcon;
13723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            mPrimaryContentDescription = primaryContentDescription;
1382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIntent = intent;
139dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIcon = alternateIcon;
140dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateIntent = alternateIntent;
141dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            mAlternateContentDescription = alternateContentDescription;
14248ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            mShouldApplyColor = shouldApplyColor;
1432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            mIsEditable = isEditable;
1442a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = entryContextMenuInfo;
14548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIcon = thirdIcon;
14648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIntent = thirdIntent;
14748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdContentDescription = thirdContentDescription;
1485f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            mThirdAction = thirdAction;
1495f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            mThirdExtras = thirdExtras;
150d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai            mShouldApplyThirdIconColor = shouldApplyThirdIconColor;
15148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos            mIconResourceId = iconResourceId;
1522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getIcon() {
1552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIcon;
1562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getHeader() {
1592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mHeader;
1602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        String getSubHeader() {
1632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeader;
1642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getSubHeaderIcon() {
1672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mSubHeaderIcon;
1682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public String getText() {
1712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mText;
1722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Drawable getTextIcon() {
1752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mTextIcon;
1762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
1787ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang        Spannable getPrimaryContentDescription() {
17923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            return mPrimaryContentDescription;
18023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
18123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos
1822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        Intent getIntent() {
1832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIntent;
1842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
186dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Drawable getAlternateIcon() {
187dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIcon;
188dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
189dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
190dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Intent getAlternateIntent() {
191dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateIntent;
192dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
193dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
1945da55ff837f57a63b409cd495cc25f61ed6fd709Wenyi Wang        Spannable getAlternateContentDescription() {
195dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return mAlternateContentDescription;
196dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
197dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
19848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        boolean shouldApplyColor() {
19948ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos            return mShouldApplyColor;
20048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        }
20148ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos
2022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        boolean isEditable() {
2032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            return mIsEditable;
2042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
205ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
2062ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        int getId() {
2072ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
208ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos        }
2092a4207fb39330e840436215c896cde911489e111Paul Soulos
2102a4207fb39330e840436215c896cde911489e111Paul Soulos        EntryContextMenuInfo getEntryContextMenuInfo() {
2112a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
2122a4207fb39330e840436215c896cde911489e111Paul Soulos        }
21348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
21448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Drawable getThirdIcon() {
21548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdIcon;
21648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
21748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
21848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Intent getThirdIntent() {
21948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdIntent;
22048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
22148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
22248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        String getThirdContentDescription() {
22348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return mThirdContentDescription;
22448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
22548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos
22648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        int getIconResourceId() {
22748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos            return mIconResourceId;
22848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        }
2295f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn
2305f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        public int getThirdAction() {
2315f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            return mThirdAction;
2325f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        }
2335f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn
2345f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        public Bundle getThirdExtras() {
2355f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            return mThirdExtras;
2365f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        }
237d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai
238d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai        boolean shouldApplyThirdIconColor() {
239d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai            return mShouldApplyThirdIconColor;
240d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai        }
2412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
243e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    public interface ExpandingEntryCardViewListener {
244e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        void onCollapse(int heightDelta);
245245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        void onExpand();
246245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        void onExpandDone();
247e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    }
248e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell
2492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private View mExpandCollapseButton;
2502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mExpandCollapseTextView;
2512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private TextView mTitleTextView;
2522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private OnClickListener mOnClickListener;
2532a4207fb39330e840436215c896cde911489e111Paul Soulos    private OnCreateContextMenuListener mOnCreateContextMenuListener;
2542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private boolean mIsExpanded = false;
255691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos    /**
256691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * The max number of entries to show in a collapsed card. If there are less entries passed in,
257691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     * then they are all shown.
258691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos     */
2592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mCollapsedEntriesCount;
260e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    private ExpandingEntryCardViewListener mListener;
26160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<Entry>> mEntries;
26260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private int mNumEntries = 0;
26360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private boolean mAllEntriesInflated = false;
26460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private List<List<View>> mEntryViews;
2652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private LinearLayout mEntriesViewGroup;
266c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private final ImageView mExpandCollapseArrow;
2672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private int mThemeColor;
2687b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    private ColorFilter mThemeColorFilter;
26989966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos    private boolean mIsAlwaysExpanded;
2700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    /** The ViewGroup to run the expand/collapse animation on */
2710cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    private ViewGroup mAnimationViewGroup;
27205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell    private final int mDividerLineHeightPixels;
273cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    /**
274cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * List to hold the separators. This saves us from reconstructing every expand/collapse and
275cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     * provides a smoother animation.
276cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos     */
277cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private List<View> mSeparators;
278ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos    private LinearLayout mContainer;
2792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private final OnClickListener mExpandCollapseButtonListener = new OnClickListener() {
2812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        @Override
2822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public void onClick(View v) {
2832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            if (mIsExpanded) {
2842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                collapse();
2852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            } else {
2862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expand();
2872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
2882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
2892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    };
2902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context) {
2920d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        this(context, null);
2932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
2942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
2952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public ExpandingEntryCardView(Context context, AttributeSet attrs) {
2962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        super(context, attrs);
2972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater inflater = LayoutInflater.from(context);
2982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        View expandingEntryCardView = inflater.inflate(R.layout.expanding_entry_card_view, this);
2992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup = (LinearLayout)
3002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                expandingEntryCardView.findViewById(R.id.content_area_linear_layout);
3012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView = (TextView) expandingEntryCardView.findViewById(R.id.title);
302ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        mContainer = (LinearLayout) expandingEntryCardView.findViewById(R.id.container);
3037b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
3047b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton = inflater.inflate(
3057b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                R.layout.quickcontact_expanding_entry_card_button, this, false);
3067b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseTextView = (TextView) mExpandCollapseButton.findViewById(R.id.text);
307c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        mExpandCollapseArrow = (ImageView) mExpandCollapseButton.findViewById(R.id.arrow);
3087b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mExpandCollapseButton.setOnClickListener(mExpandCollapseButtonListener);
30905287bf0cea303b93802a629aa883fb6322ca342Brian Attwell        mDividerLineHeightPixels = getResources()
31005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                .getDimensionPixelSize(R.dimen.divider_line_height);
3112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
3142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the Entry list to display.
3152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     *
3162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param entries The Entry list to display.
3172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
31860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries,
319139a03bd82f45338402e747154dd7b3d61bf1747yaolu            boolean isExpanded, boolean isAlwaysExpanded, ExpandingEntryCardViewListener listener,
320139a03bd82f45338402e747154dd7b3d61bf1747yaolu            ViewGroup animationViewGroup) {
3212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
3222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = isExpanded;
32389966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsAlwaysExpanded = isAlwaysExpanded;
32489966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        // If isAlwaysExpanded is true, mIsExpanded should be true
32589966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos        mIsExpanded |= mIsAlwaysExpanded;
32660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mEntryViews = new ArrayList<List<View>>(entries.size());
3270d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        mEntries = entries;
3286095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNumEntries = 0;
3296095369885edcca566a812b551886e29c7ff8039Brian Attwell        mAllEntriesInflated = false;
33060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (List<Entry> entryList : mEntries) {
33160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mNumEntries += entryList.size();
33260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            mEntryViews.add(new ArrayList<View>());
33360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
33460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries);
335cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        // We need a separator between each list, but not after the last one
336cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        if (entries.size() > 1) {
337cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            mSeparators = new ArrayList<>(entries.size() - 1);
338cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        }
339e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        mListener = listener;
3400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        mAnimationViewGroup = animationViewGroup;
3410d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell
3427b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mIsExpanded) {
343c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getCollapseButtonText(), /* duration = */ 0);
34460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
3457b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        } else {
346c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            updateExpandCollapseButton(getExpandButtonText(), /* duration = */ 0);
34760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateInitialEntries(layoutInflater);
3482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
3507b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
3512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    @Override
3542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setOnClickListener(OnClickListener listener) {
3552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mOnClickListener = listener;
3562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
3572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
3582a4207fb39330e840436215c896cde911489e111Paul Soulos    @Override
3592a4207fb39330e840436215c896cde911489e111Paul Soulos    public void setOnCreateContextMenuListener (OnCreateContextMenuListener listener) {
3602a4207fb39330e840436215c896cde911489e111Paul Soulos        mOnCreateContextMenuListener = listener;
3612a4207fb39330e840436215c896cde911489e111Paul Soulos    }
3622a4207fb39330e840436215c896cde911489e111Paul Soulos
363245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    private List<View> calculateEntriesToRemoveDuringCollapse() {
364245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final List<View> viewsToRemove = getViewsToDisplay(true);
365245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final List<View> viewsCollapsed = getViewsToDisplay(false);
366245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        viewsToRemove.removeAll(viewsCollapsed);
367245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        return viewsToRemove;
368245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    }
369245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
3702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void insertEntriesIntoViewGroup() {
3712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mEntriesViewGroup.removeAllViews();
37260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
373245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        for (View view : getViewsToDisplay(mIsExpanded)) {
374245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            mEntriesViewGroup.addView(view);
375245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        }
376245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
377245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        removeView(mExpandCollapseButton);
378245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        if (mCollapsedEntriesCount < mNumEntries
379245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                && mExpandCollapseButton.getParent() == null && !mIsAlwaysExpanded) {
380245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            mContainer.addView(mExpandCollapseButton, -1);
381245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        }
382245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    }
383245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
384245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    /**
385245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell     * Returns the list of views that should be displayed. This changes depending on whether
386245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell     * the card is expanded or collapsed.
387245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell     */
388245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    private List<View> getViewsToDisplay(boolean isExpanded) {
389245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final List<View> viewsToDisplay = new ArrayList<View>();
390245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        if (isExpanded) {
391cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            for (int i = 0; i < mEntryViews.size(); i++) {
392cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                List<View> viewList = mEntryViews.get(i);
393cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                if (i > 0) {
394cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
395cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
396cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(viewList.get(0));
397cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
398cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
399cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
400cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
401245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    viewsToDisplay.add(separator);
40297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
40360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (View view : viewList) {
404245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    viewsToDisplay.add(view);
40560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                }
40660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
40760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
408691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // We want to insert mCollapsedEntriesCount entries into the group. extraEntries is the
409691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // number of entries that need to be added that are not the head element of a list
410691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // to reach mCollapsedEntriesCount.
411691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInViewGroup = 0;
412691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntryViews.size();
413691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntryViews.size() && numInViewGroup < mCollapsedEntriesCount;
414691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    i++) {
415691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
41697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (i > 0) {
417cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    View separator;
418cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    if (mSeparators.size() <= i - 1) {
419cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = generateSeparator(entryViewList.get(0));
420cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        mSeparators.add(separator);
421cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    } else {
422cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                        separator = mSeparators.get(i - 1);
423cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    }
424245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    viewsToDisplay.add(separator);
425691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
426245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                viewsToDisplay.add(entryViewList.get(0));
427691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInViewGroup++;
42805287bf0cea303b93802a629aa883fb6322ca342Brian Attwell
429691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Insert entries in this list to hit mCollapsedEntriesCount.
430139a03bd82f45338402e747154dd7b3d61bf1747yaolu                for (int j = 1; j < entryViewList.size() && numInViewGroup < mCollapsedEntriesCount
431139a03bd82f45338402e747154dd7b3d61bf1747yaolu                        && extraEntries > 0; j++) {
432245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    viewsToDisplay.add(entryViewList.get(j));
433691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInViewGroup++;
434691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
43597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
4362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
4372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
4382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
439245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        formatEntryIfFirst(viewsToDisplay);
440245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        return viewsToDisplay;
4412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
443245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell    private void formatEntryIfFirst(List<View> entriesViewGroup) {
4441321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If no title and the first entry in the group, add extra padding
4451321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (TextUtils.isEmpty(mTitleTextView.getText()) &&
446245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                entriesViewGroup.size() > 0) {
447245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            final View entry = entriesViewGroup.get(0);
4487c6c48ab12ce4dabe4609db847e747f6629d47e8yaolu            entry.setPaddingRelative(entry.getPaddingStart(),
449568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
450568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
451568d5d82610f87a5e733690e57075f0a99551972Paul Soulos                    getResources().getDimensionPixelSize(
4521321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_null_title_top_extra_padding),
4537c6c48ab12ce4dabe4609db847e747f6629d47e8yaolu                    entry.getPaddingEnd(),
4541321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    entry.getPaddingBottom());
4551321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
4562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
458cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos    private View generateSeparator(View entry) {
4590cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        View separator = new View(getContext());
460ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        Resources res = getResources();
461ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
462ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        separator.setBackgroundColor(res.getColor(
463daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell                R.color.divider_line_color_light));
464ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
46505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                ViewGroup.LayoutParams.MATCH_PARENT, mDividerLineHeightPixels);
4660cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // The separator is aligned with the text in the entry. This is offset by a default
4670cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        // margin. If there is an icon present, the icon's width and margin are added
468ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        int marginStart = res.getDimensionPixelSize(
4690cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                R.dimen.expanding_entry_card_item_padding_start);
4700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ImageView entryIcon = (ImageView) entry.findViewById(R.id.icon);
47197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        if (entryIcon.getVisibility() == View.VISIBLE) {
4720cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            int imageWidthAndMargin =
473ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_icon_width) +
474ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_image_spacing);
4750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            marginStart += imageWidthAndMargin;
4760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        }
47797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        layoutParams.setMarginStart(marginStart);
4780cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        separator.setLayoutParams(layoutParams);
479cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        return separator;
4800cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos    }
4810cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
4822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getExpandButtonText() {
483139a03bd82f45338402e747154dd7b3d61bf1747yaolu        // Default to "See more".
484139a03bd82f45338402e747154dd7b3d61bf1747yaolu        return getResources().getText(R.string.expanding_entry_card_view_see_more);
4852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private CharSequence getCollapseButtonText() {
488139a03bd82f45338402e747154dd7b3d61bf1747yaolu        // Default to "See less".
489139a03bd82f45338402e747154dd7b3d61bf1747yaolu        return getResources().getText(R.string.expanding_entry_card_view_see_less);
4902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
4912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
4920d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell    /**
49360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates the initial entries to be shown.
4940d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell     */
49560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateInitialEntries(LayoutInflater layoutInflater) {
49660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        // If the number of collapsed entries equals total entries, inflate all
49760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mCollapsedEntriesCount == mNumEntries) {
49860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            inflateAllEntries(layoutInflater);
49960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        } else {
50060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            // Otherwise inflate the top entry from each list
501691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            // extraEntries is used to add extra entries until mCollapsedEntriesCount is reached.
502691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int numInflated = 0;
503691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            int extraEntries = mCollapsedEntriesCount - mEntries.size();
504691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos            for (int i = 0; i < mEntries.size() && numInflated < mCollapsedEntriesCount; i++) {
505691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<Entry> entryList = mEntries.get(i);
506691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                List<View> entryViewList = mEntryViews.get(i);
507691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos
508691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                entryViewList.add(createEntryView(layoutInflater, entryList.get(0),
50997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                        /* showIcon = */ View.VISIBLE));
510691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                numInflated++;
51105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell
512691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                // Inflate entries in this list to hit mCollapsedEntriesCount.
513139a03bd82f45338402e747154dd7b3d61bf1747yaolu                for (int j = 1; j < entryList.size() && numInflated < mCollapsedEntriesCount
51405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                        && extraEntries > 0; j++) {
515691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    entryViewList.add(createEntryView(layoutInflater, entryList.get(j),
51643e0dead719568ed610f9f111f6e7614368445efPaul Soulos                            /* showIcon = */ View.INVISIBLE));
517691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    numInflated++;
518691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                    extraEntries--;
519691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos                }
52060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
52160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
52260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    }
52360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos
52460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    /**
52560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     * Inflates all entries.
52660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos     */
52760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos    private void inflateAllEntries(LayoutInflater layoutInflater) {
52860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        if (mAllEntriesInflated) {
52960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            return;
53060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        }
53160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        for (int i = 0; i < mEntries.size(); i++) {
53260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<Entry> entryList = mEntries.get(i);
53360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            List<View> viewList = mEntryViews.get(i);
53460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            for (int j = viewList.size(); j < entryList.size(); j++) {
53597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final int iconVisibility;
53697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                final Entry entry = entryList.get(j);
53797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // If the entry does not have an icon, mark gone. Else if it has an icon, show
53897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                // for the first Entry in the list only
53997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                if (entry.getIcon() == null) {
54097ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.GONE;
54197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else if (j == 0) {
54297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.VISIBLE;
54397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                } else {
54497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                    iconVisibility = View.INVISIBLE;
54597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                }
54697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos                viewList.add(createEntryView(layoutInflater, entry, iconVisibility));
54760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            }
5482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
54960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        mAllEntriesInflated = true;
5502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
5512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
5527b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void setColorAndFilter(int color, ColorFilter colorFilter) {
5537b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColor = color;
5547b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        mThemeColorFilter = colorFilter;
5557b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        applyColor();
5567b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
5577b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5586095369885edcca566a812b551886e29c7ff8039Brian Attwell    public void setEntryHeaderColor(int color) {
5596095369885edcca566a812b551886e29c7ff8039Brian Attwell        if (mEntries != null) {
5606095369885edcca566a812b551886e29c7ff8039Brian Attwell            for (List<View> entryList : mEntryViews) {
5616095369885edcca566a812b551886e29c7ff8039Brian Attwell                for (View entryView : entryList) {
5626095369885edcca566a812b551886e29c7ff8039Brian Attwell                    TextView header = (TextView) entryView.findViewById(R.id.header);
5636095369885edcca566a812b551886e29c7ff8039Brian Attwell                    if (header != null) {
5646095369885edcca566a812b551886e29c7ff8039Brian Attwell                        header.setTextColor(color);
5656095369885edcca566a812b551886e29c7ff8039Brian Attwell                    }
5666095369885edcca566a812b551886e29c7ff8039Brian Attwell                }
5676095369885edcca566a812b551886e29c7ff8039Brian Attwell            }
5686095369885edcca566a812b551886e29c7ff8039Brian Attwell        }
5696095369885edcca566a812b551886e29c7ff8039Brian Attwell    }
5706095369885edcca566a812b551886e29c7ff8039Brian Attwell
57104a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu    public void setEntrySubHeaderColor(int color) {
57204a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu        if (mEntries != null) {
57304a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu            for (List<View> entryList : mEntryViews) {
57404a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                for (View entryView : entryList) {
57504a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                    final TextView subHeader = (TextView) entryView.findViewById(R.id.sub_header);
57604a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                    if (subHeader != null) {
57704a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                        subHeader.setTextColor(color);
57804a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                    }
57904a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu                }
58004a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu            }
58104a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu        }
58204a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu    }
58304a1936c4f1f9f414551047c68e7a344d22fddc1guanxiongliu
5847b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    /**
5857b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * The ColorFilter is passed in along with the color so that a new one only needs to be created
5867b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * once for the entire activity.
5877b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 1. Title
5887b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 2. Entry icons
5897b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 3. Expand/Collapse Text
5907b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     * 4. Expand/Collapse Button
5917b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos     */
5927b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    public void applyColor() {
5937b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        if (mThemeColor != 0 && mThemeColorFilter != null) {
5947b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Title
5957b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mTitleTextView != null) {
5967b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                mTitleTextView.setTextColor(mThemeColor);
5977b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
5987b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
5997b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Entry icons
6007b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            if (mEntries != null) {
60160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                for (List<Entry> entryList : mEntries) {
60260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                    for (Entry entry : entryList) {
60348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                        if (entry.shouldApplyColor()) {
60448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            Drawable icon = entry.getIcon();
60548ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            if (icon != null) {
6060da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell                                icon.mutate();
60748ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                                icon.setColorFilter(mThemeColorFilter);
60848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                            }
60960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos                        }
610dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        Drawable alternateIcon = entry.getAlternateIcon();
611dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        if (alternateIcon != null) {
6120da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell                            alternateIcon.mutate();
613dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                            alternateIcon.setColorFilter(mThemeColorFilter);
614dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                        }
61548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        Drawable thirdIcon = entry.getThirdIcon();
616d23de6146c23a27836a96e8a6f10a74346a905ddGary Mai                        if (thirdIcon != null && entry.shouldApplyThirdIconColor()) {
6170da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell                            thirdIcon.mutate();
61848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                            thirdIcon.setColorFilter(mThemeColorFilter);
61948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        }
620eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    }
6217b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos                }
6227b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            }
6237b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
6247b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            // Expand/Collapse
6257b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos            mExpandCollapseTextView.setTextColor(mThemeColor);
626c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            mExpandCollapseArrow.setColorFilter(mThemeColorFilter);
6277b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos        }
6287b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos    }
6297b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos
6302a4207fb39330e840436215c896cde911489e111Paul Soulos    private View createEntryView(LayoutInflater layoutInflater, final Entry entry,
6312a4207fb39330e840436215c896cde911489e111Paul Soulos            int iconVisibility) {
6322a4207fb39330e840436215c896cde911489e111Paul Soulos        final EntryView view = (EntryView) layoutInflater.inflate(
6332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                R.layout.expanding_entry_card_item, this, false);
6342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
6352a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setContextMenuInfo(entry.getEntryContextMenuInfo());
63623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        if (!TextUtils.isEmpty(entry.getPrimaryContentDescription())) {
63723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            view.setContentDescription(entry.getPrimaryContentDescription());
63823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
639ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
640dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView icon = (ImageView) view.findViewById(R.id.icon);
64197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos        icon.setVisibility(iconVisibility);
642eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (entry.getIcon() != null) {
643eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            icon.setImageDrawable(entry.getIcon());
644eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
645dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView header = (TextView) view.findViewById(R.id.header);
64603ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getHeader())) {
6472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setText(entry.getHeader());
6482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            header.setVisibility(View.GONE);
6502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
652dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView subHeader = (TextView) view.findViewById(R.id.sub_header);
65303ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getSubHeader())) {
6542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setText(entry.getSubHeader());
6552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeader.setVisibility(View.GONE);
6572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
659dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header);
6602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getSubHeaderIcon() != null) {
6612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setImageDrawable(entry.getSubHeaderIcon());
6622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            subHeaderIcon.setVisibility(View.GONE);
6642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
666dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final TextView text = (TextView) view.findViewById(R.id.text);
66703ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos        if (!TextUtils.isEmpty(entry.getText())) {
6682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setText(entry.getText());
6692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            text.setVisibility(View.GONE);
6712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
673dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text);
6742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getTextIcon() != null) {
6752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setImageDrawable(entry.getTextIcon());
6762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
6772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            textIcon.setVisibility(View.GONE);
6782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
6802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (entry.getIntent() != null) {
6817d22b94ce50f7a65dd89d4533f2aa3a3392e7972Paul Soulos            view.setOnClickListener(mOnClickListener);
6822ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            view.setTag(new EntryTag(entry.getId(), entry.getIntent()));
6832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
6842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
685a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        if (entry.getIntent() == null && entry.getEntryContextMenuInfo() == null) {
686a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            // Remove the click effect
687a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            view.setBackground(null);
688a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        }
689a42ef76251778161d27bc07db214b8c81720e476Paul Soulos
690ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // If only the header is visible, add a top margin to match icon's top margin.
691ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        // Also increase the space below the header for visual comfort.
6924b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        if (header.getVisibility() == View.VISIBLE && subHeader.getVisibility() == View.GONE &&
6934b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                text.getVisibility() == View.GONE) {
6944b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            RelativeLayout.LayoutParams headerLayoutParams =
6954b943553afdb7286b33e4bc2481431e816c57967Paul Soulos                    (RelativeLayout.LayoutParams) header.getLayoutParams();
6964b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            headerLayoutParams.topMargin = (int) (getResources().getDimension(
697ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_top));
698ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            headerLayoutParams.bottomMargin += (int) (getResources().getDimension(
699ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    R.dimen.expanding_entry_card_item_header_only_margin_bottom));
7004b943553afdb7286b33e4bc2481431e816c57967Paul Soulos            header.setLayoutParams(headerLayoutParams);
7014b943553afdb7286b33e4bc2481431e816c57967Paul Soulos        }
7024b943553afdb7286b33e4bc2481431e816c57967Paul Soulos
703edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // Adjust the top padding size for entries with an invisible icon. The padding depends on
704edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        // if there is a sub header or text section
705edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        if (iconVisibility == View.INVISIBLE &&
706edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                (!TextUtils.isEmpty(entry.getSubHeader()) || !TextUtils.isEmpty(entry.getText()))) {
707edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos            view.setPaddingRelative(view.getPaddingStart(),
708edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    getResources().getDimensionPixelSize(
709edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                            R.dimen.expanding_entry_card_item_no_icon_margin_top),
710edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingEnd(),
711edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                    view.getPaddingBottom());
712edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos        } else if (iconVisibility == View.INVISIBLE &&  TextUtils.isEmpty(entry.getSubHeader())
713edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos                && TextUtils.isEmpty(entry.getText())) {
714ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos            view.setPaddingRelative(view.getPaddingStart(), 0, view.getPaddingEnd(),
715ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos                    view.getPaddingBottom());
716ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos        }
717ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos
71848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate);
71948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        final ImageView thirdIcon = (ImageView) view.findViewById(R.id.third_icon);
72048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
72148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
72248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setImageDrawable(entry.getAlternateIcon());
72348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setOnClickListener(mOnClickListener);
72448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent()));
72548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setVisibility(View.VISIBLE);
72648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            alternateIcon.setContentDescription(entry.getAlternateContentDescription());
72748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
72848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
7295f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn        if (entry.getThirdIcon() != null && entry.getThirdAction() != Entry.ACTION_NONE) {
73048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setImageDrawable(entry.getThirdIcon());
7315f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            if (entry.getThirdAction() == Entry.ACTION_INTENT) {
7325f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                thirdIcon.setOnClickListener(mOnClickListener);
7335f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                thirdIcon.setTag(new EntryTag(entry.getId(), entry.getThirdIntent()));
7345f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            } else if (entry.getThirdAction() == Entry.ACTION_CALL_WITH_SUBJECT) {
7355f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                thirdIcon.setOnClickListener(new View.OnClickListener() {
7365f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                    @Override
7375f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                    public void onClick(View v) {
7385f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        Object tag = v.getTag();
7395f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        if (!(tag instanceof Bundle)) {
7405f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                            return;
7415f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        }
7425f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn
7435f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        Context context = getContext();
7445f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        if (context instanceof Activity) {
7455f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                            CallSubjectDialog.start((Activity) context, entry.getThirdExtras());
7465f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                        }
7475f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                    }
7485f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                });
7495f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn                thirdIcon.setTag(entry.getThirdExtras());
7505f87e923b0300173ad68f73a47b0dca7348d6a1fTyler Gunn            }
75148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setVisibility(View.VISIBLE);
75248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            thirdIcon.setContentDescription(entry.getThirdContentDescription());
75348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
75448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
75548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        // Set a custom touch listener for expanding the extra icon touch areas
75648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        view.setOnTouchListener(new EntryTouchListener(view, alternateIcon, thirdIcon));
7572a4207fb39330e840436215c896cde911489e111Paul Soulos        view.setOnCreateContextMenuListener(mOnCreateContextMenuListener);
7582a4207fb39330e840436215c896cde911489e111Paul Soulos
7592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return view;
7602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
7612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
762c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos    private void updateExpandCollapseButton(CharSequence buttonText, long duration) {
763c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        if (mIsExpanded) {
764c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
765c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 180);
766c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
767c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
7682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        } else {
769c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow,
770c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                    "rotation", 0);
771c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.setDuration(duration);
772c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos            animator.start();
7732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
7742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mExpandCollapseTextView.setText(buttonText);
7752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
7762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
7772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void expand() {
7780cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        ChangeBounds boundsTransition = new ChangeBounds();
7790cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        boundsTransition.setDuration(DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
7800cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7810cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        Fade fadeIn = new Fade(Fade.IN);
7820cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setDuration(DURATION_EXPAND_ANIMATION_FADE_IN);
7830cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        fadeIn.setStartDelay(DELAY_EXPAND_ANIMATION_FADE_IN);
7840cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7850cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionSet transitionSet = new TransitionSet();
7860cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(boundsTransition);
7870cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addTransition(fadeIn);
7880cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7894cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos        transitionSet.excludeTarget(R.id.text, /* exclude = */ true);
7904cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos
7910cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        final ViewGroup transitionViewContainer = mAnimationViewGroup == null ?
7920cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                this : mAnimationViewGroup;
7930cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
7940cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        transitionSet.addListener(new TransitionListener() {
7950cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
7960cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionStart(Transition transition) {
797245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                mListener.onExpand();
7980cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
7990cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8000cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8010cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionEnd(Transition transition) {
802245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                mListener.onExpandDone();
8030cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8040cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8050cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8060cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionCancel(Transition transition) {
8070cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8080cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8090cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8100cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionPause(Transition transition) {
8110cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8120cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8130cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
8140cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            public void onTransitionResume(Transition transition) {
8150cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8160cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        });
8170cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8180cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet);
8192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mIsExpanded = true;
8210d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell        // In order to insert new entries, we may need to inflate them for the first time
82260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos        inflateAllEntries(LayoutInflater.from(getContext()));
8232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        insertEntriesIntoViewGroup();
824c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos        updateExpandCollapseButton(getCollapseButtonText(),
825c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos                DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS);
8262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private void collapse() {
829245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final List<View> views = calculateEntriesToRemoveDuringCollapse();
830245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell
831245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // This animation requires layout changes, unlike the expand() animation: the action bar
832245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // might get scrolled open in order to fill empty space. As a result, we can't use
833245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // ChangeBounds here. Instead manually animate view height and alpha. This isn't as
834245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // efficient as the bounds and translation changes performed by ChangeBounds. Nonetheless, a
835245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // reasonable frame-rate is achieved collapsing a dozen elements on a user Svelte N4. So the
836245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        // performance hit doesn't justify writing a less maintainable animation.
837245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final AnimatorSet set = new AnimatorSet();
838245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        final List<Animator> animators = new ArrayList<Animator>(views.size());
839245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        int totalSizeChange = 0;
840245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        for (View viewToRemove : views) {
841245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            final ObjectAnimator animator = ObjectAnimator.ofObject(viewToRemove,
842245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    VIEW_LAYOUT_HEIGHT_PROPERTY, null, viewToRemove.getHeight(), 0);
843245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            totalSizeChange += viewToRemove.getHeight();
844245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            animator.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
845245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            animators.add(animator);
846245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            viewToRemove.animate().alpha(0).setDuration(DURATION_COLLAPSE_ANIMATION_FADE_OUT);
847245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        }
848245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        set.playTogether(animators);
849245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        set.start();
850245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        set.addListener(new AnimatorListener() {
8510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
852245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            public void onAnimationStart(Animator animation) {
8530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8540cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            @Override
856245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            public void onAnimationEnd(Animator animation) {
857245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                // Now that the views have been animated away, actually remove them from the view
858245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                // hierarchy. Reset their appearance so that they look appropriate when they
85905287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                // get added back later.
860245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                insertEntriesIntoViewGroup();
861245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                for (View view : views) {
86205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                    if (view instanceof EntryView) {
86305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                        VIEW_LAYOUT_HEIGHT_PROPERTY.set(view, LayoutParams.WRAP_CONTENT);
86405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                    } else {
86505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                        VIEW_LAYOUT_HEIGHT_PROPERTY.set(view, mDividerLineHeightPixels);
86605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell                    }
867245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    view.animate().cancel();
868245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                    view.setAlpha(1);
869245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                }
8700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8710cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8720cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
873245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            public void onAnimationCancel(Animator animation) {
8740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            }
8750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
8760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            @Override
877245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell            public void onAnimationRepeat(Animator animation) {
8782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
8792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        });
8800cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
881245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        mListener.onCollapse(totalSizeChange);
882245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        mIsExpanded = false;
883245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell        updateExpandCollapseButton(getExpandButtonText(),
884245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell                DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS);
8852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Returns whether the view is currently in its expanded state.
8892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public boolean isExpanded() {
8912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return mIsExpanded;
8922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
8932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
8942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    /**
8952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Sets the title text of this ExpandingEntryCardView.
8962fa690807a94708384789b211965bfc75b5ac38ePaul Soulos     * @param title The title to set. A null title will result in the title being removed.
8972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     */
8982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    public void setTitle(String title) {
8992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        if (mTitleTextView == null) {
9002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            Log.e(TAG, "mTitleTextView is null");
9012d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
9022d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mTitleTextView.setText(title);
9031321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        mTitleTextView.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
9041321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        findViewById(R.id.title_separator).setVisibility(TextUtils.isEmpty(title) ?
9051321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                View.GONE : View.VISIBLE);
9061321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // If the title is set after children have been added, reset the top entry's padding to
9071321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the default. Else if the title is cleared after children have been added, set
9081321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        // the extra top padding
9091321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
9101321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
9111321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
9121321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
9131321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top),
9141321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
9151321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingBottom());
9161321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        } else if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
9171321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            View firstEntry = mEntriesViewGroup.getChildAt(0);
9181321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos            firstEntry.setPadding(firstEntry.getPaddingLeft(),
9191321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    getResources().getDimensionPixelSize(
9201321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            R.dimen.expanding_entry_card_item_padding_top) +
9211321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                            getResources().getDimensionPixelSize(
9221321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                                    R.dimen.expanding_entry_card_null_title_top_extra_padding),
9231321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos                    firstEntry.getPaddingRight(),
9248897287c19b394c1f0b402e6291ff4304acacbc2Brian Attwell                    firstEntry.getPaddingBottom());
9251321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos        }
9262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    }
927eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
928eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    public boolean shouldShow() {
929eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        return mEntries != null && mEntries.size() > 0;
930eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
9312a4207fb39330e840436215c896cde911489e111Paul Soulos
9322a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryView extends RelativeLayout {
9332a4207fb39330e840436215c896cde911489e111Paul Soulos        private EntryContextMenuInfo mEntryContextMenuInfo;
9342a4207fb39330e840436215c896cde911489e111Paul Soulos
9352a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context) {
9362a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context);
9372a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9382a4207fb39330e840436215c896cde911489e111Paul Soulos
9392a4207fb39330e840436215c896cde911489e111Paul Soulos        public EntryView(Context context, AttributeSet attrs) {
9402a4207fb39330e840436215c896cde911489e111Paul Soulos            super(context, attrs);
9412a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9422a4207fb39330e840436215c896cde911489e111Paul Soulos
9432a4207fb39330e840436215c896cde911489e111Paul Soulos        public void setContextMenuInfo(EntryContextMenuInfo info) {
9442a4207fb39330e840436215c896cde911489e111Paul Soulos            mEntryContextMenuInfo = info;
9452a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9462a4207fb39330e840436215c896cde911489e111Paul Soulos
9472a4207fb39330e840436215c896cde911489e111Paul Soulos        @Override
9482a4207fb39330e840436215c896cde911489e111Paul Soulos        protected ContextMenuInfo getContextMenuInfo() {
9492a4207fb39330e840436215c896cde911489e111Paul Soulos            return mEntryContextMenuInfo;
9502a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9512a4207fb39330e840436215c896cde911489e111Paul Soulos    }
9522a4207fb39330e840436215c896cde911489e111Paul Soulos
9532a4207fb39330e840436215c896cde911489e111Paul Soulos    public static final class EntryContextMenuInfo implements ContextMenuInfo {
9542a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyText;
9552a4207fb39330e840436215c896cde911489e111Paul Soulos        private final String mCopyLabel;
95697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final String mMimeType;
95797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final long mId;
95897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        private final boolean mIsSuperPrimary;
9592a4207fb39330e840436215c896cde911489e111Paul Soulos
96097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public EntryContextMenuInfo(String copyText, String copyLabel, String mimeType, long id,
96197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                boolean isSuperPrimary) {
9622a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyText = copyText;
9632a4207fb39330e840436215c896cde911489e111Paul Soulos            mCopyLabel = copyLabel;
96497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mMimeType = mimeType;
96597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mId = id;
96697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mIsSuperPrimary = isSuperPrimary;
9672a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9682a4207fb39330e840436215c896cde911489e111Paul Soulos
9692a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyText() {
9702a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyText;
9712a4207fb39330e840436215c896cde911489e111Paul Soulos        }
9722a4207fb39330e840436215c896cde911489e111Paul Soulos
9732a4207fb39330e840436215c896cde911489e111Paul Soulos        public String getCopyLabel() {
9742a4207fb39330e840436215c896cde911489e111Paul Soulos            return mCopyLabel;
9752a4207fb39330e840436215c896cde911489e111Paul Soulos        }
97697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
97797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public String getMimeType() {
97897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mMimeType;
97997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
98097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
98197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public long getId() {
98297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mId;
98397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
98497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
98597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        public boolean isSuperPrimary() {
98697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            return mIsSuperPrimary;
98797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
9882a4207fb39330e840436215c896cde911489e111Paul Soulos    }
9892ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9902ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    static final class EntryTag {
9912ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final int mId;
9922ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        private final Intent mIntent;
9932ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9942ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public EntryTag(int id, Intent intent) {
9952ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mId = id;
9962ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            mIntent = intent;
9972ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
9982ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
9992ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public int getId() {
10002ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mId;
10012ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
10022ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
10032ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        public Intent getIntent() {
10042ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            return mIntent;
10052ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos        }
10062ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos    }
100748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
100848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    /**
100948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * This custom touch listener increases the touch area for the second and third icons, if
101048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * they are present. This is necessary to maintain other properties on an entry view, like
101148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     * using a top padding on entry. Based off of {@link android.view.TouchDelegate}
101248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos     */
101348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    private static final class EntryTouchListener implements View.OnTouchListener {
101448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final View mEntry;
101548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final ImageView mAlternateIcon;
101648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private final ImageView mThirdIcon;
101748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /** mTouchedView locks in a view on touch down */
101848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private View mTouchedView;
101948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /** mSlop adds some space to account for touches that are just outside the hit area */
102048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private int mSlop;
102148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
102248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        public EntryTouchListener(View entry, ImageView alternateIcon, ImageView thirdIcon) {
102348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mEntry = entry;
102448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mAlternateIcon = alternateIcon;
102548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mThirdIcon = thirdIcon;
102648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            mSlop = ViewConfiguration.get(entry.getContext()).getScaledTouchSlop();
102748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
102848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
102948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        @Override
103048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        public boolean onTouch(View v, MotionEvent event) {
103148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            View touchedView = mTouchedView;
103248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean sendToTouched = false;
103348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean hit = true;
103448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            boolean handled = false;
103548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
103648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            switch (event.getAction()) {
103748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_DOWN:
103848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    if (hitThirdIcon(event)) {
103948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mThirdIcon;
104048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = true;
104148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    } else if (hitAlternateIcon(event)) {
104248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mAlternateIcon;
104348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = true;
104448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    } else {
104548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        mTouchedView = mEntry;
104648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        sendToTouched = false;
104748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    }
104848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    touchedView = mTouchedView;
104948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
105048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_UP:
105148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_MOVE:
105248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    sendToTouched = mTouchedView != null && mTouchedView != mEntry;
105348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    if (sendToTouched) {
105448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        final Rect slopBounds = new Rect();
105548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        touchedView.getHitRect(slopBounds);
105648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        slopBounds.inset(-mSlop, -mSlop);
105748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        if (!slopBounds.contains((int) event.getX(), (int) event.getY())) {
105848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                            hit = false;
105948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        }
106048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    }
106148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
106248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                case MotionEvent.ACTION_CANCEL:
106348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    sendToTouched = mTouchedView != null && mTouchedView != mEntry;
106448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    mTouchedView = null;
106548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    break;
106648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
106748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            if (sendToTouched) {
106848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                if (hit) {
106948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    event.setLocation(touchedView.getWidth() / 2, touchedView.getHeight() / 2);
107048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                } else {
107148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    // Offset event coordinates to be outside the target view (in case it does
107248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    // something like tracking pressed state)
107348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    event.setLocation(-(mSlop * 2), -(mSlop * 2));
107448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                }
107548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                handled = touchedView.dispatchTouchEvent(event);
107648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
107748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            return handled;
107848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
107948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
108048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private boolean hitThirdIcon(MotionEvent event) {
1081f140227beb6d9e78955a7676dc0dd3f793f72017Brian Attwell            if (mEntry.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
108248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mThirdIcon.getVisibility() == View.VISIBLE &&
108348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() < mThirdIcon.getRight();
108448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            } else {
108548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mThirdIcon.getVisibility() == View.VISIBLE &&
108648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() > mThirdIcon.getLeft();
108748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
108848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
108948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
109048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        /**
109148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos         * Should be used after checking if third icon was hit
109248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos         */
109348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        private boolean hitAlternateIcon(MotionEvent event) {
109448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            // LayoutParams used to add the start margin to the touch area
109548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            final RelativeLayout.LayoutParams alternateIconParams =
109648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    (RelativeLayout.LayoutParams) mAlternateIcon.getLayoutParams();
1097f140227beb6d9e78955a7676dc0dd3f793f72017Brian Attwell            if (mEntry.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
109848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mAlternateIcon.getVisibility() == View.VISIBLE &&
109948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() < mAlternateIcon.getRight() + alternateIconParams.rightMargin;
110048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            } else {
110148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                return mAlternateIcon.getVisibility() == View.VISIBLE &&
110248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                        event.getX() > mAlternateIcon.getLeft() - alternateIconParams.leftMargin;
110348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            }
110448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        }
110548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    }
11062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos}
1107