ContactListItemView.java revision 90fbbae42d4628b18e78434e7de13254099b229e
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.Rect; 26d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Typeface; 27d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.drawable.Drawable; 28d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.os.Bundle; 29d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract; 30d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract.Contacts; 31d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.Spannable; 32d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.SpannableString; 33d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils; 34d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils.TruncateAt; 35d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.util.AttributeSet; 36d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.Gravity; 3710349f190691f802b8935175dbf38bff74a8a703Yorke Leeimport android.view.MotionEvent; 38d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.View; 39d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.ViewGroup; 40d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.AbsListView.SelectionBoundsAdjuster; 41d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView; 42d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView.ScaleType; 43d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.QuickContactBadge; 44d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.TextView; 45d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 46d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactPresenceIconUtil; 47d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactStatusUtil; 48d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.R; 49a81953a2b1818066ef5e44817f374ac288bab343Christine Chenimport com.android.contacts.common.format.TextHighlighter; 50cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Chengimport com.android.contacts.common.util.SearchUtil; 51864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Leeimport com.android.contacts.common.util.ViewUtil; 52864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee 5305897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport com.google.common.collect.Lists; 5405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 5505897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.ArrayList; 5605897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.List; 579f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglioimport java.util.Locale; 5805897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Matcher; 5905897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Pattern; 60d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 61d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/** 62d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * A custom view for an item in the contact list. 63d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view contains the contact's photo, a set of text views (for name, status, etc...) and 64d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * icons for presence and call. 65d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view uses no XML file for layout and all the measurements and layouts are done 66d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * in the onMeasure and onLayout methods. 67d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 68d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout puts the contact's photo on the right side of the view, the call icon (if present) 69d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to the left of the photo, the text lines are aligned to the left and the presence icon (if 70d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * present) is set to the left of the status line. 71d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 72d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout also supports a header (used as a header of a group of contacts) that is above the 73d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * contact's data and a divider between contact view. 74d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 75d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 76d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpublic class ContactListItemView extends ViewGroup 77d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng implements SelectionBoundsAdjuster { 78d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 79d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Style values for layout and appearance 80d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The initialized values are defaults if none is provided through xml. 81d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPreferredHeight = 0; 82d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenImageAndText = 0; 83d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenLabelAndData = 0; 84d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconMargin = 4; 85d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconSize = 16; 86d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mTextIndent = 0; 871f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee private int mHeaderWidth; 88d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Drawable mActivatedBackgroundDrawable; 89d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 90d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 91d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mLabelView}, specifying the width ratio between label and data. 92d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 93d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewWidthWeight = 3; 94d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 95d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mDataView}, specifying the width ratio between label and data. 96d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 97d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewWidthWeight = 5; 98d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 99f99a990be713ed35afe64ba8133c5428816390c6Christine Chen protected static class HighlightSequence { 100f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int start; 101f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int end; 102f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 103f99a990be713ed35afe64ba8133c5428816390c6Christine Chen HighlightSequence(int start, int end) { 104f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.start = start; 105f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.end = end; 106f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 107f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 108f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 109f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNameHighlightSequence; 110f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNumberHighlightSequence; 111a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 112a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Highlighting prefix for names. 113a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private String mHighlightedPrefix; 114a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 115d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 116d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Where to put contact photo. This affects the other Views' layout or look-and-feel. 1179f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * 1189f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * TODO: replace enum with int constants 119d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 120d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public enum PhotoPosition { 121d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LEFT, 122d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng RIGHT 123d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1249f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1259f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio static public final PhotoPosition getDefaultPhotoPosition(boolean opposite) { 1269f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final Locale locale = Locale.getDefault(); 1279f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale); 1289f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio switch (layoutDirection) { 1299f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_RTL: 130a9950433dc469d24b314204075a6250d2410e01bAndrew Lee return (opposite ? PhotoPosition.LEFT : PhotoPosition.RIGHT); 1319f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_LTR: 1329f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio default: 133a9950433dc469d24b314204075a6250d2410e01bAndrew Lee return (opposite ? PhotoPosition.RIGHT : PhotoPosition.LEFT); 1349f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1359f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1369f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1379f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio private PhotoPosition mPhotoPosition = getDefaultPhotoPosition(false /* normal/non opposite */); 138d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 139d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Header layout data 1401f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee private int mHeaderBackgroundHeight; 141d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mHeaderTextView; 1421f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee private boolean mIsSectionHeaderEnabled; 143d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 144d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The views inside the contact view 145d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mQuickContactEnabled = true; 146d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private QuickContactBadge mQuickContact; 147d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPhotoView; 148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mNameTextView; 149d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mPhoneticNameTextView; 150d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mLabelView; 151d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mDataView; 152d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mSnippetView; 153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mStatusView; 154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPresenceIcon; 155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ColorStateList mSecondaryTextColor; 157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 158a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDefaultPhotoViewSize = 0; 161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have horizontal padding 163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to align other data in this View. 164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewWidth; 166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have vertical padding. 168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewHeight; 170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * When true all the Views on the right side of the photo should have horizontal padding on 174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * those left assuming there is a photo. 175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepHorizontalPaddingForPhotoView; 177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepVerticalPaddingForPhotoView; 181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * True when {@link #mPhotoViewWidth} and {@link #mPhotoViewHeight} are ready for being used. 184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * False indicates those values should be updated before being used in position calculation. 185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mPhotoViewWidthAndHeightAreReady = false; 187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mNameTextViewHeight; 189f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen private int mNameTextViewTextColor; 190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhoneticNameTextViewHeight; 191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewHeight; 192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewHeight; 193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mSnippetTextViewHeight; 194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mStatusTextViewHeight; 195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 196d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Holds Math.max(mLabelTextViewHeight, mDataViewHeight), assuming Label and Data share the 197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // same row. 198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelAndDataViewMaxHeight; 199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TODO: some TextView fields are using CharArrayBuffer while some are not. Determine which is 201d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // more efficient for each case or in general, and simplify the whole implementation. 202d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Note: if we're sure MARQUEE will be used every time, there's no reason to use 203d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // CharArrayBuffer, since MARQUEE requires Span and thus we need to copy characters inside the 204d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // buffer to Spannable once, while CharArrayBuffer is for directly applying char array to 205d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TextView without any modification. 206d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mDataBuffer = new CharArrayBuffer(128); 207d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mPhoneticNameBuffer = new CharArrayBuffer(128); 208d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 209d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mActivatedStateSupported; 210d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 211d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Rect mBoundsWithoutHeader = new Rect(); 212d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 213d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** A helper used to highlight a prefix in a text field. */ 214a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private final TextHighlighter mTextHighlighter; 215d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private CharSequence mUnknownNameText; 216d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 217d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context) { 218d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context); 219d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 22042210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 221bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNameHighlightSequence = new ArrayList<HighlightSequence>(); 222bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 223d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 224d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 225d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context, AttributeSet attrs) { 226d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context, attrs); 227d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 228d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Read all style values 229d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ContactListItemView); 230d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPreferredHeight = a.getDimensionPixelSize( 231d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_height, mPreferredHeight); 232d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable = a.getDrawable( 233d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_activated_background); 234d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 235d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText = a.getDimensionPixelOffset( 236d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 237d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText); 238d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData = a.getDimensionPixelOffset( 239d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_label_and_data, 240d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData); 241d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin = a.getDimensionPixelOffset( 242d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_margin, 243d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin); 244d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconSize = a.getDimensionPixelOffset( 245d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_size, mPresenceIconSize); 246d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultPhotoViewSize = a.getDimensionPixelOffset( 247d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_photo_size, mDefaultPhotoViewSize); 248d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mTextIndent = a.getDimensionPixelOffset( 249d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_text_indent, mTextIndent); 250d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewWidthWeight = a.getInteger( 251d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_data_width_weight, mDataViewWidthWeight); 252d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight = a.getInteger( 253d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_label_width_weight, 254d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight); 255f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen mNameTextViewTextColor = a.getColor( 256f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen R.styleable.ContactListItemView_list_item_name_text_color, 257f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen mNameTextViewTextColor); 258d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio setPaddingRelative( 260d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 261d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_left, 0), 262d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 263d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_top, 0), 264d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 265d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_right, 0), 266d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 267d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_bottom, 0)); 268d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 26942210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 27042210256d3d584783ac2fb2742088ce57d9da766Yorke Lee 271d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 272d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2733aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee a = getContext().obtainStyledAttributes(R.styleable.Theme); 2743aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee mSecondaryTextColor = a.getColorStateList(R.styleable.Theme_android_textColorSecondary); 275d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 276d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2771f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderWidth = 2781f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee getResources().getDimensionPixelSize(R.dimen.contact_list_section_header_width); 2791f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee 280d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedBackgroundDrawable != null) { 281d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setCallback(this); 282d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 283f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 284f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence = new ArrayList<HighlightSequence>(); 285f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 286d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 287d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 288d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setUnknownNameText(CharSequence unknownNameText) { 289d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mUnknownNameText = unknownNameText; 290d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 291d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 292d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setQuickContactEnabled(boolean flag) { 293d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContactEnabled = flag; 294d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 295d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 296d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 297d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 298d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will match parent's width and wrap content vertically, but make sure 299d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // height is no less than listPreferredItemHeight. 300d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int specWidth = resolveSize(0, widthMeasureSpec); 301f4fcd3def28e5b1168f5160e476c05ad69339adcAndrew Lee final int preferredHeight = mPreferredHeight; 302d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 303d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = 0; 304d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = 0; 305d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = 0; 306d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = 0; 307d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = 0; 308d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = 0; 309d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 0; 310d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 311d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ensurePhotoViewSize(); 312d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 313d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Width each TextView is able to use. 314ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee int effectiveWidth; 315d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // All the other Views will honor the photo, so available width for them may be shrunk. 316d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoViewWidth > 0 || mKeepHorizontalPaddingForPhotoView) { 317d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight() 318d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - (mPhotoViewWidth + mGapBetweenImageAndText); 319d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 320d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight(); 321d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 322d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 323ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (mIsSectionHeaderEnabled) { 324ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee effectiveWidth -= mHeaderWidth + mGapBetweenImageAndText; 325ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 326ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee 327d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Go over all visible text views and measure actual width of each of them. 328d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Also calculate their heights to get the total height for this entire view. 329d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 330d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 33190fbbae42d4628b18e78434e7de13254099b229ePaul Soulos // Calculate width for name text - this parallels similar measurement in onLayout. 332d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int nameTextWidth = effectiveWidth; 333d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition != PhotoPosition.LEFT) { 334d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng nameTextWidth -= mTextIndent; 335d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 336d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.measure( 337d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(nameTextWidth, MeasureSpec.EXACTLY), 338d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 339d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = mNameTextView.getMeasuredHeight(); 340d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 341d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 342d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 343d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.measure( 344d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 345d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 346d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = mPhoneticNameTextView.getMeasuredHeight(); 347d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 348d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 349d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If both data (phone number/email address) and label (type like "MOBILE") are quite long, 350d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // we should ellipsize both using appropriate ratio. 351d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int dataWidth; 352d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int labelWidth; 353d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 354d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 355d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalWidth = effectiveWidth - mGapBetweenLabelAndData; 356d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = ((totalWidth * mDataViewWidthWeight) 357d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng / (mDataViewWidthWeight + mLabelViewWidthWeight)); 358d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = ((totalWidth * mLabelViewWidthWeight) / 359d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng (mDataViewWidthWeight + mLabelViewWidthWeight)); 360d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 361d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = effectiveWidth; 362d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 363d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 364d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 365d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = 0; 366d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 367d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = effectiveWidth; 368d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 369d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 370d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 371d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 372d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 373d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 374d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.measure(MeasureSpec.makeMeasureSpec(dataWidth, MeasureSpec.EXACTLY), 375d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 376d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = mDataView.getMeasuredHeight(); 377d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 378d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 379d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 380d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // For performance reason we don't want AT_MOST usually, but when the picture is 381d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // on right, we need to use it anyway because mDataView is next to mLabelView. 382d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int mode = (mPhotoPosition == PhotoPosition.LEFT 383d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ? MeasureSpec.EXACTLY : MeasureSpec.AT_MOST); 384d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.measure(MeasureSpec.makeMeasureSpec(labelWidth, mode), 385d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 386d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = mLabelView.getMeasuredHeight(); 387d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 388d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = Math.max(mLabelViewHeight, mDataViewHeight); 389d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 390d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 391d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.measure( 392d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 393d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 394d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = mSnippetView.getMeasuredHeight(); 395d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 396d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 397d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Status view height is the biggest of the text view and the presence icon 398d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 399d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.measure( 400d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY), 401d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY)); 402d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = mPresenceIcon.getMeasuredHeight(); 403d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 404d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 405d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView)) { 406d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status are in a same row, so status will be affected by icon size. 407d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int statusWidth; 408d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 409d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = (effectiveWidth - mPresenceIcon.getMeasuredWidth() 410d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - mPresenceIconMargin); 411d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 412d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = effectiveWidth; 413d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 414d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.measure(MeasureSpec.makeMeasureSpec(statusWidth, MeasureSpec.EXACTLY), 415d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 416d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 417d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Math.max(mStatusTextViewHeight, mStatusView.getMeasuredHeight()); 418d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 419d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 420d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Calculate height including padding. 421d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int height = (mNameTextViewHeight + mPhoneticNameTextViewHeight + 422d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + 423d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight + mStatusTextViewHeight); 424d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 425d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure the height is at least as high as the photo 426d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, mPhotoViewHeight + getPaddingBottom() + getPaddingTop()); 427d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 428d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure height is at least the preferred height 429d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, preferredHeight); 430d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 4311f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee // Measure the header if it is visible. 4321f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mHeaderTextView != null && mHeaderTextView.getVisibility() == VISIBLE) { 433d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.measure( 4341f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee MeasureSpec.makeMeasureSpec(mHeaderWidth, MeasureSpec.EXACTLY), 4351f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 4361f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderBackgroundHeight = Math.min(height, mHeaderTextView.getMeasuredHeight()); 437d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 438d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 439d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMeasuredDimension(specWidth, height); 440d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 441d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 442d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 443d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 444d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int height = bottom - top; 445d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int width = right - left; 446d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 447d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Determine the vertical bounds by laying out the header first. 448d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int topBound = 0; 449d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int bottomBound = height; 450d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int leftBound = getPaddingLeft(); 451d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int rightBound = width - getPaddingRight(); 452d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 453864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee final boolean isLayoutRtl = ViewUtil.isViewLayoutRtl(this); 45409f15e70e86d92ae0f4c15a726b777f170845a3cYorke Lee 4551f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee // Put the section header on the left side of the contact view. 4561f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mIsSectionHeaderEnabled) { 4571f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mHeaderTextView != null) { 4581f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderTextView.layout( 4591f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee isLayoutRtl ? rightBound - mHeaderWidth : leftBound, 4601f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee topBound, 4611f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee isLayoutRtl ? rightBound : leftBound + mHeaderWidth, 4621f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderBackgroundHeight); 4631f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 4641f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (isLayoutRtl) { 4651f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee rightBound -= mHeaderWidth; 4661f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } else { 4671f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee leftBound += mHeaderWidth; 4681f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 469d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 470d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 471ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee mBoundsWithoutHeader.set(leftBound, topBound, rightBound, bottomBound); 472ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee 473ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (mIsSectionHeaderEnabled) { 474ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (isLayoutRtl) { 475ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee rightBound -= mGapBetweenImageAndText; 476ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } else { 477ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee leftBound += mGapBetweenImageAndText; 478ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 479ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 480d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 481d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 482d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setBounds(mBoundsWithoutHeader); 483d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 484d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 485d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final View photoView = mQuickContact != null ? mQuickContact : mPhotoView; 486d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 487d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the left most view. All the other Views should on the right of the photo. 488d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 489d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 490d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 491d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 492d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound, 493d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 494d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound + mPhotoViewWidth, 495d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 496d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 497d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else if (mKeepHorizontalPaddingForPhotoView) { 498d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Draw nothing but keep the padding. 499d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 500d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 501d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 502d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the right most view. Right bound should be adjusted that way. 503d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 504d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 505d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 506d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 507d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound - mPhotoViewWidth, 508d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 509d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 510d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 511d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 5129f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else if (mKeepHorizontalPaddingForPhotoView) { 5139f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio // Draw nothing but keep the padding. 5149f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 515d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 516d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 517d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Add indent between left-most padding and texts. 518d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mTextIndent; 519d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 520d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 521d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center text vertically 522d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalTextHeight = mNameTextViewHeight + mPhoneticNameTextViewHeight + 523d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + mSnippetTextViewHeight + mStatusTextViewHeight; 524d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int textTopBound = (bottomBound + topBound - totalTextHeight) / 2; 525d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 526d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Layout all text view and presence icon 527d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Put name TextView first 528d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 529d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.layout(leftBound, 530d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 531d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 532d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mNameTextViewHeight); 533d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mNameTextViewHeight; 534d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 535d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 536d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status 5379f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isLayoutRtl) { 5389f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusRightBound = rightBound; 5399f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 5409f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 5419f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 5429f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound - iconWidth, 5439f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5449f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 5459f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5469f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound -= (iconWidth + mPresenceIconMargin); 5479f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 548d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 5499f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 5509f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(leftBound, 5519f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5529f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound, 5539f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5549f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 5559f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else { 5569f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusLeftBound = leftBound; 5579f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 5589f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 5599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 5609f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound, 5619f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5629f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound + iconWidth, 5639f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5649f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusLeftBound += (iconWidth + mPresenceIconMargin); 5659f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 5669f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 5679f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 5689f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(statusLeftBound, 5699f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5709f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 5719f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5729f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 573d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 574d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 575d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView) || isVisible(mPresenceIcon)) { 576d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mStatusTextViewHeight; 577d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 578d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 579d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Rest of text views 580d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int dataLeftBound = leftBound; 581d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 582d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.layout(leftBound, 583d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 584d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 585d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mPhoneticNameTextViewHeight); 586d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mPhoneticNameTextViewHeight; 587d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 588d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 589d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Label and Data align bottom. 590d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 591d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 592d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on left, label is placed on the right edge of the list item. 593d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(rightBound - mLabelView.getMeasuredWidth(), 594d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 595d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 596d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 597d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= mLabelView.getMeasuredWidth(); 598d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 599d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on right, label is placed on the left of data view. 600d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound = leftBound + mLabelView.getMeasuredWidth(); 601d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(leftBound, 602d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 603d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound, 604d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 605d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound += mGapBetweenLabelAndData; 606d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 607d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 608d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 609d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 610d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.layout(dataLeftBound, 611d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mDataViewHeight, 612d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 613d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 614d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 615d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView) || isVisible(mDataView)) { 616d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mLabelAndDataViewMaxHeight; 617d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 618d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 619d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 620d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.layout(leftBound, 621d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 622d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 623d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mSnippetTextViewHeight); 624d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 625d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 626d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 627d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 628d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void adjustListItemSelectionBounds(Rect bounds) { 629d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.top += mBoundsWithoutHeader.top; 630d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng bounds.bottom = bounds.top + mBoundsWithoutHeader.height(); 631ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee bounds.left = mBoundsWithoutHeader.left; 632ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee bounds.right = mBoundsWithoutHeader.right; 633d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 634d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 635d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean isVisible(View view) { 636d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return view != null && view.getVisibility() == View.VISIBLE; 637d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 638d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 639d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 640d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Extracts width and height from the style 641d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 642d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void ensurePhotoViewSize() { 643d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mPhotoViewWidthAndHeightAreReady) { 644d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = mPhotoViewHeight = getDefaultPhotoViewSize(); 645d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled && mPhotoView == null) { 646d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepHorizontalPaddingForPhotoView) { 647d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = 0; 648d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 649d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepVerticalPaddingForPhotoView) { 650d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewHeight = 0; 651d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 652d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 653d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 654d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = true; 655d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 656d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 657d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 658d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected int getDefaultPhotoViewSize() { 659d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDefaultPhotoViewSize; 660d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 661d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 662d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 663d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Gets a LayoutParam that corresponds to the default photo size. 664d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 665d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @return A new LayoutParam. 666d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 667d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private LayoutParams getDefaultPhotoLayoutParams() { 668d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LayoutParams params = generateDefaultLayoutParams(); 669d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.width = getDefaultPhotoViewSize(); 670d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.height = params.width; 671d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return params; 672d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 673d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 674d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 675d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void drawableStateChanged() { 676d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.drawableStateChanged(); 677d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 678d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setState(getDrawableState()); 679d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 680d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 681d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 682d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 683d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean verifyDrawable(Drawable who) { 684d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return who == mActivatedBackgroundDrawable || super.verifyDrawable(who); 685d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 686d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 687d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 688d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void jumpDrawablesToCurrentState() { 689d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.jumpDrawablesToCurrentState(); 690d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 691d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.jumpToCurrentState(); 692d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 693d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 694d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 695d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 696d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void dispatchDraw(Canvas canvas) { 697d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 698d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.draw(canvas); 699d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 700d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 701d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.dispatchDraw(canvas); 702d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 703d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 704d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 705d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets section header or makes it invisible if the title is null. 706d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 707d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSectionHeader(String title) { 708d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(title)) { 709d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderTextView == null) { 710e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView = new TextView(getContext()); 711e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView.setTextAppearance(getContext(), R.style.SectionHeaderStyle); 712ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee mHeaderTextView.setGravity(Gravity.CENTER_VERTICAL | 713ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee (ViewUtil.isViewLayoutRtl(this) ? Gravity.RIGHT : Gravity.LEFT)); 714d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mHeaderTextView); 715d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 716d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mHeaderTextView, title); 717d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setVisibility(View.VISIBLE); 718d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setAllCaps(true); 7191f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } else if (mHeaderTextView != null) { 7201f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderTextView.setVisibility(View.GONE); 721d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 722d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 723d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 7241f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee public void setIsSectionHeaderEnabled(boolean isSectionHeaderEnabled) { 7251f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mIsSectionHeaderEnabled = isSectionHeaderEnabled; 7261f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 7271f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee 728d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 729d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the quick contact badge, creating it if necessary. 730d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 731d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public QuickContactBadge getQuickContact() { 732d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled) { 733d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng throw new IllegalStateException("QuickContact is disabled for this view"); 734d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 735d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact == null) { 736e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact = new QuickContactBadge(getContext()); 7373f9c2f426058413055fa54c08c69ad9461717658Yorke Lee mQuickContact.setOverlay(null); 738d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams()); 739d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 740e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 741d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.string.description_quick_contact_for, mNameTextView.getText())); 742d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 743d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 744d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mQuickContact); 745d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 746d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 747d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mQuickContact; 748d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 749d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 750d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 751d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the photo view, creating it if necessary. 752d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 753d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ImageView getPhotoView() { 754d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView == null) { 755e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhotoView = new ImageView(getContext()); 756d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams()); 757d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Quick contact style used above will set a background - remove it 758d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setBackground(null); 759d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhotoView); 760d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 761d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 762d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoView; 763d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 764d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 765d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 766d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 767d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 768d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView() { 769d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removePhotoView(false, true); 770d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 771d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 772d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 773d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 774d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 775d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepHorizontalPadding True means data on the right side will have 776d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * padding on left, pretending there is still a photo view. 777d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepVerticalPadding True means the View will have some height 778d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * enough for accommodating a photo view. 779d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 780d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView(boolean keepHorizontalPadding, boolean keepVerticalPadding) { 781d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 782d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepHorizontalPaddingForPhotoView = keepHorizontalPadding; 783d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepVerticalPaddingForPhotoView = keepVerticalPadding; 784d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView != null) { 785d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhotoView); 786d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView = null; 787d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 788d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact != null) { 789d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mQuickContact); 790d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact = null; 791d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 792d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 793d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 794d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 795d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets a word prefix that will be highlighted if encountered in fields like 796a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * name and search snippet. This will disable the mask highlighting for names. 797d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * <p> 798d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * NOTE: must be all upper-case 799d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 800bd80fd64b9ff94c9ffbdb843beb4b363bb209463Chiao Cheng public void setHighlightedPrefix(String upperCasePrefix) { 801d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHighlightedPrefix = upperCasePrefix; 802a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 803a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 804a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 805f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Clears previously set highlight sequences for the view. 806a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 807f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void clearHighlightSequences() { 808f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.clear(); 809f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.clear(); 810a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mHighlightedPrefix = null; 811a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 812a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 813a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 814f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the name highlighter. 815f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 816f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 817f99a990be713ed35afe64ba8133c5428816390c6Christine Chen */ 818f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNameHighlightSequence(int start, int end) { 819f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.add(new HighlightSequence(start, end)); 820f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 821f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 822f99a990be713ed35afe64ba8133c5428816390c6Christine Chen /** 823f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the number highlighter. 824f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 825f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 826a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 827f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNumberHighlightSequence(int start, int end) { 828f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.add(new HighlightSequence(start, end)); 829d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 830d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 831d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 832d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the contact name, creating it if necessary. 833d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 834d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getNameTextView() { 835d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView == null) { 836e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mNameTextView = new TextView(getContext()); 837d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setSingleLine(true); 838d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setEllipsize(getTextEllipsis()); 83990a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mNameTextView.setTextAppearance(getContext(), R.style.TextAppearanceMedium); 840f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen mNameTextView.setTextColor(mNameTextViewTextColor); 841d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Manually call setActivated() since this view may be added after the first 842d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // setActivated() call toward this whole item view. 843d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setActivated(isActivated()); 844d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setGravity(Gravity.CENTER_VERTICAL); 8459f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 8469f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setId(R.id.cliv_name_textview); 847d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mNameTextView); 848d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 849d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mNameTextView; 850d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 851d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 852d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 853d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the phonetic name. 854d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 855d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhoneticName(char[] text, int size) { 856d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 857d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 858d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(View.GONE); 859d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 860d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 861d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getPhoneticNameTextView(); 862d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mPhoneticNameTextView, text, size); 863d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(VISIBLE); 864d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 865d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 866d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 867d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 868d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the phonetic name, creating it if necessary. 869d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 870d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getPhoneticNameTextView() { 871d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView == null) { 872e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView = new TextView(getContext()); 873d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setSingleLine(true); 874d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setEllipsize(getTextEllipsis()); 875e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 876d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD); 877d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setActivated(isActivated()); 8789f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPhoneticNameTextView.setId(R.id.cliv_phoneticname_textview); 879d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhoneticNameTextView); 880d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 881d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhoneticNameTextView; 882d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 883d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 884d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 885d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data label. 886d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 887d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setLabel(CharSequence text) { 888d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 889d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView != null) { 890d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(View.GONE); 891d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 892d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 893d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getLabelView(); 894d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mLabelView, text); 895d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(VISIBLE); 896d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 897d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 898d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 899d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 900d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data label, creating it if necessary. 901d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 902d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getLabelView() { 903d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView == null) { 904e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mLabelView = new TextView(getContext()); 905d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setSingleLine(true); 906d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setEllipsize(getTextEllipsis()); 90790a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mLabelView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 908d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 909d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setAllCaps(true); 9109f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setGravity(Gravity.END); 911d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 912d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD); 913d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 914d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setActivated(isActivated()); 9159f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setId(R.id.cliv_label_textview); 916d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mLabelView); 917d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 918d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mLabelView; 919d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 920d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 921d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 922d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data element. 923d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 924a81953a2b1818066ef5e44817f374ac288bab343Christine Chen public void setData(char[] text, int size) { 925d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 926d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView != null) { 927d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(View.GONE); 928d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 929d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 930d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getDataView(); 931d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mDataView, text, size); 932d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(VISIBLE); 933a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 934a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 935a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 936a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 937a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * Sets phone number for a list item. This takes care of number highlighting if the highlight 938a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * mask exists. 939a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 94062dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee public void setPhoneNumber(String text, String countryIso) { 941a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (text == null) { 942a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mDataView != null) { 943a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(View.GONE); 9449f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 945a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } else { 946a81953a2b1818066ef5e44817f374ac288bab343Christine Chen getDataView(); 94762dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee 948eabf27292960173c0600e022c64919453741c93fYorke Lee // TODO: Format number using PhoneNumberUtils.formatNumber before assigning it to 949eabf27292960173c0600e022c64919453741c93fYorke Lee // mDataView. Make sure that determination of the highlight sequences are done only 950eabf27292960173c0600e022c64919453741c93fYorke Lee // after number formatting. 95162dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee 952a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Sets phone number texts for display after highlighting it, if applicable. 95362dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee // CharSequence textToSet = text; 954f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString textToSet = new SpannableString(text); 955f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 956f99a990be713ed35afe64ba8133c5428816390c6Christine Chen if (mNumberHighlightSequence.size() != 0) { 957f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final HighlightSequence highlightSequence = mNumberHighlightSequence.get(0); 958f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(textToSet, highlightSequence.start, 959f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 960a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 961f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 962a81953a2b1818066ef5e44817f374ac288bab343Christine Chen setMarqueeText(mDataView, textToSet); 963a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(VISIBLE); 964a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 965a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // We have a phone number as "mDataView" so make it always LTR and VIEW_START 966a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextDirection(View.TEXT_DIRECTION_LTR); 967a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 968d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 969d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 970d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 971d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, char[] text, int size) { 972d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 973d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(textView, new String(text, 0, size)); 974d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 975d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text, 0, size); 976d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 977d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 978d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 979d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, CharSequence text) { 980d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 981d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // To show MARQUEE correctly (with END effect during non-active state), we need 982d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // to build Spanned with MARQUEE in addition to TextView's ellipsize setting. 983d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final SpannableString spannable = new SpannableString(text); 984d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng spannable.setSpan(TruncateAt.MARQUEE, 0, spannable.length(), 985d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 986d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(spannable); 987d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 988d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text); 989d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 990d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 991d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 992d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 993d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data text, creating it if necessary. 994d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 995d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getDataView() { 996d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView == null) { 997e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mDataView = new TextView(getContext()); 998d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setSingleLine(true); 999d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setEllipsize(getTextEllipsis()); 100090a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mDataView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 1001d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setActivated(isActivated()); 10029f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mDataView.setId(R.id.cliv_data_view); 1003d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mDataView); 1004d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1005d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDataView; 1006d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1007d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1008d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1009d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the search snippet. 1010d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1011d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSnippet(String text) { 1012d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1013d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView != null) { 1014d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(View.GONE); 1015d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1016d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1017f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix); 1018d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(VISIBLE); 1019d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1020d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1021d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1022d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1023d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the search snippet, creating it if necessary. 1024d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1025d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getSnippetView() { 1026d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView == null) { 1027e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView = new TextView(getContext()); 1028d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setSingleLine(true); 1029d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setEllipsize(getTextEllipsis()); 1030e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1031d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setActivated(isActivated()); 1032d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mSnippetView); 1033d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1034d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mSnippetView; 1035d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1036d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1037d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1038d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the status, creating it if necessary. 1039d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1040d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getStatusView() { 1041d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView == null) { 1042e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView = new TextView(getContext()); 1043d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setSingleLine(true); 1044d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setEllipsize(getTextEllipsis()); 1045e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1046d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setTextColor(mSecondaryTextColor); 1047d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setActivated(isActivated()); 10489f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 1049d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mStatusView); 1050d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1051d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mStatusView; 1052d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1053d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1054d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1055d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the status. 1056d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1057d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setStatus(CharSequence text) { 1058d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1059d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView != null) { 1060d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(View.GONE); 1061d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1062d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1063d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getStatusView(); 1064d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mStatusView, text); 1065d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(VISIBLE); 1066d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1067d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1068d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1069d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1070d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates the presence icon view. 1071d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1072d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPresence(Drawable icon) { 1073d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (icon != null) { 1074d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon == null) { 1075e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPresenceIcon = new ImageView(getContext()); 1076d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPresenceIcon); 1077d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1078d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setImageDrawable(icon); 1079d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setScaleType(ScaleType.CENTER); 1080d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.VISIBLE); 1081d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1082d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon != null) { 1083d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.GONE); 1084d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1085d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1086d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1087d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1088d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TruncateAt getTextEllipsis() { 1089d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return TruncateAt.MARQUEE; 1090d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1091d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1092d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showDisplayName(Cursor cursor, int nameColumnIndex, int displayOrder) { 1093d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng CharSequence name = cursor.getString(nameColumnIndex); 109427330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 109527330d80bb6575df2964112d34143125c8af9b78Yorke Lee 109627330d80bb6575df2964112d34143125c8af9b78Yorke Lee // Since the quick contact content description is derived from the display name and there is 109727330d80bb6575df2964112d34143125c8af9b78Yorke Lee // no guarantee that when the quick contact is initialized the display name is already set, 109827330d80bb6575df2964112d34143125c8af9b78Yorke Lee // do it here too. 109927330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (mQuickContact != null) { 1100e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 110127330d80bb6575df2964112d34143125c8af9b78Yorke Lee R.string.description_quick_contact_for, mNameTextView.getText())); 110227330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 110327330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 110427330d80bb6575df2964112d34143125c8af9b78Yorke Lee 110527330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name, boolean highlight) { 110627330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (!TextUtils.isEmpty(name) && highlight) { 110727330d80bb6575df2964112d34143125c8af9b78Yorke Lee clearHighlightSequences(); 110827330d80bb6575df2964112d34143125c8af9b78Yorke Lee addNameHighlightSequence(0, name.length()); 110927330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 111027330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 111127330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 111227330d80bb6575df2964112d34143125c8af9b78Yorke Lee 111327330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name) { 1114d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(name)) { 1115a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Chooses the available highlighting method for highlighting. 1116a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mHighlightedPrefix != null) { 1117a81953a2b1818066ef5e44817f374ac288bab343Christine Chen name = mTextHighlighter.applyPrefixHighlight(name, mHighlightedPrefix); 1118f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } else if (mNameHighlightSequence.size() != 0) { 1119f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString spannableName = new SpannableString(name); 1120f99a990be713ed35afe64ba8133c5428816390c6Christine Chen for (HighlightSequence highlightSequence : mNameHighlightSequence) { 1121f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(spannableName, highlightSequence.start, 1122f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 1123f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 1124f99a990be713ed35afe64ba8133c5428816390c6Christine Chen name = spannableName; 1125a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1126d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1127d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng name = mUnknownNameText; 1128d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1129d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(getNameTextView(), name); 1130d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1131d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1132d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hideDisplayName() { 1133d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 1134d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mNameTextView); 1135d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView = null; 1136d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1137d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1138d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1139d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPhoneticName(Cursor cursor, int phoneticNameColumnIndex) { 1140d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(phoneticNameColumnIndex, mPhoneticNameBuffer); 1141d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int phoneticNameSize = mPhoneticNameBuffer.sizeCopied; 1142d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (phoneticNameSize != 0) { 1143d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(mPhoneticNameBuffer.data, phoneticNameSize); 1144d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1145d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(null, 0); 1146d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1147d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1149d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hidePhoneticName() { 1150d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 1151d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhoneticNameTextView); 1152d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView = null; 1153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets the proper icon (star or presence or nothing) and/or status message. 1158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPresenceAndStatusMessage(Cursor cursor, int presenceColumnIndex, 1160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int contactStatusColumnIndex) { 1161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Drawable icon = null; 1162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int presence = 0; 1163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!cursor.isNull(presenceColumnIndex)) { 1164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng presence = cursor.getInt(presenceColumnIndex); 1165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng icon = ContactPresenceIconUtil.getPresenceIcon(getContext(), presence); 1166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPresence(icon); 1168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String statusMessage = null; 1170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (contactStatusColumnIndex != 0 && !cursor.isNull(contactStatusColumnIndex)) { 1171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = cursor.getString(contactStatusColumnIndex); 1172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If there is no status message from the contact, but there was a presence value, then use 1174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // the default status message string 1175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (statusMessage == null && presence != 0) { 1176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = ContactStatusUtil.getStatusString(getContext(), presence); 1177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setStatus(statusMessage); 1179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Shows search snippet. 1183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showSnippet(Cursor cursor, int summarySnippetColumnIndex) { 1185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (cursor.getColumnCount() <= summarySnippetColumnIndex) { 1186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(null); 1187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return; 1188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 119005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng String snippet = cursor.getString(summarySnippetColumnIndex); 1191cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Do client side snippeting if provider didn't do it 119305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Bundle extras = cursor.getExtras(); 1194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (extras.getBoolean(ContactsContract.DEFERRED_SNIPPETING)) { 1195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 119605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final String query = extras.getString(ContactsContract.DEFERRED_SNIPPETING_QUERY); 1197cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1198cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng String displayName = null; 1199cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int displayNameIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); 1200cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (displayNameIndex >= 0) { 1201cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng displayName = cursor.getString(displayNameIndex); 120205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1203cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1204cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng snippet = updateSnippet(snippet, query, displayName); 1205cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 120605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 120705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (snippet != null) { 120805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int from = 0; 120905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int to = snippet.length(); 121005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int start = snippet.indexOf(DefaultContactListAdapter.SNIPPET_START_MATCH); 121105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (start == -1) { 121205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = null; 121305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 121405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int firstNl = snippet.lastIndexOf('\n', start); 121505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (firstNl != -1) { 121605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng from = firstNl + 1; 121705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 121805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int end = snippet.lastIndexOf(DefaultContactListAdapter.SNIPPET_END_MATCH); 121905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (end != -1) { 122005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int lastNl = snippet.indexOf('\n', end); 122105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (lastNl != -1) { 122205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng to = lastNl; 122305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 122405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1225d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 122605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng StringBuilder sb = new StringBuilder(); 122705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng for (int i = from; i < to; i++) { 122805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng char c = snippet.charAt(i); 122905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (c != DefaultContactListAdapter.SNIPPET_START_MATCH && 123005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng c != DefaultContactListAdapter.SNIPPET_END_MATCH) { 123105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng sb.append(c); 123205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1233d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 123405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = sb.toString(); 1235d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1236d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1237d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1238cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1239d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(snippet); 1240d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1241d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1242cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng /** 1243cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * Used for deferred snippets from the database. The contents come back as large strings which 1244cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * need to be extracted for display. 1245cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * 1246cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param snippet The snippet from the database. 1247cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param query The search query substring. 1248cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param displayName The contact display name. 1249cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @return The proper snippet to display. 1250cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng */ 1251cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String updateSnippet(String snippet, String query, String displayName) { 1252cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1253cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (TextUtils.isEmpty(snippet) || TextUtils.isEmpty(query)) { 1254cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1255cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1256cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng query = SearchUtil.cleanStartAndEndOfSearchQuery(query.toLowerCase()); 1257cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1258cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // If the display name already contains the query term, return empty - snippets should 1259cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // not be needed in that case. 1260cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!TextUtils.isEmpty(displayName)) { 1261cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final String lowerDisplayName = displayName.toLowerCase(); 1262cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final List<String> nameTokens = split(lowerDisplayName); 1263cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng for (String nameToken : nameTokens) { 1264cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (nameToken.startsWith(query)) { 1265cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1266cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1267cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1268cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1269cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1270cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // The snippet may contain multiple data lines. 1271cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show the first line that matches the query. 1272cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final SearchUtil.MatchedLine matched = SearchUtil.findMatchingLine(snippet, query); 1273cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1274cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched != null && matched.line != null) { 1275cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Tokenize for long strings since the match may be at the end of it. 1276cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Skip this part for short strings since the whole string will be displayed. 1277cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Most contact strings are short so the snippetize method will be called infrequently. 1278cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final int lengthThreshold = getResources().getInteger( 1279cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng R.integer.snippet_length_before_tokenize); 1280cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched.line.length() > lengthThreshold) { 1281cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return snippetize(matched.line, matched.startIndex, lengthThreshold); 1282cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } else { 1283cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return matched.line; 1284cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1285cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1286cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1287cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // No match found. 1288cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1289cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1290cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1291cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String snippetize(String line, int matchIndex, int maxLength) { 1292cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show up to maxLength characters. But we only show full tokens so show the last full token 1293cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // up to maxLength characters. So as many starting tokens as possible before trying ending 1294cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // tokens. 1295cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int remainingLength = maxLength; 1296cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int tempRemainingLength = remainingLength; 1297cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1298cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Start the end token after the matched query. 1299cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int index = matchIndex; 1300cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int endTokenIndex = index; 1301cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1302cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find the match token first. 1303cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length()) { 1304cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1305cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1306cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1307cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng break; 1308cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1309cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1310cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1311cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1312cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1313cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find as much content before the match. 1314cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = matchIndex - 1; 1315cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1316cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int startTokenIndex = matchIndex; 1317cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index > -1 && tempRemainingLength > 0) { 1318cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1319cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng startTokenIndex = index; 1320cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1321cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1322cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1323cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index--; 1324cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1325cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1326cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = endTokenIndex; 1327cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1328cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find remaining content at after match. 1329cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length() && tempRemainingLength > 0) { 1330cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1331cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1332cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1333cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1334cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1335cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1336cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Append ellipse if there is content before or after. 1337cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final StringBuilder sb = new StringBuilder(); 1338cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (startTokenIndex > 0) { 1339cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1340cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1341cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append(line.substring(startTokenIndex, endTokenIndex)); 1342cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (endTokenIndex < line.length()) { 1343cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1344cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1345cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return sb.toString(); 1346cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1347cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 134805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static final Pattern SPLIT_PATTERN = Pattern.compile( 134905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng "([\\w-\\.]+)@((?:[\\w]+\\.)+)([a-zA-Z]{2,4})|[\\w]+"); 135005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 135105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng /** 135205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * Helper method for splitting a string into tokens. The lists passed in are populated with 135305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * the 135405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * tokens and offsets into the content of each token. The tokenization function parses e-mail 135505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * addresses as a single token; otherwise it splits on any non-alphanumeric character. 135605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * 135705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @param content Content to split. 135805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @return List of token strings. 135905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng */ 136005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static List<String> split(String content) { 136105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Matcher matcher = SPLIT_PATTERN.matcher(content); 136205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final ArrayList<String> tokens = Lists.newArrayList(); 136305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng while (matcher.find()) { 136405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng tokens.add(matcher.group()); 136505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 136605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng return tokens; 136705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 136805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 1369d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 13707a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner * Shows data element. 1371d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1372d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showData(Cursor cursor, int dataColumnIndex) { 1373d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(dataColumnIndex, mDataBuffer); 13747a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner setData(mDataBuffer.data, mDataBuffer.sizeCopied); 13757a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner } 13767a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner 1377d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setActivatedStateSupported(boolean flag) { 1378d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng this.mActivatedStateSupported = flag; 1379d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1380d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1381d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 1382d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void requestLayout() { 1383d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will assume that once measured this will not need to resize 1384d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // itself, so there is no need to pass the layout request to the parent 1385d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // view (ListView). 1386d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng forceLayout(); 1387d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1388d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1389d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhotoPosition(PhotoPosition photoPosition) { 1390d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoPosition = photoPosition; 1391d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1392d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1393d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public PhotoPosition getPhotoPosition() { 1394d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoPosition; 1395d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1396d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1397d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 139827330d80bb6575df2964112d34143125c8af9b78Yorke Lee * Set drawable resources directly for both the background and the drawable resource 139927330d80bb6575df2964112d34143125c8af9b78Yorke Lee * of the photo view 140027330d80bb6575df2964112d34143125c8af9b78Yorke Lee * 140127330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param backgroundId Id of background resource 140227330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param drawableId Id of drawable resource 140327330d80bb6575df2964112d34143125c8af9b78Yorke Lee */ 140427330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDrawableResource(int backgroundId, int drawableId) { 140527330d80bb6575df2964112d34143125c8af9b78Yorke Lee final ImageView photo = getPhotoView(); 140627330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setScaleType(ImageView.ScaleType.CENTER); 140727330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setBackgroundResource(backgroundId); 140827330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setImageResource(drawableId); 140927330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 141010349f190691f802b8935175dbf38bff74a8a703Yorke Lee 141110349f190691f802b8935175dbf38bff74a8a703Yorke Lee @Override 141210349f190691f802b8935175dbf38bff74a8a703Yorke Lee public boolean onTouchEvent(MotionEvent event) { 141310349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float x = event.getX(); 141410349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float y = event.getY(); 1415538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // If the touch event's coordinates are not within the view's header, then delegate 1416538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // to super.onTouchEvent so that regular view behavior is preserved. Otherwise, consume 1417538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // and ignore the touch event. 1418bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointIsInView(x, y)) { 141910349f190691f802b8935175dbf38bff74a8a703Yorke Lee return super.onTouchEvent(event); 142010349f190691f802b8935175dbf38bff74a8a703Yorke Lee } else { 142110349f190691f802b8935175dbf38bff74a8a703Yorke Lee return true; 142210349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 142310349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 1424bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee 1425bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee private final boolean pointIsInView(float localX, float localY) { 14263d7e2893cb55dc0f1bc4f7e731322973ee09bc1fYorke Lee return localX >= 0 && localX < (getRight() - getLeft()) 14273d7e2893cb55dc0f1bc4f7e731322973ee09bc1fYorke Lee && localY >= 0 && localY < (getBottom() - getTop()); 1428bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee } 1429d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng} 1430