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; 222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Context; 232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.Intent; 242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.content.res.Resources; 257b0b0ce616c6c2fa149918c112128388712f5657Paul Soulosimport android.graphics.ColorFilter; 26dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.graphics.Rect; 272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.graphics.drawable.Drawable; 28ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulosimport android.support.v7.widget.CardView; 297ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jangimport android.text.Spannable; 302d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.text.TextUtils; 310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.ChangeBounds; 320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Fade; 330cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition; 340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.Transition.TransitionListener; 350cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionManager; 360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport android.transition.TransitionSet; 372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.AttributeSet; 382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.util.Log; 39245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.util.Property; 402a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo; 412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.LayoutInflater; 4248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.MotionEvent; 432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.View; 4448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulosimport android.view.ViewConfiguration; 452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.view.ViewGroup; 462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.ImageView; 472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.LinearLayout; 48245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwellimport android.widget.LinearLayout.LayoutParams; 494b943553afdb7286b33e4bc2481431e816c57967Paul Soulosimport android.widget.RelativeLayout; 502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport android.widget.TextView; 512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulosimport com.android.contacts.R; 530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.List; 562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos/** 582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Display entries in a LinearLayout that can be expanded to show all entries. 592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 60ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulospublic class ExpandingEntryCardView extends CardView { 612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private static final String TAG = "ExpandingEntryCardView"; 630cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos private static final int DURATION_EXPAND_ANIMATION_FADE_IN = 200; 64245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell private static final int DURATION_COLLAPSE_ANIMATION_FADE_OUT = 75; 650cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos private static final int DELAY_EXPAND_ANIMATION_FADE_IN = 100; 660cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 670cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public static final int DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS = 300; 680cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public static final int DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS = 300; 692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 70245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell private static final Property<View, Integer> VIEW_LAYOUT_HEIGHT_PROPERTY = 71245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell new Property<View, Integer>(Integer.class, "height") { 72245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell @Override 73245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public void set(View view, Integer height) { 74245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) 75245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell view.getLayoutParams(); 76245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell params.height = height; 77245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell view.setLayoutParams(params); 78245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 79245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 80245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell @Override 81245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public Integer get(View view) { 82245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell return view.getLayoutParams().height; 83245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 84245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell }; 85245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Entry data. 882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public static final class Entry { 902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 912ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos private final int mId; 922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final Drawable mIcon; 932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final String mHeader; 942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final String mSubHeader; 952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final Drawable mSubHeaderIcon; 962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final String mText; 972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final Drawable mTextIcon; 987ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang private Spannable mPrimaryContentDescription; 992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final Intent mIntent; 100dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos private final Drawable mAlternateIcon; 101dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos private final Intent mAlternateIntent; 102dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos private final String mAlternateContentDescription; 10348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos private final boolean mShouldApplyColor; 1042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final boolean mIsEditable; 1052a4207fb39330e840436215c896cde911489e111Paul Soulos private final EntryContextMenuInfo mEntryContextMenuInfo; 10648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final Drawable mThirdIcon; 10748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final Intent mThirdIntent; 10848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final String mThirdContentDescription; 10948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos private final int mIconResourceId; 1102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1112ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos public Entry(int id, Drawable mainIcon, String header, String subHeader, 11223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos Drawable subHeaderIcon, String text, Drawable textIcon, 1137ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang Spannable primaryContentDescription, Intent intent, 114dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription, 1152a4207fb39330e840436215c896cde911489e111Paul Soulos boolean shouldApplyColor, boolean isEditable, 11648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos EntryContextMenuInfo entryContextMenuInfo, Drawable thirdIcon, Intent thirdIntent, 11748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos String thirdContentDescription, int iconResourceId) { 1182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos mId = id; 1192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mIcon = mainIcon; 1202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mHeader = header; 1212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mSubHeader = subHeader; 1222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mSubHeaderIcon = subHeaderIcon; 1232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mText = text; 1242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mTextIcon = textIcon; 12523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos mPrimaryContentDescription = primaryContentDescription; 1262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mIntent = intent; 127dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos mAlternateIcon = alternateIcon; 128dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos mAlternateIntent = alternateIntent; 129dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos mAlternateContentDescription = alternateContentDescription; 13048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos mShouldApplyColor = shouldApplyColor; 1312d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mIsEditable = isEditable; 1322a4207fb39330e840436215c896cde911489e111Paul Soulos mEntryContextMenuInfo = entryContextMenuInfo; 13348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mThirdIcon = thirdIcon; 13448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mThirdIntent = thirdIntent; 13548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mThirdContentDescription = thirdContentDescription; 13648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos mIconResourceId = iconResourceId; 1372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Drawable getIcon() { 1402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mIcon; 1412d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1432d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos String getHeader() { 1442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mHeader; 1452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos String getSubHeader() { 1482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mSubHeader; 1492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Drawable getSubHeaderIcon() { 1522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mSubHeaderIcon; 1532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public String getText() { 1562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mText; 1572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Drawable getTextIcon() { 1602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mTextIcon; 1612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 1637ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang Spannable getPrimaryContentDescription() { 16423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return mPrimaryContentDescription; 16523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 16623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos 1672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Intent getIntent() { 1682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mIntent; 1692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 1702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 171dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable getAlternateIcon() { 172dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return mAlternateIcon; 173dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 174dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 175dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Intent getAlternateIntent() { 176dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return mAlternateIntent; 177dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 178dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 179dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos String getAlternateContentDescription() { 180dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return mAlternateContentDescription; 181dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 182dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 18348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos boolean shouldApplyColor() { 18448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos return mShouldApplyColor; 18548ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos } 18648ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos 1872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos boolean isEditable() { 1882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mIsEditable; 1892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 190ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 1912ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos int getId() { 1922ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos return mId; 193ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 1942a4207fb39330e840436215c896cde911489e111Paul Soulos 1952a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo getEntryContextMenuInfo() { 1962a4207fb39330e840436215c896cde911489e111Paul Soulos return mEntryContextMenuInfo; 1972a4207fb39330e840436215c896cde911489e111Paul Soulos } 19848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 19948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Drawable getThirdIcon() { 20048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mThirdIcon; 20148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 20248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 20348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Intent getThirdIntent() { 20448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mThirdIntent; 20548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 20648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 20748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos String getThirdContentDescription() { 20848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mThirdContentDescription; 20948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 21048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos 21148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos int getIconResourceId() { 21248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos return mIconResourceId; 21348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos } 2142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 216e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell public interface ExpandingEntryCardViewListener { 217e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell void onCollapse(int heightDelta); 218245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell void onExpand(); 219245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell void onExpandDone(); 220e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell } 221e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell 2222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private View mExpandCollapseButton; 2232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private TextView mExpandCollapseTextView; 2242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private TextView mTitleTextView; 2252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private CharSequence mExpandButtonText; 2262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private CharSequence mCollapseButtonText; 2272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private OnClickListener mOnClickListener; 2282a4207fb39330e840436215c896cde911489e111Paul Soulos private OnCreateContextMenuListener mOnCreateContextMenuListener; 2292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private boolean mIsExpanded = false; 230691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos /** 231691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos * The max number of entries to show in a collapsed card. If there are less entries passed in, 232691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos * then they are all shown. 233691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos */ 2342d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private int mCollapsedEntriesCount; 235e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell private ExpandingEntryCardViewListener mListener; 23660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private List<List<Entry>> mEntries; 23760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private int mNumEntries = 0; 23860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private boolean mAllEntriesInflated = false; 23960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private List<List<View>> mEntryViews; 2402d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private LinearLayout mEntriesViewGroup; 241c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos private final ImageView mExpandCollapseArrow; 2422d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private int mThemeColor; 2437b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos private ColorFilter mThemeColorFilter; 24405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell /** 24505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell * Whether to prioritize the first entry type. If prioritized, we should show at least two 24605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell * of this entry type. 24705287bf0cea303b93802a629aa883fb6322ca342Brian Attwell */ 24805287bf0cea303b93802a629aa883fb6322ca342Brian Attwell private boolean mShowFirstEntryTypeTwice; 24989966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos private boolean mIsAlwaysExpanded; 2500cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos /** The ViewGroup to run the expand/collapse animation on */ 2510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos private ViewGroup mAnimationViewGroup; 2526b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos private LinearLayout mBadgeContainer; 2536b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos private final List<ImageView> mBadges; 25448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos private final List<Integer> mBadgeIds; 25505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell private final int mDividerLineHeightPixels; 256cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /** 257cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos * List to hold the separators. This saves us from reconstructing every expand/collapse and 258cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos * provides a smoother animation. 259cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos */ 260cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos private List<View> mSeparators; 261ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos private LinearLayout mContainer; 2622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 2632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private final OnClickListener mExpandCollapseButtonListener = new OnClickListener() { 2642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 2652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 2662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (mIsExpanded) { 2672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos collapse(); 2682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 2692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos expand(); 2702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 2732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 2742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public ExpandingEntryCardView(Context context) { 2750d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell this(context, null); 2762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 2782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public ExpandingEntryCardView(Context context, AttributeSet attrs) { 2792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos super(context, attrs); 2802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos LayoutInflater inflater = LayoutInflater.from(context); 2812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos View expandingEntryCardView = inflater.inflate(R.layout.expanding_entry_card_view, this); 2822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mEntriesViewGroup = (LinearLayout) 2832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos expandingEntryCardView.findViewById(R.id.content_area_linear_layout); 2842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mTitleTextView = (TextView) expandingEntryCardView.findViewById(R.id.title); 285ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos mContainer = (LinearLayout) expandingEntryCardView.findViewById(R.id.container); 2867b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 2877b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mExpandCollapseButton = inflater.inflate( 2887b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos R.layout.quickcontact_expanding_entry_card_button, this, false); 2897b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mExpandCollapseTextView = (TextView) mExpandCollapseButton.findViewById(R.id.text); 290c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos mExpandCollapseArrow = (ImageView) mExpandCollapseButton.findViewById(R.id.arrow); 2917b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mExpandCollapseButton.setOnClickListener(mExpandCollapseButtonListener); 2926b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadgeContainer = (LinearLayout) mExpandCollapseButton.findViewById(R.id.badge_container); 29305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell mDividerLineHeightPixels = getResources() 29405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell .getDimensionPixelSize(R.dimen.divider_line_height); 2957b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 2966b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadges = new ArrayList<ImageView>(); 29748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos mBadgeIds = new ArrayList<Integer>(); 2982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 2992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 30005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries, 30105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell boolean isExpanded, boolean isAlwaysExpanded, ExpandingEntryCardViewListener listener, 30205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell ViewGroup animationViewGroup) { 30305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell initialize(entries, numInitialVisibleEntries, isExpanded, isAlwaysExpanded, 30405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell listener, animationViewGroup, /* showFirstEntryTypeTwice = */ false); 30505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } 30605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell 3072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 3082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Sets the Entry list to display. 3092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * 3102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @param entries The Entry list to display. 3112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 31260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos public void initialize(List<List<Entry>> entries, int numInitialVisibleEntries, 31389966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos boolean isExpanded, boolean isAlwaysExpanded, 31405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell ExpandingEntryCardViewListener listener, ViewGroup animationViewGroup, 31505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell boolean showFirstEntryTypeTwice) { 3162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos LayoutInflater layoutInflater = LayoutInflater.from(getContext()); 3172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mIsExpanded = isExpanded; 31889966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos mIsAlwaysExpanded = isAlwaysExpanded; 31989966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos // If isAlwaysExpanded is true, mIsExpanded should be true 32089966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos mIsExpanded |= mIsAlwaysExpanded; 32160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos mEntryViews = new ArrayList<List<View>>(entries.size()); 3220d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell mEntries = entries; 3236095369885edcca566a812b551886e29c7ff8039Brian Attwell mNumEntries = 0; 3246095369885edcca566a812b551886e29c7ff8039Brian Attwell mAllEntriesInflated = false; 32505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell mShowFirstEntryTypeTwice = showFirstEntryTypeTwice; 32660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (List<Entry> entryList : mEntries) { 32760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos mNumEntries += entryList.size(); 32860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos mEntryViews.add(new ArrayList<View>()); 32960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 33060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries); 331cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos // We need a separator between each list, but not after the last one 332cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (entries.size() > 1) { 333cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mSeparators = new ArrayList<>(entries.size() - 1); 334cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 335e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell mListener = listener; 3360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mAnimationViewGroup = animationViewGroup; 3370d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell 3387b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos if (mIsExpanded) { 339c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos updateExpandCollapseButton(getCollapseButtonText(), /* duration = */ 0); 34060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos inflateAllEntries(layoutInflater); 3417b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } else { 342c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos updateExpandCollapseButton(getExpandButtonText(), /* duration = */ 0); 34360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos inflateInitialEntries(layoutInflater); 3442d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos insertEntriesIntoViewGroup(); 3467b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos applyColor(); 3472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 3492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 3502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Sets the text for the expand button. 3512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * 3522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @param expandButtonText The expand button text. 3532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 3542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void setExpandButtonText(CharSequence expandButtonText) { 3552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mExpandButtonText = expandButtonText; 3562d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (mExpandCollapseTextView != null && !mIsExpanded) { 3572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mExpandCollapseTextView.setText(expandButtonText); 3582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 3612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 3622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Sets the text for the expand button. 3632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * 3642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * @param expandButtonText The expand button text. 3652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 3662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void setCollapseButtonText(CharSequence expandButtonText) { 3672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mCollapseButtonText = expandButtonText; 3682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (mExpandCollapseTextView != null && mIsExpanded) { 3692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mExpandCollapseTextView.setText(mCollapseButtonText); 3702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 3732d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 3742d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void setOnClickListener(OnClickListener listener) { 3752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mOnClickListener = listener; 3762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 3782a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 3792a4207fb39330e840436215c896cde911489e111Paul Soulos public void setOnCreateContextMenuListener (OnCreateContextMenuListener listener) { 3802a4207fb39330e840436215c896cde911489e111Paul Soulos mOnCreateContextMenuListener = listener; 3812a4207fb39330e840436215c896cde911489e111Paul Soulos } 3822a4207fb39330e840436215c896cde911489e111Paul Soulos 383245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell private List<View> calculateEntriesToRemoveDuringCollapse() { 384245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final List<View> viewsToRemove = getViewsToDisplay(true); 385245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final List<View> viewsCollapsed = getViewsToDisplay(false); 386245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToRemove.removeAll(viewsCollapsed); 387245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell return viewsToRemove; 388245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 389245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 3902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private void insertEntriesIntoViewGroup() { 3912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mEntriesViewGroup.removeAllViews(); 39260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos 393245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell for (View view : getViewsToDisplay(mIsExpanded)) { 394245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mEntriesViewGroup.addView(view); 395245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 396245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 397245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell removeView(mExpandCollapseButton); 398245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell if (mCollapsedEntriesCount < mNumEntries 399245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell && mExpandCollapseButton.getParent() == null && !mIsAlwaysExpanded) { 400245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mContainer.addView(mExpandCollapseButton, -1); 401245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 402245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 403245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 404245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell /** 405245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell * Returns the list of views that should be displayed. This changes depending on whether 406245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell * the card is expanded or collapsed. 407245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell */ 408245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell private List<View> getViewsToDisplay(boolean isExpanded) { 409245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final List<View> viewsToDisplay = new ArrayList<View>(); 410245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell if (isExpanded) { 411cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos for (int i = 0; i < mEntryViews.size(); i++) { 412cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos List<View> viewList = mEntryViews.get(i); 413cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (i > 0) { 414cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos View separator; 415cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (mSeparators.size() <= i - 1) { 416cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos separator = generateSeparator(viewList.get(0)); 417cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mSeparators.add(separator); 418cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } else { 419cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos separator = mSeparators.get(i - 1); 420cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 421245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToDisplay.add(separator); 42297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos } 42360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (View view : viewList) { 424245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToDisplay.add(view); 42560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 42660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 42760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } else { 428691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // We want to insert mCollapsedEntriesCount entries into the group. extraEntries is the 429691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // number of entries that need to be added that are not the head element of a list 430691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // to reach mCollapsedEntriesCount. 431691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos int numInViewGroup = 0; 432691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos int extraEntries = mCollapsedEntriesCount - mEntryViews.size(); 433691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos for (int i = 0; i < mEntryViews.size() && numInViewGroup < mCollapsedEntriesCount; 434691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos i++) { 435691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos List<View> entryViewList = mEntryViews.get(i); 43697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos if (i > 0) { 437cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos View separator; 438cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (mSeparators.size() <= i - 1) { 439cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos separator = generateSeparator(entryViewList.get(0)); 440cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mSeparators.add(separator); 441cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } else { 442cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos separator = mSeparators.get(i - 1); 443cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 444245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToDisplay.add(separator); 445691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos } 446245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToDisplay.add(entryViewList.get(0)); 447691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos numInViewGroup++; 44805287bf0cea303b93802a629aa883fb6322ca342Brian Attwell 44905287bf0cea303b93802a629aa883fb6322ca342Brian Attwell int indexInEntryViewList = 1; 45005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell if (mShowFirstEntryTypeTwice && i == 0 && entryViewList.size() > 1) { 45105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell viewsToDisplay.add(entryViewList.get(1)); 45205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell numInViewGroup++; 45305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell extraEntries--; 45405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell indexInEntryViewList++; 45505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } 45605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell 457691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // Insert entries in this list to hit mCollapsedEntriesCount. 45805287bf0cea303b93802a629aa883fb6322ca342Brian Attwell for (int j = indexInEntryViewList; 459691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos j < entryViewList.size() && numInViewGroup < mCollapsedEntriesCount && 460691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos extraEntries > 0; 461691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos j++) { 462245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewsToDisplay.add(entryViewList.get(j)); 463691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos numInViewGroup++; 464691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos extraEntries--; 46597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos } 4662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 4672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 4682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 469245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell formatEntryIfFirst(viewsToDisplay); 470245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell return viewsToDisplay; 4712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 4722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 473245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell private void formatEntryIfFirst(List<View> entriesViewGroup) { 4741321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos // If no title and the first entry in the group, add extra padding 4751321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos if (TextUtils.isEmpty(mTitleTextView.getText()) && 476245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell entriesViewGroup.size() > 0) { 477245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final View entry = entriesViewGroup.get(0); 4781321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos entry.setPadding(entry.getPaddingLeft(), 479568d5d82610f87a5e733690e57075f0a99551972Paul Soulos getResources().getDimensionPixelSize( 480568d5d82610f87a5e733690e57075f0a99551972Paul Soulos R.dimen.expanding_entry_card_item_padding_top) + 481568d5d82610f87a5e733690e57075f0a99551972Paul Soulos getResources().getDimensionPixelSize( 4821321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos R.dimen.expanding_entry_card_null_title_top_extra_padding), 4831321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos entry.getPaddingRight(), 4841321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos entry.getPaddingBottom()); 4851321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos } 4862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 4872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 488cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos private View generateSeparator(View entry) { 4890cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos View separator = new View(getContext()); 490ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos Resources res = getResources(); 491ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos 492ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos separator.setBackgroundColor(res.getColor( 493daa2058979fda84a0ce22e21edd53aa049e80aa0Brian Attwell R.color.divider_line_color_light)); 494ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 49505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell ViewGroup.LayoutParams.MATCH_PARENT, mDividerLineHeightPixels); 4960cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos // The separator is aligned with the text in the entry. This is offset by a default 4970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos // margin. If there is an icon present, the icon's width and margin are added 498ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos int marginStart = res.getDimensionPixelSize( 4990cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos R.dimen.expanding_entry_card_item_padding_start); 5000cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos ImageView entryIcon = (ImageView) entry.findViewById(R.id.icon); 50197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos if (entryIcon.getVisibility() == View.VISIBLE) { 5020cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos int imageWidthAndMargin = 503ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_icon_width) + 504ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos res.getDimensionPixelSize(R.dimen.expanding_entry_card_item_image_spacing); 5050cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos marginStart += imageWidthAndMargin; 5060cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 50797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos layoutParams.setMarginStart(marginStart); 5080cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos separator.setLayoutParams(layoutParams); 509cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos return separator; 5100cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 5110cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 5122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private CharSequence getExpandButtonText() { 5132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (!TextUtils.isEmpty(mExpandButtonText)) { 5142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mExpandButtonText; 5152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 5162d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos // Default to "See more". 5172d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return getResources().getText(R.string.expanding_entry_card_view_see_more); 5182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5202d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 5212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private CharSequence getCollapseButtonText() { 5222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (!TextUtils.isEmpty(mCollapseButtonText)) { 5232d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mCollapseButtonText; 5242d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 5252d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos // Default to "See less". 5262d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return getResources().getText(R.string.expanding_entry_card_view_see_less); 5272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5292d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 5300d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell /** 53160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos * Inflates the initial entries to be shown. 5320d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell */ 53360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private void inflateInitialEntries(LayoutInflater layoutInflater) { 53460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos // If the number of collapsed entries equals total entries, inflate all 53560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos if (mCollapsedEntriesCount == mNumEntries) { 53660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos inflateAllEntries(layoutInflater); 53760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } else { 53860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos // Otherwise inflate the top entry from each list 539691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // extraEntries is used to add extra entries until mCollapsedEntriesCount is reached. 540691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos int numInflated = 0; 541691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos int extraEntries = mCollapsedEntriesCount - mEntries.size(); 542691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos for (int i = 0; i < mEntries.size() && numInflated < mCollapsedEntriesCount; i++) { 543691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos List<Entry> entryList = mEntries.get(i); 544691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos List<View> entryViewList = mEntryViews.get(i); 545691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos 546691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos entryViewList.add(createEntryView(layoutInflater, entryList.get(0), 54797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos /* showIcon = */ View.VISIBLE)); 548691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos numInflated++; 54905287bf0cea303b93802a629aa883fb6322ca342Brian Attwell 55005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell int indexInEntryViewList = 1; 55105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell if (mShowFirstEntryTypeTwice && i == 0 && entryList.size() > 1) { 55205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell entryViewList.add(createEntryView(layoutInflater, entryList.get(1), 55305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell /* showIcon = */ View.INVISIBLE)); 55405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell numInflated++; 55505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell extraEntries--; 55605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell indexInEntryViewList++; 55705287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } 55805287bf0cea303b93802a629aa883fb6322ca342Brian Attwell 559691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos // Inflate entries in this list to hit mCollapsedEntriesCount. 56005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell for (int j = indexInEntryViewList; j < entryList.size() 56105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell && numInflated < mCollapsedEntriesCount 56205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell && extraEntries > 0; j++) { 563691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos entryViewList.add(createEntryView(layoutInflater, entryList.get(j), 56443e0dead719568ed610f9f111f6e7614368445efPaul Soulos /* showIcon = */ View.INVISIBLE)); 565691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos numInflated++; 566691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos extraEntries--; 567691dd8fc7ce4b330cb6341f8e54fa6703564bd3ePaul Soulos } 56860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 56960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 57060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 57160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos 57260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos /** 57360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos * Inflates all entries. 57460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos */ 57560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos private void inflateAllEntries(LayoutInflater layoutInflater) { 57660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos if (mAllEntriesInflated) { 57760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos return; 57860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 57960e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (int i = 0; i < mEntries.size(); i++) { 58060e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos List<Entry> entryList = mEntries.get(i); 58160e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos List<View> viewList = mEntryViews.get(i); 58260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (int j = viewList.size(); j < entryList.size(); j++) { 58397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos final int iconVisibility; 58497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos final Entry entry = entryList.get(j); 58597ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos // If the entry does not have an icon, mark gone. Else if it has an icon, show 58697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos // for the first Entry in the list only 58797ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos if (entry.getIcon() == null) { 58897ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos iconVisibility = View.GONE; 58997ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos } else if (j == 0) { 59097ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos iconVisibility = View.VISIBLE; 59197ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos } else { 59297ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos iconVisibility = View.INVISIBLE; 59397ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos } 59497ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos viewList.add(createEntryView(layoutInflater, entry, iconVisibility)); 59560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 5962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 59760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos mAllEntriesInflated = true; 5982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 5992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 6007b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos public void setColorAndFilter(int color, ColorFilter colorFilter) { 6017b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mThemeColor = color; 6027b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mThemeColorFilter = colorFilter; 6037b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos applyColor(); 6047b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6057b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 6066095369885edcca566a812b551886e29c7ff8039Brian Attwell public void setEntryHeaderColor(int color) { 6076095369885edcca566a812b551886e29c7ff8039Brian Attwell if (mEntries != null) { 6086095369885edcca566a812b551886e29c7ff8039Brian Attwell for (List<View> entryList : mEntryViews) { 6096095369885edcca566a812b551886e29c7ff8039Brian Attwell for (View entryView : entryList) { 6106095369885edcca566a812b551886e29c7ff8039Brian Attwell TextView header = (TextView) entryView.findViewById(R.id.header); 6116095369885edcca566a812b551886e29c7ff8039Brian Attwell if (header != null) { 6126095369885edcca566a812b551886e29c7ff8039Brian Attwell header.setTextColor(color); 6136095369885edcca566a812b551886e29c7ff8039Brian Attwell } 6146095369885edcca566a812b551886e29c7ff8039Brian Attwell } 6156095369885edcca566a812b551886e29c7ff8039Brian Attwell } 6166095369885edcca566a812b551886e29c7ff8039Brian Attwell } 6176095369885edcca566a812b551886e29c7ff8039Brian Attwell } 6186095369885edcca566a812b551886e29c7ff8039Brian Attwell 6197b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos /** 6207b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * The ColorFilter is passed in along with the color so that a new one only needs to be created 6217b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * once for the entire activity. 6227b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * 1. Title 6237b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * 2. Entry icons 6247b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * 3. Expand/Collapse Text 6257b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos * 4. Expand/Collapse Button 6267b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos */ 6277b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos public void applyColor() { 6287b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos if (mThemeColor != 0 && mThemeColorFilter != null) { 6297b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos // Title 6307b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos if (mTitleTextView != null) { 6317b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mTitleTextView.setTextColor(mThemeColor); 6327b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6337b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 6347b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos // Entry icons 6357b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos if (mEntries != null) { 63660e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (List<Entry> entryList : mEntries) { 63760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos for (Entry entry : entryList) { 63848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos if (entry.shouldApplyColor()) { 63948ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos Drawable icon = entry.getIcon(); 64048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos if (icon != null) { 6410da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell icon.mutate(); 64248ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos icon.setColorFilter(mThemeColorFilter); 64348ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos } 64460e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos } 645dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable alternateIcon = entry.getAlternateIcon(); 646dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (alternateIcon != null) { 6470da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell alternateIcon.mutate(); 648dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIcon.setColorFilter(mThemeColorFilter); 649dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 65048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Drawable thirdIcon = entry.getThirdIcon(); 65148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (thirdIcon != null) { 6520da93008e49306e99a90b114b7f8a60c78774fc3Brian Attwell thirdIcon.mutate(); 65348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setColorFilter(mThemeColorFilter); 65448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 655eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 6567b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6577b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6587b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 6597b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos // Expand/Collapse 6607b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos mExpandCollapseTextView.setTextColor(mThemeColor); 661c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos mExpandCollapseArrow.setColorFilter(mThemeColorFilter); 6627b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6637b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos } 6647b0b0ce616c6c2fa149918c112128388712f5657Paul Soulos 6652a4207fb39330e840436215c896cde911489e111Paul Soulos private View createEntryView(LayoutInflater layoutInflater, final Entry entry, 6662a4207fb39330e840436215c896cde911489e111Paul Soulos int iconVisibility) { 6672a4207fb39330e840436215c896cde911489e111Paul Soulos final EntryView view = (EntryView) layoutInflater.inflate( 6682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos R.layout.expanding_entry_card_item, this, false); 6692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 6702a4207fb39330e840436215c896cde911489e111Paul Soulos view.setContextMenuInfo(entry.getEntryContextMenuInfo()); 67123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos if (!TextUtils.isEmpty(entry.getPrimaryContentDescription())) { 67223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos view.setContentDescription(entry.getPrimaryContentDescription()); 67323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 674ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 675dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final ImageView icon = (ImageView) view.findViewById(R.id.icon); 67697ed5019d75bd6afdfd5f3a8150161d9d9441275Paul Soulos icon.setVisibility(iconVisibility); 677eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (entry.getIcon() != null) { 678eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos icon.setImageDrawable(entry.getIcon()); 679eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 680dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final TextView header = (TextView) view.findViewById(R.id.header); 68103ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos if (!TextUtils.isEmpty(entry.getHeader())) { 6822d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos header.setText(entry.getHeader()); 6832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 6842d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos header.setVisibility(View.GONE); 6852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 6862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 687dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final TextView subHeader = (TextView) view.findViewById(R.id.sub_header); 68803ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos if (!TextUtils.isEmpty(entry.getSubHeader())) { 6892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos subHeader.setText(entry.getSubHeader()); 6902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 6912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos subHeader.setVisibility(View.GONE); 6922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 6932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 694dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final ImageView subHeaderIcon = (ImageView) view.findViewById(R.id.icon_sub_header); 6952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (entry.getSubHeaderIcon() != null) { 6962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos subHeaderIcon.setImageDrawable(entry.getSubHeaderIcon()); 6972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 6982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos subHeaderIcon.setVisibility(View.GONE); 6992d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7002d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 701dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final TextView text = (TextView) view.findViewById(R.id.text); 70203ece86bc2bda7f29aa2f8f2111035e4c6c6b871Paul Soulos if (!TextUtils.isEmpty(entry.getText())) { 7032d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos text.setText(entry.getText()); 7042d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 7052d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos text.setVisibility(View.GONE); 7062d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 708dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final ImageView textIcon = (ImageView) view.findViewById(R.id.icon_text); 7092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (entry.getTextIcon() != null) { 7102d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos textIcon.setImageDrawable(entry.getTextIcon()); 7112d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 7122d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos textIcon.setVisibility(View.GONE); 7132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 7152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (entry.getIntent() != null) { 7167d22b94ce50f7a65dd89d4533f2aa3a3392e7972Paul Soulos view.setOnClickListener(mOnClickListener); 7172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos view.setTag(new EntryTag(entry.getId(), entry.getIntent())); 7182d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7192d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 720a42ef76251778161d27bc07db214b8c81720e476Paul Soulos if (entry.getIntent() == null && entry.getEntryContextMenuInfo() == null) { 721a42ef76251778161d27bc07db214b8c81720e476Paul Soulos // Remove the click effect 722a42ef76251778161d27bc07db214b8c81720e476Paul Soulos view.setBackground(null); 723a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 724a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 725ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos // If only the header is visible, add a top margin to match icon's top margin. 726ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos // Also increase the space below the header for visual comfort. 7274b943553afdb7286b33e4bc2481431e816c57967Paul Soulos if (header.getVisibility() == View.VISIBLE && subHeader.getVisibility() == View.GONE && 7284b943553afdb7286b33e4bc2481431e816c57967Paul Soulos text.getVisibility() == View.GONE) { 7294b943553afdb7286b33e4bc2481431e816c57967Paul Soulos RelativeLayout.LayoutParams headerLayoutParams = 7304b943553afdb7286b33e4bc2481431e816c57967Paul Soulos (RelativeLayout.LayoutParams) header.getLayoutParams(); 7314b943553afdb7286b33e4bc2481431e816c57967Paul Soulos headerLayoutParams.topMargin = (int) (getResources().getDimension( 732ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos R.dimen.expanding_entry_card_item_header_only_margin_top)); 733ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos headerLayoutParams.bottomMargin += (int) (getResources().getDimension( 734ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos R.dimen.expanding_entry_card_item_header_only_margin_bottom)); 7354b943553afdb7286b33e4bc2481431e816c57967Paul Soulos header.setLayoutParams(headerLayoutParams); 7364b943553afdb7286b33e4bc2481431e816c57967Paul Soulos } 7374b943553afdb7286b33e4bc2481431e816c57967Paul Soulos 738edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos // Adjust the top padding size for entries with an invisible icon. The padding depends on 739edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos // if there is a sub header or text section 740edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos if (iconVisibility == View.INVISIBLE && 741edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos (!TextUtils.isEmpty(entry.getSubHeader()) || !TextUtils.isEmpty(entry.getText()))) { 742edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos view.setPaddingRelative(view.getPaddingStart(), 743edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos getResources().getDimensionPixelSize( 744edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos R.dimen.expanding_entry_card_item_no_icon_margin_top), 745edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos view.getPaddingEnd(), 746edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos view.getPaddingBottom()); 747edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos } else if (iconVisibility == View.INVISIBLE && TextUtils.isEmpty(entry.getSubHeader()) 748edd44f03e0e7aa57d4eb721147d4a3f3d2551c1aPaul Soulos && TextUtils.isEmpty(entry.getText())) { 749ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos view.setPaddingRelative(view.getPaddingStart(), 0, view.getPaddingEnd(), 750ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos view.getPaddingBottom()); 751ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos } 752ac9b31665c157e6aa7bce487a5467e8abd8224d5Paul Soulos 75348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos final ImageView alternateIcon = (ImageView) view.findViewById(R.id.icon_alternate); 75448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos final ImageView thirdIcon = (ImageView) view.findViewById(R.id.third_icon); 75548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 75648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) { 75748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos alternateIcon.setImageDrawable(entry.getAlternateIcon()); 75848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos alternateIcon.setOnClickListener(mOnClickListener); 75948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent())); 76048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos alternateIcon.setVisibility(View.VISIBLE); 76148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos alternateIcon.setContentDescription(entry.getAlternateContentDescription()); 76248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 76348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 76448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (entry.getThirdIcon() != null && entry.getThirdIntent() != null) { 76548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setImageDrawable(entry.getThirdIcon()); 76648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setOnClickListener(mOnClickListener); 76748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setTag(new EntryTag(entry.getId(), entry.getThirdIntent())); 76848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setVisibility(View.VISIBLE); 76948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIcon.setContentDescription(entry.getThirdContentDescription()); 77048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 77148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 77248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // Set a custom touch listener for expanding the extra icon touch areas 77348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos view.setOnTouchListener(new EntryTouchListener(view, alternateIcon, thirdIcon)); 7742a4207fb39330e840436215c896cde911489e111Paul Soulos view.setOnCreateContextMenuListener(mOnCreateContextMenuListener); 7752a4207fb39330e840436215c896cde911489e111Paul Soulos 7762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return view; 7772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7782d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 779c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos private void updateExpandCollapseButton(CharSequence buttonText, long duration) { 780c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos if (mIsExpanded) { 781c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow, 782c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos "rotation", 180); 783c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos animator.setDuration(duration); 784c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos animator.start(); 7852d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } else { 786c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos final ObjectAnimator animator = ObjectAnimator.ofFloat(mExpandCollapseArrow, 787c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos "rotation", 0); 788c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos animator.setDuration(duration); 789c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos animator.start(); 7902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 791c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos updateBadges(); 792c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos 7932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mExpandCollapseTextView.setText(buttonText); 7942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 7952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 7966b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos private void updateBadges() { 7976b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos if (mIsExpanded) { 7986b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadgeContainer.removeAllViews(); 7996b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } else { 80005287bf0cea303b93802a629aa883fb6322ca342Brian Attwell int numberOfMimeTypesShown = mCollapsedEntriesCount; 80105287bf0cea303b93802a629aa883fb6322ca342Brian Attwell if (mShowFirstEntryTypeTwice && mEntries.size() > 0 80205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell && mEntries.get(0).size() > 1) { 80305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell numberOfMimeTypesShown--; 80405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } 8056b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos // Inflate badges if not yet created 80605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell if (mBadges.size() < mEntries.size() - numberOfMimeTypesShown) { 80705287bf0cea303b93802a629aa883fb6322ca342Brian Attwell for (int i = numberOfMimeTypesShown; i < mEntries.size(); i++) { 8086b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos Drawable badgeDrawable = mEntries.get(i).get(0).getIcon(); 80948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos int badgeResourceId = mEntries.get(i).get(0).getIconResourceId(); 81048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos // Do not add the same badge twice 81148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos if (badgeResourceId != 0 && mBadgeIds.contains(badgeResourceId)) { 81248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos continue; 81348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos } 8146b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos if (badgeDrawable != null) { 8156b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos ImageView badgeView = new ImageView(getContext()); 8166b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos LinearLayout.LayoutParams badgeViewParams = new LinearLayout.LayoutParams( 8176b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos (int) getResources().getDimension( 8186b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos R.dimen.expanding_entry_card_item_icon_width), 8196b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos (int) getResources().getDimension( 8206b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos R.dimen.expanding_entry_card_item_icon_height)); 8216b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos badgeViewParams.setMarginEnd((int) getResources().getDimension( 8226b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos R.dimen.expanding_entry_card_badge_separator_margin)); 8236b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos badgeView.setLayoutParams(badgeViewParams); 8246b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos badgeView.setImageDrawable(badgeDrawable); 8256b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadges.add(badgeView); 82648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos mBadgeIds.add(badgeResourceId); 8276b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8286b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8296b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8306b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadgeContainer.removeAllViews(); 8316b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos for (ImageView badge : mBadges) { 8326b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos mBadgeContainer.addView(badge); 8336b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8346b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8356b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos } 8366b6328915d66f0c5947badc3d1973c31f29eef62Paul Soulos 8372d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private void expand() { 8380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos ChangeBounds boundsTransition = new ChangeBounds(); 8390cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos boundsTransition.setDuration(DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS); 8400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8410cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos Fade fadeIn = new Fade(Fade.IN); 8420cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos fadeIn.setDuration(DURATION_EXPAND_ANIMATION_FADE_IN); 8430cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos fadeIn.setStartDelay(DELAY_EXPAND_ANIMATION_FADE_IN); 8440cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8450cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos TransitionSet transitionSet = new TransitionSet(); 8460cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos transitionSet.addTransition(boundsTransition); 8470cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos transitionSet.addTransition(fadeIn); 8480cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8494cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos transitionSet.excludeTarget(R.id.text, /* exclude = */ true); 8504cd9ed68dca5f4adeb8ec2065526c18f33af5926Paul Soulos 8510cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos final ViewGroup transitionViewContainer = mAnimationViewGroup == null ? 8520cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos this : mAnimationViewGroup; 8530cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8540cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos transitionSet.addListener(new TransitionListener() { 8550cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 8560cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onTransitionStart(Transition transition) { 857245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mListener.onExpand(); 8580cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 8590cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8600cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 8610cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onTransitionEnd(Transition transition) { 862245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mListener.onExpandDone(); 8630cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 8640cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8650cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 8660cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onTransitionCancel(Transition transition) { 8670cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 8680cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8690cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 8700cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onTransitionPause(Transition transition) { 8710cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 8720cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8730cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 8740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onTransitionResume(Transition transition) { 8750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 8760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos }); 8770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 8780cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos TransitionManager.beginDelayedTransition(transitionViewContainer, transitionSet); 8792d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 8802d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mIsExpanded = true; 8810d49d81a3df2eea40dfe57570767c7661463f2dcBrian Attwell // In order to insert new entries, we may need to inflate them for the first time 88260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos inflateAllEntries(LayoutInflater.from(getContext())); 8832d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos insertEntriesIntoViewGroup(); 884c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos updateExpandCollapseButton(getCollapseButtonText(), 885c205cf1d4db6a85f52175af0add8852d5e1f8605Paul Soulos DURATION_EXPAND_ANIMATION_CHANGE_BOUNDS); 8862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 8872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 8882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos private void collapse() { 889245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final List<View> views = calculateEntriesToRemoveDuringCollapse(); 890245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell 891245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // This animation requires layout changes, unlike the expand() animation: the action bar 892245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // might get scrolled open in order to fill empty space. As a result, we can't use 893245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // ChangeBounds here. Instead manually animate view height and alpha. This isn't as 894245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // efficient as the bounds and translation changes performed by ChangeBounds. Nonetheless, a 895245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // reasonable frame-rate is achieved collapsing a dozen elements on a user Svelte N4. So the 896245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // performance hit doesn't justify writing a less maintainable animation. 897245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final AnimatorSet set = new AnimatorSet(); 898245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final List<Animator> animators = new ArrayList<Animator>(views.size()); 899245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell int totalSizeChange = 0; 900245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell for (View viewToRemove : views) { 901245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell final ObjectAnimator animator = ObjectAnimator.ofObject(viewToRemove, 902245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell VIEW_LAYOUT_HEIGHT_PROPERTY, null, viewToRemove.getHeight(), 0); 903245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell totalSizeChange += viewToRemove.getHeight(); 904245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell animator.setDuration(DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS); 905245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell animators.add(animator); 906245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell viewToRemove.animate().alpha(0).setDuration(DURATION_COLLAPSE_ANIMATION_FADE_OUT); 907245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 908245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell set.playTogether(animators); 909245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell set.start(); 910245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell set.addListener(new AnimatorListener() { 9110cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 912245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public void onAnimationStart(Animator animation) { 9130cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 9140cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 9152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 916245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public void onAnimationEnd(Animator animation) { 917245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // Now that the views have been animated away, actually remove them from the view 918245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell // hierarchy. Reset their appearance so that they look appropriate when they 91905287bf0cea303b93802a629aa883fb6322ca342Brian Attwell // get added back later. 920245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell insertEntriesIntoViewGroup(); 921245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell for (View view : views) { 92205287bf0cea303b93802a629aa883fb6322ca342Brian Attwell if (view instanceof EntryView) { 92305287bf0cea303b93802a629aa883fb6322ca342Brian Attwell VIEW_LAYOUT_HEIGHT_PROPERTY.set(view, LayoutParams.WRAP_CONTENT); 92405287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } else { 92505287bf0cea303b93802a629aa883fb6322ca342Brian Attwell VIEW_LAYOUT_HEIGHT_PROPERTY.set(view, mDividerLineHeightPixels); 92605287bf0cea303b93802a629aa883fb6322ca342Brian Attwell } 927245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell view.animate().cancel(); 928245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell view.setAlpha(1); 929245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell } 9300cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 9310cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 9320cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 933245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public void onAnimationCancel(Animator animation) { 9340cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 9350cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 9360cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 937245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell public void onAnimationRepeat(Animator animation) { 9382d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 9392d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }); 9400cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 941245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mListener.onCollapse(totalSizeChange); 942245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell mIsExpanded = false; 943245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell updateExpandCollapseButton(getExpandButtonText(), 944245d3d2000150cbb21111370f42addaeeb1b10a0Brian Attwell DURATION_COLLAPSE_ANIMATION_CHANGE_BOUNDS); 9452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 9462d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 9472d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 9482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Returns whether the view is currently in its expanded state. 9492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 9502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public boolean isExpanded() { 9512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return mIsExpanded; 9522d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 9532d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 9542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos /** 9552d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos * Sets the title text of this ExpandingEntryCardView. 9562fa690807a94708384789b211965bfc75b5ac38ePaul Soulos * @param title The title to set. A null title will result in the title being removed. 9572d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos */ 9582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void setTitle(String title) { 9592d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos if (mTitleTextView == null) { 9602d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos Log.e(TAG, "mTitleTextView is null"); 9612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 9622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos mTitleTextView.setText(title); 9631321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos mTitleTextView.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE); 9641321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos findViewById(R.id.title_separator).setVisibility(TextUtils.isEmpty(title) ? 9651321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos View.GONE : View.VISIBLE); 9661321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos // If the title is set after children have been added, reset the top entry's padding to 9671321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos // the default. Else if the title is cleared after children have been added, set 9681321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos // the extra top padding 9691321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) { 9701321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos View firstEntry = mEntriesViewGroup.getChildAt(0); 9711321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos firstEntry.setPadding(firstEntry.getPaddingLeft(), 9721321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos getResources().getDimensionPixelSize( 9731321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos R.dimen.expanding_entry_card_item_padding_top), 9741321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos firstEntry.getPaddingRight(), 9751321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos firstEntry.getPaddingBottom()); 9761321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos } else if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) { 9771321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos View firstEntry = mEntriesViewGroup.getChildAt(0); 9781321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos firstEntry.setPadding(firstEntry.getPaddingLeft(), 9791321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos getResources().getDimensionPixelSize( 9801321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos R.dimen.expanding_entry_card_item_padding_top) + 9811321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos getResources().getDimensionPixelSize( 9821321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos R.dimen.expanding_entry_card_null_title_top_extra_padding), 9831321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos firstEntry.getPaddingRight(), 9848897287c19b394c1f0b402e6291ff4304acacbc2Brian Attwell firstEntry.getPaddingBottom()); 9851321736e0b6f4da580aa77075dd3845c8781f460Paul Soulos } 9862d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 987eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 988eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public boolean shouldShow() { 989eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return mEntries != null && mEntries.size() > 0; 990eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 9912a4207fb39330e840436215c896cde911489e111Paul Soulos 9922a4207fb39330e840436215c896cde911489e111Paul Soulos public static final class EntryView extends RelativeLayout { 9932a4207fb39330e840436215c896cde911489e111Paul Soulos private EntryContextMenuInfo mEntryContextMenuInfo; 9942a4207fb39330e840436215c896cde911489e111Paul Soulos 9952a4207fb39330e840436215c896cde911489e111Paul Soulos public EntryView(Context context) { 9962a4207fb39330e840436215c896cde911489e111Paul Soulos super(context); 9972a4207fb39330e840436215c896cde911489e111Paul Soulos } 9982a4207fb39330e840436215c896cde911489e111Paul Soulos 9992a4207fb39330e840436215c896cde911489e111Paul Soulos public EntryView(Context context, AttributeSet attrs) { 10002a4207fb39330e840436215c896cde911489e111Paul Soulos super(context, attrs); 10012a4207fb39330e840436215c896cde911489e111Paul Soulos } 10022a4207fb39330e840436215c896cde911489e111Paul Soulos 10032a4207fb39330e840436215c896cde911489e111Paul Soulos public void setContextMenuInfo(EntryContextMenuInfo info) { 10042a4207fb39330e840436215c896cde911489e111Paul Soulos mEntryContextMenuInfo = info; 10052a4207fb39330e840436215c896cde911489e111Paul Soulos } 10062a4207fb39330e840436215c896cde911489e111Paul Soulos 10072a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 10082a4207fb39330e840436215c896cde911489e111Paul Soulos protected ContextMenuInfo getContextMenuInfo() { 10092a4207fb39330e840436215c896cde911489e111Paul Soulos return mEntryContextMenuInfo; 10102a4207fb39330e840436215c896cde911489e111Paul Soulos } 10112a4207fb39330e840436215c896cde911489e111Paul Soulos } 10122a4207fb39330e840436215c896cde911489e111Paul Soulos 10132a4207fb39330e840436215c896cde911489e111Paul Soulos public static final class EntryContextMenuInfo implements ContextMenuInfo { 10142a4207fb39330e840436215c896cde911489e111Paul Soulos private final String mCopyText; 10152a4207fb39330e840436215c896cde911489e111Paul Soulos private final String mCopyLabel; 101697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private final String mMimeType; 101797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private final long mId; 101897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private final boolean mIsSuperPrimary; 10192a4207fb39330e840436215c896cde911489e111Paul Soulos 102097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos public EntryContextMenuInfo(String copyText, String copyLabel, String mimeType, long id, 102197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos boolean isSuperPrimary) { 10222a4207fb39330e840436215c896cde911489e111Paul Soulos mCopyText = copyText; 10232a4207fb39330e840436215c896cde911489e111Paul Soulos mCopyLabel = copyLabel; 102497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mMimeType = mimeType; 102597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mId = id; 102697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mIsSuperPrimary = isSuperPrimary; 10272a4207fb39330e840436215c896cde911489e111Paul Soulos } 10282a4207fb39330e840436215c896cde911489e111Paul Soulos 10292a4207fb39330e840436215c896cde911489e111Paul Soulos public String getCopyText() { 10302a4207fb39330e840436215c896cde911489e111Paul Soulos return mCopyText; 10312a4207fb39330e840436215c896cde911489e111Paul Soulos } 10322a4207fb39330e840436215c896cde911489e111Paul Soulos 10332a4207fb39330e840436215c896cde911489e111Paul Soulos public String getCopyLabel() { 10342a4207fb39330e840436215c896cde911489e111Paul Soulos return mCopyLabel; 10352a4207fb39330e840436215c896cde911489e111Paul Soulos } 103697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 103797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos public String getMimeType() { 103897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return mMimeType; 103997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 104097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 104197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos public long getId() { 104297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return mId; 104397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 104497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 104597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos public boolean isSuperPrimary() { 104697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return mIsSuperPrimary; 104797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 10482a4207fb39330e840436215c896cde911489e111Paul Soulos } 10492ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 10502ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos static final class EntryTag { 10512ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos private final int mId; 10522ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos private final Intent mIntent; 10532ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 10542ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos public EntryTag(int id, Intent intent) { 10552ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos mId = id; 10562ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos mIntent = intent; 10572ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos } 10582ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 10592ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos public int getId() { 10602ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos return mId; 10612ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos } 10622ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 10632ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos public Intent getIntent() { 10642ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos return mIntent; 10652ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos } 10662ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos } 106748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 106848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /** 106948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos * This custom touch listener increases the touch area for the second and third icons, if 107048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos * they are present. This is necessary to maintain other properties on an entry view, like 107148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos * using a top padding on entry. Based off of {@link android.view.TouchDelegate} 107248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos */ 107348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private static final class EntryTouchListener implements View.OnTouchListener { 107448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final View mEntry; 107548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final ImageView mAlternateIcon; 107648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private final ImageView mThirdIcon; 107748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /** mTouchedView locks in a view on touch down */ 107848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private View mTouchedView; 107948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /** mSlop adds some space to account for touches that are just outside the hit area */ 108048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private int mSlop; 108148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 108248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos public EntryTouchListener(View entry, ImageView alternateIcon, ImageView thirdIcon) { 108348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mEntry = entry; 108448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mAlternateIcon = alternateIcon; 108548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mThirdIcon = thirdIcon; 108648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mSlop = ViewConfiguration.get(entry.getContext()).getScaledTouchSlop(); 108748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 108848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 108948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos @Override 109048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos public boolean onTouch(View v, MotionEvent event) { 109148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos View touchedView = mTouchedView; 109248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos boolean sendToTouched = false; 109348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos boolean hit = true; 109448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos boolean handled = false; 109548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 109648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos switch (event.getAction()) { 109748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos case MotionEvent.ACTION_DOWN: 109848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (hitThirdIcon(event)) { 109948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mTouchedView = mThirdIcon; 110048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos sendToTouched = true; 110148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } else if (hitAlternateIcon(event)) { 110248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mTouchedView = mAlternateIcon; 110348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos sendToTouched = true; 110448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } else { 110548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mTouchedView = mEntry; 110648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos sendToTouched = false; 110748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 110848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos touchedView = mTouchedView; 110948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos break; 111048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos case MotionEvent.ACTION_UP: 111148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos case MotionEvent.ACTION_MOVE: 111248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos sendToTouched = mTouchedView != null && mTouchedView != mEntry; 111348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (sendToTouched) { 111448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos final Rect slopBounds = new Rect(); 111548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos touchedView.getHitRect(slopBounds); 111648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos slopBounds.inset(-mSlop, -mSlop); 111748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (!slopBounds.contains((int) event.getX(), (int) event.getY())) { 111848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos hit = false; 111948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 112048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 112148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos break; 112248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos case MotionEvent.ACTION_CANCEL: 112348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos sendToTouched = mTouchedView != null && mTouchedView != mEntry; 112448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos mTouchedView = null; 112548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos break; 112648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 112748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (sendToTouched) { 112848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos if (hit) { 112948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.setLocation(touchedView.getWidth() / 2, touchedView.getHeight() / 2); 113048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } else { 113148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // Offset event coordinates to be outside the target view (in case it does 113248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // something like tracking pressed state) 113348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.setLocation(-(mSlop * 2), -(mSlop * 2)); 113448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 113548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos handled = touchedView.dispatchTouchEvent(event); 113648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 113748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return handled; 113848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 113948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 114048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private boolean hitThirdIcon(MotionEvent event) { 1141f140227beb6d9e78955a7676dc0dd3f793f72017Brian Attwell if (mEntry.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { 114248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mThirdIcon.getVisibility() == View.VISIBLE && 114348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.getX() < mThirdIcon.getRight(); 114448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } else { 114548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mThirdIcon.getVisibility() == View.VISIBLE && 114648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.getX() > mThirdIcon.getLeft(); 114748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 114848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 114948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 115048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /** 115148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos * Should be used after checking if third icon was hit 115248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos */ 115348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private boolean hitAlternateIcon(MotionEvent event) { 115448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // LayoutParams used to add the start margin to the touch area 115548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos final RelativeLayout.LayoutParams alternateIconParams = 115648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos (RelativeLayout.LayoutParams) mAlternateIcon.getLayoutParams(); 1157f140227beb6d9e78955a7676dc0dd3f793f72017Brian Attwell if (mEntry.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { 115848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mAlternateIcon.getVisibility() == View.VISIBLE && 115948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.getX() < mAlternateIcon.getRight() + alternateIconParams.rightMargin; 116048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } else { 116148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos return mAlternateIcon.getVisibility() == View.VISIBLE && 116248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos event.getX() > mAlternateIcon.getLeft() - alternateIconParams.leftMargin; 116348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 116448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 116548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 11662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos} 1167