ContactListItemView.java revision bb67024ef64a7853f5ec320652d80f0cdf7b660f
1d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/* 2d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Copyright (C) 2010 The Android Open Source Project 3d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 4d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * you may not use this file except in compliance with the License. 6d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * You may obtain a copy of the License at 7d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 8d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 9d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 10d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Unless required by applicable law or agreed to in writing, software 11d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * See the License for the specific language governing permissions and 14d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * limitations under the License. 15d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 16d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 17d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpackage com.android.contacts.common.list; 18d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 19d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.Context; 20d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.res.ColorStateList; 21d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.content.res.TypedArray; 22d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.database.CharArrayBuffer; 23d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.database.Cursor; 24d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Canvas; 25d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Color; 26d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Rect; 27d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Typeface; 28d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.drawable.Drawable; 29d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.os.Bundle; 30d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract; 31d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract.Contacts; 32d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.Spannable; 33d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.SpannableString; 34d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils; 35d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils.TruncateAt; 36d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.util.AttributeSet; 37d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.util.TypedValue; 38d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.Gravity; 3910349f190691f802b8935175dbf38bff74a8a703Yorke Leeimport android.view.MotionEvent; 40d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.View; 41d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.ViewGroup; 42d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.AbsListView.SelectionBoundsAdjuster; 43d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView; 44d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView.ScaleType; 45d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.QuickContactBadge; 46d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.TextView; 47d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 48d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactPresenceIconUtil; 49d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactStatusUtil; 50d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.R; 51a81953a2b1818066ef5e44817f374ac288bab343Christine Chenimport com.android.contacts.common.format.TextHighlighter; 52cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Chengimport com.android.contacts.common.util.SearchUtil; 53864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Leeimport com.android.contacts.common.util.ViewUtil; 54864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee 5505897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport com.google.common.collect.Lists; 5605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 5705897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.ArrayList; 5805897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.List; 599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglioimport java.util.Locale; 6005897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Matcher; 6105897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Pattern; 62d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 63d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/** 64d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * A custom view for an item in the contact list. 65d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view contains the contact's photo, a set of text views (for name, status, etc...) and 66d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * icons for presence and call. 67d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view uses no XML file for layout and all the measurements and layouts are done 68d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * in the onMeasure and onLayout methods. 69d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 70d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout puts the contact's photo on the right side of the view, the call icon (if present) 71d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to the left of the photo, the text lines are aligned to the left and the presence icon (if 72d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * present) is set to the left of the status line. 73d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 74d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout also supports a header (used as a header of a group of contacts) that is above the 75d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * contact's data and a divider between contact view. 76d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 77d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 78d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpublic class ContactListItemView extends ViewGroup 79d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng implements SelectionBoundsAdjuster { 80d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 81d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Style values for layout and appearance 82d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The initialized values are defaults if none is provided through xml. 83d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPreferredHeight = 0; 84d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenImageAndText = 0; 85d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenLabelAndData = 0; 86d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconMargin = 4; 87d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconSize = 16; 88d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderTextColor = Color.BLACK; 89d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderTextIndent = 0; 90d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderTextSize = 12; 91d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderUnderlineHeight = 1; 92d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderUnderlineColor = 0; 93d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mCountViewTextSize = 12; 94d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mContactsCountTextColor = Color.BLACK; 95d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mTextIndent = 0; 96d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Drawable mActivatedBackgroundDrawable; 97d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 98d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 99d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mLabelView}, specifying the width ratio between label and data. 100d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 101d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewWidthWeight = 3; 102d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 103d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mDataView}, specifying the width ratio between label and data. 104d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 105d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewWidthWeight = 5; 106d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 107d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Will be used with adjustListItemSelectionBounds(). 108d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mSelectionBoundsMarginLeft; 109d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mSelectionBoundsMarginRight; 110d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 111d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Horizontal divider between contact views. 112d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mHorizontalDividerVisible = true; 113d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Drawable mHorizontalDividerDrawable; 114d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHorizontalDividerHeight; 115d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 116f99a990be713ed35afe64ba8133c5428816390c6Christine Chen protected static class HighlightSequence { 117f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int start; 118f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int end; 119f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 120f99a990be713ed35afe64ba8133c5428816390c6Christine Chen HighlightSequence(int start, int end) { 121f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.start = start; 122f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.end = end; 123f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 124f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 125f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 126f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNameHighlightSequence; 127f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNumberHighlightSequence; 128a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 129a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Highlighting prefix for names. 130a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private String mHighlightedPrefix; 131a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 132d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 133d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Where to put contact photo. This affects the other Views' layout or look-and-feel. 1349f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * 1359f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * TODO: replace enum with int constants 136d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 137d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public enum PhotoPosition { 138d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LEFT, 139d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng RIGHT 140d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1419f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1429f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio static public final PhotoPosition getDefaultPhotoPosition(boolean opposite) { 1439f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final Locale locale = Locale.getDefault(); 1449f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale); 1459f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio switch (layoutDirection) { 1469f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_RTL: 1479f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio return (opposite ? PhotoPosition.RIGHT : PhotoPosition.LEFT); 1489f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_LTR: 1499f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio default: 1509f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio return (opposite ? PhotoPosition.LEFT : PhotoPosition.RIGHT); 1519f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1529f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1539f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1549f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio private PhotoPosition mPhotoPosition = getDefaultPhotoPosition(false /* normal/non opposite */); 155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Header layout data 157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mHeaderVisible; 158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private View mHeaderDivider; 159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mHeaderBackgroundHeight = 30; 160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mHeaderTextView; 161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The views inside the contact view 163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mQuickContactEnabled = true; 164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private QuickContactBadge mQuickContact; 165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPhotoView; 166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mNameTextView; 167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mPhoneticNameTextView; 168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mLabelView; 169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mDataView; 170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mSnippetView; 171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mStatusView; 172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mCountView; 173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPresenceIcon; 174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ColorStateList mSecondaryTextColor; 176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 177a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDefaultPhotoViewSize = 0; 180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have horizontal padding 182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to align other data in this View. 183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewWidth; 185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have vertical padding. 187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewHeight; 189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * When true all the Views on the right side of the photo should have horizontal padding on 193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * those left assuming there is a photo. 194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepHorizontalPaddingForPhotoView; 196d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepVerticalPaddingForPhotoView; 200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 201d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 202d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * True when {@link #mPhotoViewWidth} and {@link #mPhotoViewHeight} are ready for being used. 203d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * False indicates those values should be updated before being used in position calculation. 204d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 205d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mPhotoViewWidthAndHeightAreReady = false; 206d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 207d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mNameTextViewHeight; 208d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhoneticNameTextViewHeight; 209d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewHeight; 210d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewHeight; 211d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mSnippetTextViewHeight; 212d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mStatusTextViewHeight; 213d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 214d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Holds Math.max(mLabelTextViewHeight, mDataViewHeight), assuming Label and Data share the 215d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // same row. 216d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelAndDataViewMaxHeight; 217d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 218d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TODO: some TextView fields are using CharArrayBuffer while some are not. Determine which is 219d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // more efficient for each case or in general, and simplify the whole implementation. 220d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Note: if we're sure MARQUEE will be used every time, there's no reason to use 221d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // CharArrayBuffer, since MARQUEE requires Span and thus we need to copy characters inside the 222d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // buffer to Spannable once, while CharArrayBuffer is for directly applying char array to 223d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TextView without any modification. 224d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mDataBuffer = new CharArrayBuffer(128); 225d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mPhoneticNameBuffer = new CharArrayBuffer(128); 226d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 227d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mActivatedStateSupported; 228d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 229d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Rect mBoundsWithoutHeader = new Rect(); 230d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 231d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** A helper used to highlight a prefix in a text field. */ 232a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private final TextHighlighter mTextHighlighter; 233d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private CharSequence mUnknownNameText; 234d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 235d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context) { 236d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context); 237d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 23842210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 239bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNameHighlightSequence = new ArrayList<HighlightSequence>(); 240bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 241d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 242d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 243d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context, AttributeSet attrs) { 244d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context, attrs); 245d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 246d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Read all style values 247d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ContactListItemView); 248d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPreferredHeight = a.getDimensionPixelSize( 249d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_height, mPreferredHeight); 250d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable = a.getDrawable( 251d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_activated_background); 252d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHorizontalDividerDrawable = a.getDrawable( 253d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_divider); 254d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 255d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText = a.getDimensionPixelOffset( 256d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 257d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText); 258d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData = a.getDimensionPixelOffset( 259d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_label_and_data, 260d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData); 261d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin = a.getDimensionPixelOffset( 262d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_margin, 263d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin); 264d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconSize = a.getDimensionPixelOffset( 265d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_size, mPresenceIconSize); 266d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultPhotoViewSize = a.getDimensionPixelOffset( 267d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_photo_size, mDefaultPhotoViewSize); 268d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextIndent = a.getDimensionPixelOffset( 269d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_text_indent, mHeaderTextIndent); 270d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextColor = a.getColor( 271d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_text_color, mHeaderTextColor); 272d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextSize = a.getDimensionPixelSize( 273d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_text_size, mHeaderTextSize); 274d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight = a.getDimensionPixelSize( 275d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_height, mHeaderBackgroundHeight); 276d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderUnderlineHeight = a.getDimensionPixelSize( 277d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_underline_height, 278d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderUnderlineHeight); 279d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderUnderlineColor = a.getColor( 280d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_header_underline_color, 281d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderUnderlineColor); 282d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mTextIndent = a.getDimensionPixelOffset( 283d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_text_indent, mTextIndent); 284d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountViewTextSize = a.getDimensionPixelSize( 285d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_contacts_count_text_size, 286d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountViewTextSize); 287d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mContactsCountTextColor = a.getColor( 288d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_contacts_count_text_color, 289d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mContactsCountTextColor); 290d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewWidthWeight = a.getInteger( 291d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_data_width_weight, mDataViewWidthWeight); 292d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight = a.getInteger( 293d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_label_width_weight, 294d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight); 295d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2969f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio setPaddingRelative( 297d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 298d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_left, 0), 299d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 300d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_top, 0), 301d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 302d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_right, 0), 303d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 304d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_bottom, 0)); 305d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 30642210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 30742210256d3d584783ac2fb2742088ce57d9da766Yorke Lee 308d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 309d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 3103aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee a = getContext().obtainStyledAttributes(R.styleable.Theme); 3113aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee mSecondaryTextColor = a.getColorStateList(R.styleable.Theme_android_textColorSecondary); 312d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 313d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 314d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHorizontalDividerHeight = mHorizontalDividerDrawable.getIntrinsicHeight(); 315d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 316d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedBackgroundDrawable != null) { 317d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setCallback(this); 318d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 319f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 320f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence = new ArrayList<HighlightSequence>(); 321f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 322d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 323d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 324d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setUnknownNameText(CharSequence unknownNameText) { 325d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mUnknownNameText = unknownNameText; 326d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 327d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 328d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setQuickContactEnabled(boolean flag) { 329d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContactEnabled = flag; 330d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 331d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 332d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 333d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 334d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will match parent's width and wrap content vertically, but make sure 335d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // height is no less than listPreferredItemHeight. 336d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int specWidth = resolveSize(0, widthMeasureSpec); 337d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int preferredHeight; 338d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHorizontalDividerVisible) { 339d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng preferredHeight = mPreferredHeight + mHorizontalDividerHeight; 340d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 341d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng preferredHeight = mPreferredHeight; 342d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 343d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 344d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = 0; 345d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = 0; 346d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = 0; 347d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = 0; 348d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = 0; 349d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = 0; 350d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 0; 351d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 352d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ensurePhotoViewSize(); 353d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 354d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Width each TextView is able to use. 355d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int effectiveWidth; 356d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // All the other Views will honor the photo, so available width for them may be shrunk. 357d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoViewWidth > 0 || mKeepHorizontalPaddingForPhotoView) { 358d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight() 359d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - (mPhotoViewWidth + mGapBetweenImageAndText); 360d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 361d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight(); 362d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 363d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 364d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Go over all visible text views and measure actual width of each of them. 365d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Also calculate their heights to get the total height for this entire view. 366d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 367d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 368d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Caculate width for name text - this parallels similar measurement in onLayout. 369d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int nameTextWidth = effectiveWidth; 370d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition != PhotoPosition.LEFT) { 371d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng nameTextWidth -= mTextIndent; 372d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 373d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.measure( 374d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(nameTextWidth, MeasureSpec.EXACTLY), 375d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 376d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = mNameTextView.getMeasuredHeight(); 377d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 378d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 379d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 380d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.measure( 381d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 382d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 383d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = mPhoneticNameTextView.getMeasuredHeight(); 384d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 385d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 386d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If both data (phone number/email address) and label (type like "MOBILE") are quite long, 387d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // we should ellipsize both using appropriate ratio. 388d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int dataWidth; 389d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int labelWidth; 390d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 391d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 392d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalWidth = effectiveWidth - mGapBetweenLabelAndData; 393d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = ((totalWidth * mDataViewWidthWeight) 394d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng / (mDataViewWidthWeight + mLabelViewWidthWeight)); 395d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = ((totalWidth * mLabelViewWidthWeight) / 396d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng (mDataViewWidthWeight + mLabelViewWidthWeight)); 397d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 398d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = effectiveWidth; 399d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 400d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 401d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 402d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = 0; 403d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 404d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = effectiveWidth; 405d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 406d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 407d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 408d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 409d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 410d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 411d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.measure(MeasureSpec.makeMeasureSpec(dataWidth, MeasureSpec.EXACTLY), 412d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 413d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = mDataView.getMeasuredHeight(); 414d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 415d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 416d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 417d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // For performance reason we don't want AT_MOST usually, but when the picture is 418d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // on right, we need to use it anyway because mDataView is next to mLabelView. 419d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int mode = (mPhotoPosition == PhotoPosition.LEFT 420d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ? MeasureSpec.EXACTLY : MeasureSpec.AT_MOST); 421d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.measure(MeasureSpec.makeMeasureSpec(labelWidth, mode), 422d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 423d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = mLabelView.getMeasuredHeight(); 424d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 425d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = Math.max(mLabelViewHeight, mDataViewHeight); 426d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 427d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 428d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.measure( 429d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 430d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 431d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = mSnippetView.getMeasuredHeight(); 432d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 433d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 434d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Status view height is the biggest of the text view and the presence icon 435d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 436d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.measure( 437d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY), 438d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY)); 439d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = mPresenceIcon.getMeasuredHeight(); 440d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 441d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 442d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView)) { 443d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status are in a same row, so status will be affected by icon size. 444d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int statusWidth; 445d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 446d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = (effectiveWidth - mPresenceIcon.getMeasuredWidth() 447d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - mPresenceIconMargin); 448d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 449d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = effectiveWidth; 450d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 451d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.measure(MeasureSpec.makeMeasureSpec(statusWidth, MeasureSpec.EXACTLY), 452d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 453d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 454d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Math.max(mStatusTextViewHeight, mStatusView.getMeasuredHeight()); 455d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 456d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 457d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Calculate height including padding. 458d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int height = (mNameTextViewHeight + mPhoneticNameTextViewHeight + 459d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + 460d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight + mStatusTextViewHeight); 461d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 462d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure the height is at least as high as the photo 463d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, mPhotoViewHeight + getPaddingBottom() + getPaddingTop()); 464d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 465d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Add horizontal divider height 466d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHorizontalDividerVisible) { 467d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height += mHorizontalDividerHeight; 468d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 469d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 470d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure height is at least the preferred height 471d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, preferredHeight); 472d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 473d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Add the height of the header if visible 474d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderVisible) { 4759f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final int headerWidth = specWidth - 4769f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio getPaddingLeft() - getPaddingRight() - mHeaderTextIndent; 477d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.measure( 4789f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio MeasureSpec.makeMeasureSpec(headerWidth, MeasureSpec.EXACTLY), 479d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY)); 480d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mCountView != null) { 481d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.measure( 4829f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio MeasureSpec.makeMeasureSpec(headerWidth, MeasureSpec.AT_MOST), 483d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY)); 484d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 485d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight = Math.max(mHeaderBackgroundHeight, 486d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.getMeasuredHeight()); 487d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height += (mHeaderBackgroundHeight + mHeaderUnderlineHeight); 488d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 489d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 490d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMeasuredDimension(specWidth, height); 491d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 492d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 493d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 494d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 495d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int height = bottom - top; 496d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int width = right - left; 497d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 498d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Determine the vertical bounds by laying out the header first. 499d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int topBound = 0; 500d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int bottomBound = height; 501d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int leftBound = getPaddingLeft(); 502d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int rightBound = width - getPaddingRight(); 503d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 504864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee final boolean isLayoutRtl = ViewUtil.isViewLayoutRtl(this); 50509f15e70e86d92ae0f4c15a726b777f170845a3cYorke Lee 506d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Put the header in the top of the contact view (Text + underline view) 507d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderVisible) { 5089f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mHeaderTextView.layout(isLayoutRtl ? leftBound : leftBound + mHeaderTextIndent, 509d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 0, 5109f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio isLayoutRtl ? rightBound - mHeaderTextIndent : rightBound, 511d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight); 512d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mCountView != null) { 513d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.layout(rightBound - mCountView.getMeasuredWidth(), 514d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 0, 515d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 516d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight); 517d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 518d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderDivider.layout(leftBound, 519d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight, 520d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 521d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderBackgroundHeight + mHeaderUnderlineHeight); 522d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng topBound += (mHeaderBackgroundHeight + mHeaderUnderlineHeight); 523d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 524d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 525d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Put horizontal divider at the bottom 526d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHorizontalDividerVisible) { 527d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHorizontalDividerDrawable.setBounds( 528d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound, 529d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height - mHorizontalDividerHeight, 530d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 531d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height); 532d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bottomBound -= mHorizontalDividerHeight; 533d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 534d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 535d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mBoundsWithoutHeader.set(0, topBound, width, bottomBound); 536d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 537d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 538d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setBounds(mBoundsWithoutHeader); 539d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 540d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 541d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final View photoView = mQuickContact != null ? mQuickContact : mPhotoView; 542d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 543d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the left most view. All the other Views should on the right of the photo. 544d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 545d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 546d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 547d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 548d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound, 549d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 550d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound + mPhotoViewWidth, 551d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 552d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 553d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else if (mKeepHorizontalPaddingForPhotoView) { 554d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Draw nothing but keep the padding. 555d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 556d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 557d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 558d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the right most view. Right bound should be adjusted that way. 559d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 560d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 561d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 562d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 563d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound - mPhotoViewWidth, 564d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 565d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 566d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 567d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 5689f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else if (mKeepHorizontalPaddingForPhotoView) { 5699f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio // Draw nothing but keep the padding. 5709f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 571d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 572d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 573d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Add indent between left-most padding and texts. 574d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mTextIndent; 575d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 576d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 577d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center text vertically 578d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalTextHeight = mNameTextViewHeight + mPhoneticNameTextViewHeight + 579d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + mSnippetTextViewHeight + mStatusTextViewHeight; 580d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int textTopBound = (bottomBound + topBound - totalTextHeight) / 2; 581d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 582d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Layout all text view and presence icon 583d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Put name TextView first 584d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 585d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.layout(leftBound, 586d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 587d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 588d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mNameTextViewHeight); 589d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mNameTextViewHeight; 590d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 591d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 592d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status 5939f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isLayoutRtl) { 5949f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusRightBound = rightBound; 5959f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 5969f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 5979f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 5989f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound - iconWidth, 5999f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 6009f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 6019f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 6029f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound -= (iconWidth + mPresenceIconMargin); 6039f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 604d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 6059f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 6069f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(leftBound, 6079f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 6089f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound, 6099f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 6109f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 6119f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else { 6129f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusLeftBound = leftBound; 6139f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 6149f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 6159f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 6169f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound, 6179f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 6189f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound + iconWidth, 6199f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 6209f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusLeftBound += (iconWidth + mPresenceIconMargin); 6219f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 6229f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 6239f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 6249f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(statusLeftBound, 6259f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 6269f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 6279f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 6289f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 629d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 630d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 631d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView) || isVisible(mPresenceIcon)) { 632d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mStatusTextViewHeight; 633d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 634d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 635d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Rest of text views 636d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int dataLeftBound = leftBound; 637d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 638d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.layout(leftBound, 639d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 640d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 641d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mPhoneticNameTextViewHeight); 642d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mPhoneticNameTextViewHeight; 643d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 644d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 645d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Label and Data align bottom. 646d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 647d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 648d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on left, label is placed on the right edge of the list item. 649d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(rightBound - mLabelView.getMeasuredWidth(), 650d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 651d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 652d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 653d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= mLabelView.getMeasuredWidth(); 654d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 655d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on right, label is placed on the left of data view. 656d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound = leftBound + mLabelView.getMeasuredWidth(); 657d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(leftBound, 658d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 659d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound, 660d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 661d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound += mGapBetweenLabelAndData; 662d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 663d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 664d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 665d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 666d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.layout(dataLeftBound, 667d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mDataViewHeight, 668d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 669d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 670d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 671d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView) || isVisible(mDataView)) { 672d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mLabelAndDataViewMaxHeight; 673d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 674d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 675d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 676d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.layout(leftBound, 677d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 678d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 679d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mSnippetTextViewHeight); 680d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 681d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 682d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 683d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 684d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void adjustListItemSelectionBounds(Rect bounds) { 685d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.top += mBoundsWithoutHeader.top; 686d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.bottom = bounds.top + mBoundsWithoutHeader.height(); 687d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.left += mSelectionBoundsMarginLeft; 688d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.right -= mSelectionBoundsMarginRight; 689d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 690d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 691d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean isVisible(View view) { 692d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return view != null && view.getVisibility() == View.VISIBLE; 693d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 694d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 695d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 696d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Extracts width and height from the style 697d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 698d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void ensurePhotoViewSize() { 699d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mPhotoViewWidthAndHeightAreReady) { 700d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = mPhotoViewHeight = getDefaultPhotoViewSize(); 701d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled && mPhotoView == null) { 702d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepHorizontalPaddingForPhotoView) { 703d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = 0; 704d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 705d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepVerticalPaddingForPhotoView) { 706d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewHeight = 0; 707d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 708d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 709d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 710d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = true; 711d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 712d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 713d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 714d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void setDefaultPhotoViewSize(int pixels) { 715d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultPhotoViewSize = pixels; 716d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 717d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 718d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected int getDefaultPhotoViewSize() { 719d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDefaultPhotoViewSize; 720d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 721d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 722d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 723d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Gets a LayoutParam that corresponds to the default photo size. 724d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 725d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @return A new LayoutParam. 726d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 727d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private LayoutParams getDefaultPhotoLayoutParams() { 728d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LayoutParams params = generateDefaultLayoutParams(); 729d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.width = getDefaultPhotoViewSize(); 730d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.height = params.width; 731d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return params; 732d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 733d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 734d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 735d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void drawableStateChanged() { 736d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.drawableStateChanged(); 737d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 738d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setState(getDrawableState()); 739d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 740d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 741d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 742d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 743d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean verifyDrawable(Drawable who) { 744d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return who == mActivatedBackgroundDrawable || super.verifyDrawable(who); 745d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 746d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 747d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 748d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void jumpDrawablesToCurrentState() { 749d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.jumpDrawablesToCurrentState(); 750d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 751d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.jumpToCurrentState(); 752d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 753d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 754d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 755d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 756d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void dispatchDraw(Canvas canvas) { 757d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 758d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.draw(canvas); 759d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 760d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHorizontalDividerVisible) { 761d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHorizontalDividerDrawable.draw(canvas); 762d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 763d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 764d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.dispatchDraw(canvas); 765d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 766d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 767d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 768d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets the flag that determines whether a divider should drawn at the bottom 769d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * of the view. 770d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 771d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setDividerVisible(boolean visible) { 772d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHorizontalDividerVisible = visible; 773d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 774d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 775d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 776d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets section header or makes it invisible if the title is null. 777d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 778d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSectionHeader(String title) { 779d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(title)) { 780d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderTextView == null) { 781e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView = new TextView(getContext()); 782d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setTextColor(mHeaderTextColor); 783d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mHeaderTextSize); 784e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView.setTextAppearance(getContext(), R.style.SectionHeaderStyle); 785d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setGravity(Gravity.CENTER_VERTICAL); 7869f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mHeaderTextView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 787d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mHeaderTextView); 788d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 789d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderDivider == null) { 790e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderDivider = new View(getContext()); 791d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderDivider.setBackgroundColor(mHeaderUnderlineColor); 792d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mHeaderDivider); 793d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 794d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mHeaderTextView, title); 795d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setVisibility(View.VISIBLE); 796d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderDivider.setVisibility(View.VISIBLE); 797d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setAllCaps(true); 798d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderVisible = true; 799d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 800d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderTextView != null) { 801d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setVisibility(View.GONE); 802d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 803d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderDivider != null) { 804d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderDivider.setVisibility(View.GONE); 805d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 806d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderVisible = false; 807d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 808d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 809d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 810d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 811d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the quick contact badge, creating it if necessary. 812d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 813d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public QuickContactBadge getQuickContact() { 814d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled) { 815d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng throw new IllegalStateException("QuickContact is disabled for this view"); 816d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 817d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact == null) { 818e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact = new QuickContactBadge(getContext()); 819d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams()); 820d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 821e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 822d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.string.description_quick_contact_for, mNameTextView.getText())); 823d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 824d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 825d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mQuickContact); 826d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 827d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 828d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mQuickContact; 829d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 830d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 831d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 832d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the photo view, creating it if necessary. 833d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 834d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ImageView getPhotoView() { 835d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView == null) { 836e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhotoView = new ImageView(getContext()); 837d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams()); 838d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Quick contact style used above will set a background - remove it 839d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setBackground(null); 840d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhotoView); 841d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 842d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 843d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoView; 844d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 845d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 846d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 847d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 848d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 849d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView() { 850d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removePhotoView(false, true); 851d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 852d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 853d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 854d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 855d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 856d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepHorizontalPadding True means data on the right side will have 857d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * padding on left, pretending there is still a photo view. 858d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepVerticalPadding True means the View will have some height 859d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * enough for accommodating a photo view. 860d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 861d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView(boolean keepHorizontalPadding, boolean keepVerticalPadding) { 862d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 863d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepHorizontalPaddingForPhotoView = keepHorizontalPadding; 864d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepVerticalPaddingForPhotoView = keepVerticalPadding; 865d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView != null) { 866d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhotoView); 867d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView = null; 868d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 869d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact != null) { 870d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mQuickContact); 871d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact = null; 872d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 873d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 874d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 875d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 876d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets a word prefix that will be highlighted if encountered in fields like 877a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * name and search snippet. This will disable the mask highlighting for names. 878d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * <p> 879d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * NOTE: must be all upper-case 880d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 881bd80fd64b9ff94c9ffbdb843beb4b363bb209463Chiao Cheng public void setHighlightedPrefix(String upperCasePrefix) { 882d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHighlightedPrefix = upperCasePrefix; 883a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 884a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 885a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 886f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Clears previously set highlight sequences for the view. 887a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 888f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void clearHighlightSequences() { 889f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.clear(); 890f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.clear(); 891a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mHighlightedPrefix = null; 892a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 893a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 894a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 895f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the name highlighter. 896f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 897f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 898f99a990be713ed35afe64ba8133c5428816390c6Christine Chen */ 899f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNameHighlightSequence(int start, int end) { 900f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.add(new HighlightSequence(start, end)); 901f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 902f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 903f99a990be713ed35afe64ba8133c5428816390c6Christine Chen /** 904f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the number highlighter. 905f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 906f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 907a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 908f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNumberHighlightSequence(int start, int end) { 909f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.add(new HighlightSequence(start, end)); 910d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 911d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 912d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 913d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the contact name, creating it if necessary. 914d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 915d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getNameTextView() { 916d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView == null) { 917e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mNameTextView = new TextView(getContext()); 918d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setSingleLine(true); 919d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setEllipsize(getTextEllipsis()); 92090a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mNameTextView.setTextAppearance(getContext(), R.style.TextAppearanceMedium); 921d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Manually call setActivated() since this view may be added after the first 922d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // setActivated() call toward this whole item view. 923d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setActivated(isActivated()); 924d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setGravity(Gravity.CENTER_VERTICAL); 9259f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 9269f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setId(R.id.cliv_name_textview); 927d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mNameTextView); 928d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 929d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mNameTextView; 930d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 931d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 932d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 933d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the phonetic name. 934d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 935d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhoneticName(char[] text, int size) { 936d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 937d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 938d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(View.GONE); 939d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 940d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 941d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getPhoneticNameTextView(); 942d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mPhoneticNameTextView, text, size); 943d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(VISIBLE); 944d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 945d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 946d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 947d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 948d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the phonetic name, creating it if necessary. 949d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 950d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getPhoneticNameTextView() { 951d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView == null) { 952e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView = new TextView(getContext()); 953d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setSingleLine(true); 954d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setEllipsize(getTextEllipsis()); 955e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 956d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD); 957d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setActivated(isActivated()); 9589f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPhoneticNameTextView.setId(R.id.cliv_phoneticname_textview); 959d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhoneticNameTextView); 960d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 961d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhoneticNameTextView; 962d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 963d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 964d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 965d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data label. 966d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 967d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setLabel(CharSequence text) { 968d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 969d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView != null) { 970d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(View.GONE); 971d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 972d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 973d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getLabelView(); 974d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mLabelView, text); 975d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(VISIBLE); 976d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 977d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 978d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 979d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 980d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data label, creating it if necessary. 981d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 982d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getLabelView() { 983d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView == null) { 984e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mLabelView = new TextView(getContext()); 985d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setSingleLine(true); 986d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setEllipsize(getTextEllipsis()); 98790a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mLabelView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 988d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 989d396439cb61b5470363fda394137f706b792f29aChiao Cheng //mLabelView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCountViewTextSize); 990d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setAllCaps(true); 9919f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setGravity(Gravity.END); 992d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 993d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD); 994d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 995d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setActivated(isActivated()); 9969f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setId(R.id.cliv_label_textview); 997d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mLabelView); 998d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 999d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mLabelView; 1000d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1001d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1002d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1003d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data element. 1004d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1005a81953a2b1818066ef5e44817f374ac288bab343Christine Chen public void setData(char[] text, int size) { 1006d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 1007d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView != null) { 1008d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(View.GONE); 1009d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1010d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1011d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getDataView(); 1012d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mDataView, text, size); 1013d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(VISIBLE); 1014a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1015a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1016a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 1017a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 1018a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * Sets phone number for a list item. This takes care of number highlighting if the highlight 1019a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * mask exists. 1020a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 1021a81953a2b1818066ef5e44817f374ac288bab343Christine Chen public void setPhoneNumber(String text) { 1022a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (text == null) { 1023a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mDataView != null) { 1024a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(View.GONE); 10259f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1026a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } else { 1027a81953a2b1818066ef5e44817f374ac288bab343Christine Chen getDataView(); 1028a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Sets phone number texts for display after highlighting it, if applicable. 1029f99a990be713ed35afe64ba8133c5428816390c6Christine Chen //CharSequence textToSet = text; 1030f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString textToSet = new SpannableString(text); 1031f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 1032f99a990be713ed35afe64ba8133c5428816390c6Christine Chen if (mNumberHighlightSequence.size() != 0) { 1033f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final HighlightSequence highlightSequence = mNumberHighlightSequence.get(0); 1034f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(textToSet, highlightSequence.start, 1035f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 1036a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1037f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 1038a81953a2b1818066ef5e44817f374ac288bab343Christine Chen setMarqueeText(mDataView, textToSet); 1039a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(VISIBLE); 1040a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 1041a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // We have a phone number as "mDataView" so make it always LTR and VIEW_START 1042a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextDirection(View.TEXT_DIRECTION_LTR); 1043a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 1044d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1045d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1046d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1047d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, char[] text, int size) { 1048d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 1049d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(textView, new String(text, 0, size)); 1050d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1051d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text, 0, size); 1052d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1053d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1054d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1055d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, CharSequence text) { 1056d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 1057d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // To show MARQUEE correctly (with END effect during non-active state), we need 1058d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // to build Spanned with MARQUEE in addition to TextView's ellipsize setting. 1059d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final SpannableString spannable = new SpannableString(text); 1060d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng spannable.setSpan(TruncateAt.MARQUEE, 0, spannable.length(), 1061d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1062d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(spannable); 1063d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1064d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text); 1065d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1066d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1067d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1068d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1069d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data text, creating it if necessary. 1070d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1071d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getDataView() { 1072d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView == null) { 1073e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mDataView = new TextView(getContext()); 1074d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setSingleLine(true); 1075d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setEllipsize(getTextEllipsis()); 107690a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mDataView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 1077d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setActivated(isActivated()); 10789f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mDataView.setId(R.id.cliv_data_view); 1079d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mDataView); 1080d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1081d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDataView; 1082d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1083d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1084d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1085d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the search snippet. 1086d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1087d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSnippet(String text) { 1088d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1089d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView != null) { 1090d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(View.GONE); 1091d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1092d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1093f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix); 1094d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(VISIBLE); 1095d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1096d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1097d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1098d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1099d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the search snippet, creating it if necessary. 1100d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1101d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getSnippetView() { 1102d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView == null) { 1103e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView = new TextView(getContext()); 1104d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setSingleLine(true); 1105d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setEllipsize(getTextEllipsis()); 1106e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1107d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setActivated(isActivated()); 1108d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mSnippetView); 1109d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1110d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mSnippetView; 1111d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1112d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1113d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1114d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the status, creating it if necessary. 1115d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1116d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getStatusView() { 1117d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView == null) { 1118e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView = new TextView(getContext()); 1119d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setSingleLine(true); 1120d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setEllipsize(getTextEllipsis()); 1121e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1122d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setTextColor(mSecondaryTextColor); 1123d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setActivated(isActivated()); 11249f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 1125d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mStatusView); 1126d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1127d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mStatusView; 1128d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1129d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1130d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1131d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the contacts count, creating it if necessary. 1132d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1133d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getCountView() { 1134d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mCountView == null) { 1135e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mCountView = new TextView(getContext()); 1136d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setSingleLine(true); 1137d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setEllipsize(getTextEllipsis()); 1138e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mCountView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium); 1139ad21d11eed06b39ede8f171da0faf119b7b6c4b2Paul Sliwowski mCountView.setTextColor(R.color.people_app_theme_color); 1140d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mCountView); 1141d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1142d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mCountView; 1143d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1144d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1145d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1146d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the contacts count. 1147d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setCountView(CharSequence text) { 1149d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1150d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mCountView != null) { 1151d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setVisibility(View.GONE); 1152d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getCountView(); 1155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mCountView, text); 1156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCountViewTextSize); 1157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setGravity(Gravity.CENTER_VERTICAL); 1158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setTextColor(mContactsCountTextColor); 1159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mCountView.setVisibility(VISIBLE); 1160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the status. 1165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setStatus(CharSequence text) { 1167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView != null) { 1169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(View.GONE); 1170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getStatusView(); 1173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mStatusView, text); 1174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(VISIBLE); 1175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates the presence icon view. 1180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPresence(Drawable icon) { 1182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (icon != null) { 1183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon == null) { 1184e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPresenceIcon = new ImageView(getContext()); 1185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPresenceIcon); 1186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setImageDrawable(icon); 1188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setScaleType(ScaleType.CENTER); 1189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.VISIBLE); 1190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon != null) { 1192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.GONE); 1193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1196d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TruncateAt getTextEllipsis() { 1198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return TruncateAt.MARQUEE; 1199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1201d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showDisplayName(Cursor cursor, int nameColumnIndex, int displayOrder) { 1202d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng CharSequence name = cursor.getString(nameColumnIndex); 120327330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 120427330d80bb6575df2964112d34143125c8af9b78Yorke Lee 120527330d80bb6575df2964112d34143125c8af9b78Yorke Lee // Since the quick contact content description is derived from the display name and there is 120627330d80bb6575df2964112d34143125c8af9b78Yorke Lee // no guarantee that when the quick contact is initialized the display name is already set, 120727330d80bb6575df2964112d34143125c8af9b78Yorke Lee // do it here too. 120827330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (mQuickContact != null) { 1209e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 121027330d80bb6575df2964112d34143125c8af9b78Yorke Lee R.string.description_quick_contact_for, mNameTextView.getText())); 121127330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 121227330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 121327330d80bb6575df2964112d34143125c8af9b78Yorke Lee 121427330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name, boolean highlight) { 121527330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (!TextUtils.isEmpty(name) && highlight) { 121627330d80bb6575df2964112d34143125c8af9b78Yorke Lee clearHighlightSequences(); 121727330d80bb6575df2964112d34143125c8af9b78Yorke Lee addNameHighlightSequence(0, name.length()); 121827330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 121927330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 122027330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 122127330d80bb6575df2964112d34143125c8af9b78Yorke Lee 122227330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name) { 1223d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(name)) { 1224a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Chooses the available highlighting method for highlighting. 1225a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mHighlightedPrefix != null) { 1226a81953a2b1818066ef5e44817f374ac288bab343Christine Chen name = mTextHighlighter.applyPrefixHighlight(name, mHighlightedPrefix); 1227f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } else if (mNameHighlightSequence.size() != 0) { 1228f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString spannableName = new SpannableString(name); 1229f99a990be713ed35afe64ba8133c5428816390c6Christine Chen for (HighlightSequence highlightSequence : mNameHighlightSequence) { 1230f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(spannableName, highlightSequence.start, 1231f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 1232f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 1233f99a990be713ed35afe64ba8133c5428816390c6Christine Chen name = spannableName; 1234a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1235d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1236d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng name = mUnknownNameText; 1237d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1238d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(getNameTextView(), name); 1239d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1240d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1241d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hideDisplayName() { 1242d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 1243d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mNameTextView); 1244d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView = null; 1245d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1246d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1247d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1248d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPhoneticName(Cursor cursor, int phoneticNameColumnIndex) { 1249d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(phoneticNameColumnIndex, mPhoneticNameBuffer); 1250d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int phoneticNameSize = mPhoneticNameBuffer.sizeCopied; 1251d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (phoneticNameSize != 0) { 1252d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(mPhoneticNameBuffer.data, phoneticNameSize); 1253d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1254d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(null, 0); 1255d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1256d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1257d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1258d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hidePhoneticName() { 1259d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 1260d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhoneticNameTextView); 1261d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView = null; 1262d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1263d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1264d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1265d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1266d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets the proper icon (star or presence or nothing) and/or status message. 1267d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1268d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPresenceAndStatusMessage(Cursor cursor, int presenceColumnIndex, 1269d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int contactStatusColumnIndex) { 1270d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Drawable icon = null; 1271d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int presence = 0; 1272d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!cursor.isNull(presenceColumnIndex)) { 1273d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng presence = cursor.getInt(presenceColumnIndex); 1274d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng icon = ContactPresenceIconUtil.getPresenceIcon(getContext(), presence); 1275d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1276d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPresence(icon); 1277d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1278d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String statusMessage = null; 1279d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (contactStatusColumnIndex != 0 && !cursor.isNull(contactStatusColumnIndex)) { 1280d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = cursor.getString(contactStatusColumnIndex); 1281d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1282d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If there is no status message from the contact, but there was a presence value, then use 1283d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // the default status message string 1284d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (statusMessage == null && presence != 0) { 1285d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = ContactStatusUtil.getStatusString(getContext(), presence); 1286d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1287d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setStatus(statusMessage); 1288d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1289d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1290d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1291d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Shows search snippet. 1292d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1293d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showSnippet(Cursor cursor, int summarySnippetColumnIndex) { 1294d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (cursor.getColumnCount() <= summarySnippetColumnIndex) { 1295d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(null); 1296d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return; 1297d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1298d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 129905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng String snippet = cursor.getString(summarySnippetColumnIndex); 1300cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1301d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Do client side snippeting if provider didn't do it 130205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Bundle extras = cursor.getExtras(); 1303d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (extras.getBoolean(ContactsContract.DEFERRED_SNIPPETING)) { 1304d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 130505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final String query = extras.getString(ContactsContract.DEFERRED_SNIPPETING_QUERY); 1306cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1307cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng String displayName = null; 1308cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int displayNameIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); 1309cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (displayNameIndex >= 0) { 1310cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng displayName = cursor.getString(displayNameIndex); 131105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1312cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1313cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng snippet = updateSnippet(snippet, query, displayName); 1314cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 131505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 131605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (snippet != null) { 131705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int from = 0; 131805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int to = snippet.length(); 131905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int start = snippet.indexOf(DefaultContactListAdapter.SNIPPET_START_MATCH); 132005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (start == -1) { 132105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = null; 132205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 132305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int firstNl = snippet.lastIndexOf('\n', start); 132405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (firstNl != -1) { 132505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng from = firstNl + 1; 132605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 132705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int end = snippet.lastIndexOf(DefaultContactListAdapter.SNIPPET_END_MATCH); 132805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (end != -1) { 132905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int lastNl = snippet.indexOf('\n', end); 133005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (lastNl != -1) { 133105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng to = lastNl; 133205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 133305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1334d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 133505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng StringBuilder sb = new StringBuilder(); 133605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng for (int i = from; i < to; i++) { 133705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng char c = snippet.charAt(i); 133805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (c != DefaultContactListAdapter.SNIPPET_START_MATCH && 133905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng c != DefaultContactListAdapter.SNIPPET_END_MATCH) { 134005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng sb.append(c); 134105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1342d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 134305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = sb.toString(); 1344d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1345d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1346d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1347cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1348d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(snippet); 1349d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1350d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1351cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng /** 1352cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * Used for deferred snippets from the database. The contents come back as large strings which 1353cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * need to be extracted for display. 1354cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * 1355cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param snippet The snippet from the database. 1356cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param query The search query substring. 1357cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param displayName The contact display name. 1358cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @return The proper snippet to display. 1359cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng */ 1360cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String updateSnippet(String snippet, String query, String displayName) { 1361cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1362cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (TextUtils.isEmpty(snippet) || TextUtils.isEmpty(query)) { 1363cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1364cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1365cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng query = SearchUtil.cleanStartAndEndOfSearchQuery(query.toLowerCase()); 1366cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1367cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // If the display name already contains the query term, return empty - snippets should 1368cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // not be needed in that case. 1369cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!TextUtils.isEmpty(displayName)) { 1370cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final String lowerDisplayName = displayName.toLowerCase(); 1371cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final List<String> nameTokens = split(lowerDisplayName); 1372cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng for (String nameToken : nameTokens) { 1373cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (nameToken.startsWith(query)) { 1374cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1375cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1376cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1377cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1378cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1379cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // The snippet may contain multiple data lines. 1380cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show the first line that matches the query. 1381cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final SearchUtil.MatchedLine matched = SearchUtil.findMatchingLine(snippet, query); 1382cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1383cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched != null && matched.line != null) { 1384cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Tokenize for long strings since the match may be at the end of it. 1385cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Skip this part for short strings since the whole string will be displayed. 1386cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Most contact strings are short so the snippetize method will be called infrequently. 1387cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final int lengthThreshold = getResources().getInteger( 1388cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng R.integer.snippet_length_before_tokenize); 1389cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched.line.length() > lengthThreshold) { 1390cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return snippetize(matched.line, matched.startIndex, lengthThreshold); 1391cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } else { 1392cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return matched.line; 1393cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1394cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1395cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1396cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // No match found. 1397cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1398cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1399cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1400cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String snippetize(String line, int matchIndex, int maxLength) { 1401cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show up to maxLength characters. But we only show full tokens so show the last full token 1402cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // up to maxLength characters. So as many starting tokens as possible before trying ending 1403cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // tokens. 1404cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int remainingLength = maxLength; 1405cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int tempRemainingLength = remainingLength; 1406cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1407cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Start the end token after the matched query. 1408cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int index = matchIndex; 1409cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int endTokenIndex = index; 1410cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1411cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find the match token first. 1412cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length()) { 1413cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1414cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1415cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1416cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng break; 1417cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1418cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1419cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1420cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1421cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1422cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find as much content before the match. 1423cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = matchIndex - 1; 1424cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1425cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int startTokenIndex = matchIndex; 1426cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index > -1 && tempRemainingLength > 0) { 1427cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1428cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng startTokenIndex = index; 1429cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1430cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1431cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1432cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index--; 1433cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1434cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1435cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = endTokenIndex; 1436cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1437cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find remaining content at after match. 1438cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length() && tempRemainingLength > 0) { 1439cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1440cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1441cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1442cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1443cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1444cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1445cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Append ellipse if there is content before or after. 1446cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final StringBuilder sb = new StringBuilder(); 1447cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (startTokenIndex > 0) { 1448cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1449cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1450cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append(line.substring(startTokenIndex, endTokenIndex)); 1451cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (endTokenIndex < line.length()) { 1452cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1453cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1454cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return sb.toString(); 1455cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1456cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 145705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static final Pattern SPLIT_PATTERN = Pattern.compile( 145805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng "([\\w-\\.]+)@((?:[\\w]+\\.)+)([a-zA-Z]{2,4})|[\\w]+"); 145905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 146005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng /** 146105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * Helper method for splitting a string into tokens. The lists passed in are populated with 146205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * the 146305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * tokens and offsets into the content of each token. The tokenization function parses e-mail 146405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * addresses as a single token; otherwise it splits on any non-alphanumeric character. 146505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * 146605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @param content Content to split. 146705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @return List of token strings. 146805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng */ 146905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static List<String> split(String content) { 147005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Matcher matcher = SPLIT_PATTERN.matcher(content); 147105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final ArrayList<String> tokens = Lists.newArrayList(); 147205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng while (matcher.find()) { 147305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng tokens.add(matcher.group()); 147405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 147505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng return tokens; 147605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 147705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 1478d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 14797a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner * Shows data element. 1480d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1481d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showData(Cursor cursor, int dataColumnIndex) { 1482d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(dataColumnIndex, mDataBuffer); 14837a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner setData(mDataBuffer.data, mDataBuffer.sizeCopied); 14847a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner } 14857a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner 14867a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner public void showPhoneNumber(Cursor cursor, int dataColumnIndex) { 14877a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner // Highlights the number and aligns text before showing. 14887a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner setPhoneNumber(cursor.getString(dataColumnIndex)); 1489d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1490d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1491d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setActivatedStateSupported(boolean flag) { 1492d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng this.mActivatedStateSupported = flag; 1493d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1494d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1495d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 1496d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void requestLayout() { 1497d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will assume that once measured this will not need to resize 1498d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // itself, so there is no need to pass the layout request to the parent 1499d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // view (ListView). 1500d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng forceLayout(); 1501d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1502d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1503d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhotoPosition(PhotoPosition photoPosition) { 1504d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoPosition = photoPosition; 1505d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1506d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1507d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public PhotoPosition getPhotoPosition() { 1508d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoPosition; 1509d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1510d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1511d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1512d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Specifies left and right margin for selection bounds. See also 1513d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * {@link #adjustListItemSelectionBounds(Rect)}. 1514d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1515d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSelectionBoundsHorizontalMargin(int left, int right) { 1516d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSelectionBoundsMarginLeft = left; 1517d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSelectionBoundsMarginRight = right; 1518d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 151927330d80bb6575df2964112d34143125c8af9b78Yorke Lee 152027330d80bb6575df2964112d34143125c8af9b78Yorke Lee /** 152127330d80bb6575df2964112d34143125c8af9b78Yorke Lee * Set drawable resources directly for both the background and the drawable resource 152227330d80bb6575df2964112d34143125c8af9b78Yorke Lee * of the photo view 152327330d80bb6575df2964112d34143125c8af9b78Yorke Lee * 152427330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param backgroundId Id of background resource 152527330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param drawableId Id of drawable resource 152627330d80bb6575df2964112d34143125c8af9b78Yorke Lee */ 152727330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDrawableResource(int backgroundId, int drawableId) { 152827330d80bb6575df2964112d34143125c8af9b78Yorke Lee final ImageView photo = getPhotoView(); 152927330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setScaleType(ImageView.ScaleType.CENTER); 153027330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setBackgroundResource(backgroundId); 153127330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setImageResource(drawableId); 153227330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 153310349f190691f802b8935175dbf38bff74a8a703Yorke Lee 153410349f190691f802b8935175dbf38bff74a8a703Yorke Lee @Override 153510349f190691f802b8935175dbf38bff74a8a703Yorke Lee public boolean onTouchEvent(MotionEvent event) { 153610349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float x = event.getX(); 153710349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float y = event.getY(); 1538538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // If the touch event's coordinates are not within the view's header, then delegate 1539538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // to super.onTouchEvent so that regular view behavior is preserved. Otherwise, consume 1540538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // and ignore the touch event. 1541bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointIsInView(x, y)) { 154210349f190691f802b8935175dbf38bff74a8a703Yorke Lee return super.onTouchEvent(event); 154310349f190691f802b8935175dbf38bff74a8a703Yorke Lee } else { 154410349f190691f802b8935175dbf38bff74a8a703Yorke Lee return true; 154510349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 154610349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 1547bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee 1548bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee private final boolean pointIsInView(float localX, float localY) { 15493d7e2893cb55dc0f1bc4f7e731322973ee09bc1fYorke Lee return localX >= 0 && localX < (getRight() - getLeft()) 15503d7e2893cb55dc0f1bc4f7e731322973ee09bc1fYorke Lee && localY >= 0 && localY < (getBottom() - getTop()); 1551bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee } 1552d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng} 1553