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; 2558a793ee1253f8f46dd7f754a51f61a6bbcdce60Andrew Leeimport android.graphics.Color; 26d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Rect; 27d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.Typeface; 28d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.graphics.drawable.Drawable; 29d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.os.Bundle; 30d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract; 31d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.provider.ContactsContract.Contacts; 32d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.Spannable; 33d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.SpannableString; 34d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils; 35d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.text.TextUtils.TruncateAt; 36d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.util.AttributeSet; 373bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapatiimport android.util.TypedValue; 38d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.Gravity; 3910349f190691f802b8935175dbf38bff74a8a703Yorke Leeimport android.view.MotionEvent; 40d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.View; 41d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.view.ViewGroup; 42d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.AbsListView.SelectionBoundsAdjuster; 43d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView; 44d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.ImageView.ScaleType; 45d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.QuickContactBadge; 46d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport android.widget.TextView; 47d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 48d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactPresenceIconUtil; 49d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.ContactStatusUtil; 50d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengimport com.android.contacts.common.R; 51a81953a2b1818066ef5e44817f374ac288bab343Christine Chenimport com.android.contacts.common.format.TextHighlighter; 52cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Chengimport com.android.contacts.common.util.SearchUtil; 53864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Leeimport com.android.contacts.common.util.ViewUtil; 54864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee 5505897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport com.google.common.collect.Lists; 5605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 5705897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.ArrayList; 5805897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.List; 599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglioimport java.util.Locale; 6005897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Matcher; 6105897c8e016942e10f0ef6f0da02d339480d4748Chiao Chengimport java.util.regex.Pattern; 62d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 63d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng/** 64d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * A custom view for an item in the contact list. 65d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view contains the contact's photo, a set of text views (for name, status, etc...) and 66d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * icons for presence and call. 67d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The view uses no XML file for layout and all the measurements and layouts are done 68d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * in the onMeasure and onLayout methods. 69d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 70d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout puts the contact's photo on the right side of the view, the call icon (if present) 71d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to the left of the photo, the text lines are aligned to the left and the presence icon (if 72d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * present) is set to the left of the status line. 73d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 74d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * The layout also supports a header (used as a header of a group of contacts) that is above the 75d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * contact's data and a divider between contact view. 76d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 77d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 78d6bba124836ec2f528b329759e38fda6297fec49Chiao Chengpublic class ContactListItemView extends ViewGroup 79d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng implements SelectionBoundsAdjuster { 80d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 81d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Style values for layout and appearance 82d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The initialized values are defaults if none is provided through xml. 83d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPreferredHeight = 0; 84d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenImageAndText = 0; 85d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mGapBetweenLabelAndData = 0; 86d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconMargin = 4; 87d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPresenceIconSize = 16; 88d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mTextIndent = 0; 897961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee private int mTextOffsetTop; 903bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati private int mNameTextViewTextSize; 911f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee private int mHeaderWidth; 92d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Drawable mActivatedBackgroundDrawable; 93d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 94f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati // Set in onLayout. Represent left and right position of the View on the screen. 95f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati private int mLeftOffset; 96f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati private int mRightOffset; 97f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati 98d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 99d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mLabelView}, specifying the width ratio between label and data. 100d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 101d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewWidthWeight = 3; 102d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 103d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Used with {@link #mDataView}, specifying the width ratio between label and data. 104d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 105d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewWidthWeight = 5; 106d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 107f99a990be713ed35afe64ba8133c5428816390c6Christine Chen protected static class HighlightSequence { 108f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int start; 109f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private final int end; 110f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 111f99a990be713ed35afe64ba8133c5428816390c6Christine Chen HighlightSequence(int start, int end) { 112f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.start = start; 113f99a990be713ed35afe64ba8133c5428816390c6Christine Chen this.end = end; 114f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 115f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 116f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 117f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNameHighlightSequence; 118f99a990be713ed35afe64ba8133c5428816390c6Christine Chen private ArrayList<HighlightSequence> mNumberHighlightSequence; 119a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 120a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Highlighting prefix for names. 121a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private String mHighlightedPrefix; 122a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 123d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 124d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Where to put contact photo. This affects the other Views' layout or look-and-feel. 1259f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * 1269f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio * TODO: replace enum with int constants 127d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 128d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public enum PhotoPosition { 129d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LEFT, 130d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng RIGHT 131d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1329f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1339f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio static public final PhotoPosition getDefaultPhotoPosition(boolean opposite) { 1349f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final Locale locale = Locale.getDefault(); 1359f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale); 1369f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio switch (layoutDirection) { 1379f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_RTL: 138a9950433dc469d24b314204075a6250d2410e01bAndrew Lee return (opposite ? PhotoPosition.LEFT : PhotoPosition.RIGHT); 1399f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio case View.LAYOUT_DIRECTION_LTR: 1409f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio default: 141a9950433dc469d24b314204075a6250d2410e01bAndrew Lee return (opposite ? PhotoPosition.RIGHT : PhotoPosition.LEFT); 1429f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1439f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 1449f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 1459f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio private PhotoPosition mPhotoPosition = getDefaultPhotoPosition(false /* normal/non opposite */); 146d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 147d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Header layout data 148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mHeaderTextView; 1491f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee private boolean mIsSectionHeaderEnabled; 150d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 151d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // The views inside the contact view 152d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mQuickContactEnabled = true; 153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private QuickContactBadge mQuickContact; 154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPhotoView; 155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mNameTextView; 156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mPhoneticNameTextView; 157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mLabelView; 158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mDataView; 159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mSnippetView; 160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TextView mStatusView; 161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ImageView mPresenceIcon; 162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private ColorStateList mSecondaryTextColor; 164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 165a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDefaultPhotoViewSize = 0; 168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have horizontal padding 170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * to align other data in this View. 171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewWidth; 173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Can be effective even when {@link #mPhotoView} is null, as we want to have vertical padding. 175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhotoViewHeight; 177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * When true all the Views on the right side of the photo should have horizontal padding on 181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * those left assuming there is a photo. 182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepHorizontalPaddingForPhotoView; 184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Only effective when {@link #mPhotoView} is null. 186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mKeepVerticalPaddingForPhotoView; 188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * True when {@link #mPhotoViewWidth} and {@link #mPhotoViewHeight} are ready for being used. 191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * False indicates those values should be updated before being used in position calculation. 192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mPhotoViewWidthAndHeightAreReady = false; 194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mNameTextViewHeight; 19658a793ee1253f8f46dd7f754a51f61a6bbcdce60Andrew Lee private int mNameTextViewTextColor = Color.BLACK; 197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mPhoneticNameTextViewHeight; 198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelViewHeight; 199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mDataViewHeight; 200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mSnippetTextViewHeight; 201d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mStatusTextViewHeight; 202d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 203d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Holds Math.max(mLabelTextViewHeight, mDataViewHeight), assuming Label and Data share the 204d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // same row. 205d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private int mLabelAndDataViewMaxHeight; 206d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 207d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TODO: some TextView fields are using CharArrayBuffer while some are not. Determine which is 208d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // more efficient for each case or in general, and simplify the whole implementation. 209d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Note: if we're sure MARQUEE will be used every time, there's no reason to use 210d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // CharArrayBuffer, since MARQUEE requires Span and thus we need to copy characters inside the 211d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // buffer to Spannable once, while CharArrayBuffer is for directly applying char array to 212d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // TextView without any modification. 213d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mDataBuffer = new CharArrayBuffer(128); 214d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private final CharArrayBuffer mPhoneticNameBuffer = new CharArrayBuffer(128); 215d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 216d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private boolean mActivatedStateSupported; 217fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee private boolean mAdjustSelectionBoundsEnabled = true; 218d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 219d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private Rect mBoundsWithoutHeader = new Rect(); 220d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 221d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** A helper used to highlight a prefix in a text field. */ 222a81953a2b1818066ef5e44817f374ac288bab343Christine Chen private final TextHighlighter mTextHighlighter; 223d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private CharSequence mUnknownNameText; 224d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 225d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context) { 226d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context); 227d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 22842210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 229bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNameHighlightSequence = new ArrayList<HighlightSequence>(); 230bb67024ef64a7853f5ec320652d80f0cdf7b660fYorke Lee mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 231d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 232d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 233d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ContactListItemView(Context context, AttributeSet attrs) { 234d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super(context, attrs); 235d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 236d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Read all style values 237d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ContactListItemView); 238d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPreferredHeight = a.getDimensionPixelSize( 239d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_height, mPreferredHeight); 240d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable = a.getDrawable( 241d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_activated_background); 242d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 243d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText = a.getDimensionPixelOffset( 244d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 245d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenImageAndText); 246d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData = a.getDimensionPixelOffset( 247d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_gap_between_label_and_data, 248d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mGapBetweenLabelAndData); 249d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin = a.getDimensionPixelOffset( 250d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_margin, 251d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconMargin); 252d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIconSize = a.getDimensionPixelOffset( 253d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_presence_icon_size, mPresenceIconSize); 254d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDefaultPhotoViewSize = a.getDimensionPixelOffset( 255d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_photo_size, mDefaultPhotoViewSize); 256d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mTextIndent = a.getDimensionPixelOffset( 257d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_text_indent, mTextIndent); 2587961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee mTextOffsetTop = a.getDimensionPixelOffset( 2597961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee R.styleable.ContactListItemView_list_item_text_offset_top, mTextOffsetTop); 260d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewWidthWeight = a.getInteger( 261d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_data_width_weight, mDataViewWidthWeight); 262d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight = a.getInteger( 263d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_label_width_weight, 264d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewWidthWeight); 265f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen mNameTextViewTextColor = a.getColor( 26658a793ee1253f8f46dd7f754a51f61a6bbcdce60Andrew Lee R.styleable.ContactListItemView_list_item_name_text_color, mNameTextViewTextColor); 2673bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati mNameTextViewTextSize = (int) a.getDimension( 2683bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati R.styleable.ContactListItemView_list_item_name_text_size, 2693bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati (int) getResources().getDimension(R.dimen.contact_browser_list_item_text_size)); 270d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2719f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio setPaddingRelative( 272d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 273d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_left, 0), 274d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 275d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_top, 0), 276d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 277d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_right, 0), 278d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.getDimensionPixelOffset( 279d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.styleable.ContactListItemView_list_item_padding_bottom, 0)); 280d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 28142210256d3d584783ac2fb2742088ce57d9da766Yorke Lee mTextHighlighter = new TextHighlighter(Typeface.BOLD); 28242210256d3d584783ac2fb2742088ce57d9da766Yorke Lee 283d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 284d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2853aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee a = getContext().obtainStyledAttributes(R.styleable.Theme); 2863aa2cb56ece8461f2df69d9300c9a1abf03f6989Yorke Lee mSecondaryTextColor = a.getColorStateList(R.styleable.Theme_android_textColorSecondary); 287d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng a.recycle(); 288d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 2891f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderWidth = 2901f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee getResources().getDimensionPixelSize(R.dimen.contact_list_section_header_width); 2911f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee 292d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedBackgroundDrawable != null) { 293d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setCallback(this); 294d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 295f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 296f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence = new ArrayList<HighlightSequence>(); 297f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence = new ArrayList<HighlightSequence>(); 29853c7dc1e9691b5b427395642a4274d37a1a15bb4Yorke Lee 29953c7dc1e9691b5b427395642a4274d37a1a15bb4Yorke Lee setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE); 300d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 301d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 302d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setUnknownNameText(CharSequence unknownNameText) { 303d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mUnknownNameText = unknownNameText; 304d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 305d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 306d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setQuickContactEnabled(boolean flag) { 307d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContactEnabled = flag; 308d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 309d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 310d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 311d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 312d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will match parent's width and wrap content vertically, but make sure 313d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // height is no less than listPreferredItemHeight. 314d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int specWidth = resolveSize(0, widthMeasureSpec); 315f4fcd3def28e5b1168f5160e476c05ad69339adcAndrew Lee final int preferredHeight = mPreferredHeight; 316d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 317d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = 0; 318d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = 0; 319d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = 0; 320d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = 0; 321d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = 0; 322d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = 0; 323d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 0; 324d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 325d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ensurePhotoViewSize(); 326d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 327d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Width each TextView is able to use. 328ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee int effectiveWidth; 329d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // All the other Views will honor the photo, so available width for them may be shrunk. 330d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoViewWidth > 0 || mKeepHorizontalPaddingForPhotoView) { 331d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight() 332d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - (mPhotoViewWidth + mGapBetweenImageAndText); 333d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 334d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight(); 335d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 336d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 337ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (mIsSectionHeaderEnabled) { 338ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee effectiveWidth -= mHeaderWidth + mGapBetweenImageAndText; 339ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 340ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee 341d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Go over all visible text views and measure actual width of each of them. 342d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Also calculate their heights to get the total height for this entire view. 343d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 344d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 34590fbbae42d4628b18e78434e7de13254099b229ePaul Soulos // Calculate width for name text - this parallels similar measurement in onLayout. 346d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int nameTextWidth = effectiveWidth; 347d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition != PhotoPosition.LEFT) { 348d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng nameTextWidth -= mTextIndent; 349d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 350d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.measure( 351d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(nameTextWidth, MeasureSpec.EXACTLY), 352d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 353d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextViewHeight = mNameTextView.getMeasuredHeight(); 354d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 355d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 356d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 357d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.measure( 358d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 359d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 360d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextViewHeight = mPhoneticNameTextView.getMeasuredHeight(); 361d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 362d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 363d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If both data (phone number/email address) and label (type like "MOBILE") are quite long, 364d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // we should ellipsize both using appropriate ratio. 365d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int dataWidth; 366d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int labelWidth; 367d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 368d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 369d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalWidth = effectiveWidth - mGapBetweenLabelAndData; 370d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = ((totalWidth * mDataViewWidthWeight) 371d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng / (mDataViewWidthWeight + mLabelViewWidthWeight)); 372d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = ((totalWidth * mLabelViewWidthWeight) / 373d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng (mDataViewWidthWeight + mLabelViewWidthWeight)); 374d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 375d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = effectiveWidth; 376d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 377d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 378d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 379d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataWidth = 0; 380d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 381d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = effectiveWidth; 382d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 383d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng labelWidth = 0; 384d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 385d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 386d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 387d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 388d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.measure(MeasureSpec.makeMeasureSpec(dataWidth, MeasureSpec.EXACTLY), 389d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 390d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataViewHeight = mDataView.getMeasuredHeight(); 391d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 392d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 393d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 394d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // For performance reason we don't want AT_MOST usually, but when the picture is 395d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // on right, we need to use it anyway because mDataView is next to mLabelView. 396d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int mode = (mPhotoPosition == PhotoPosition.LEFT 397d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng ? MeasureSpec.EXACTLY : MeasureSpec.AT_MOST); 398d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.measure(MeasureSpec.makeMeasureSpec(labelWidth, mode), 399d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 400d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelViewHeight = mLabelView.getMeasuredHeight(); 401d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 402d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight = Math.max(mLabelViewHeight, mDataViewHeight); 403d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 404d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 405d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.measure( 406d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(effectiveWidth, MeasureSpec.EXACTLY), 407d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 408d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight = mSnippetView.getMeasuredHeight(); 409d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 410d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 411d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Status view height is the biggest of the text view and the presence icon 412d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 413d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.measure( 414d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY), 415d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(mPresenceIconSize, MeasureSpec.EXACTLY)); 416d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = mPresenceIcon.getMeasuredHeight(); 417d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 418d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 419d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView)) { 420d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status are in a same row, so status will be affected by icon size. 421d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int statusWidth; 422d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPresenceIcon)) { 423d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = (effectiveWidth - mPresenceIcon.getMeasuredWidth() 424d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng - mPresenceIconMargin); 425d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 426d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusWidth = effectiveWidth; 427d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 428d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.measure(MeasureSpec.makeMeasureSpec(statusWidth, MeasureSpec.EXACTLY), 429d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 430d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusTextViewHeight = 431d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Math.max(mStatusTextViewHeight, mStatusView.getMeasuredHeight()); 432d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 433d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 434d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Calculate height including padding. 435d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int height = (mNameTextViewHeight + mPhoneticNameTextViewHeight + 436d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + 437d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetTextViewHeight + mStatusTextViewHeight); 438d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 439d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure the height is at least as high as the photo 440d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, mPhotoViewHeight + getPaddingBottom() + getPaddingTop()); 441d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 442d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Make sure height is at least the preferred height 443d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng height = Math.max(height, preferredHeight); 444d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 4451f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee // Measure the header if it is visible. 4461f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mHeaderTextView != null && mHeaderTextView.getVisibility() == VISIBLE) { 447d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.measure( 4481f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee MeasureSpec.makeMeasureSpec(mHeaderWidth, MeasureSpec.EXACTLY), 4496fdf16941587a222f554482fb72531783a924b6eAndrew Lee MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); 450d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 451d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 452d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMeasuredDimension(specWidth, height); 453d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 454d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 455d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 456d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 457d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int height = bottom - top; 458d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int width = right - left; 459d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 460d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Determine the vertical bounds by laying out the header first. 461d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int topBound = 0; 462d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int bottomBound = height; 463d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int leftBound = getPaddingLeft(); 464d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int rightBound = width - getPaddingRight(); 465d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 466864c67691b5a0169b5cbb91469d67d93e24ad9ebYorke Lee final boolean isLayoutRtl = ViewUtil.isViewLayoutRtl(this); 46709f15e70e86d92ae0f4c15a726b777f170845a3cYorke Lee 4681f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee // Put the section header on the left side of the contact view. 4691f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mIsSectionHeaderEnabled) { 4701f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (mHeaderTextView != null) { 4716fdf16941587a222f554482fb72531783a924b6eAndrew Lee int headerHeight = mHeaderTextView.getMeasuredHeight(); 4726fdf16941587a222f554482fb72531783a924b6eAndrew Lee int headerTopBound = (bottomBound + topBound - headerHeight) / 2 + mTextOffsetTop; 4736fdf16941587a222f554482fb72531783a924b6eAndrew Lee 4741f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderTextView.layout( 4751f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee isLayoutRtl ? rightBound - mHeaderWidth : leftBound, 4766fdf16941587a222f554482fb72531783a924b6eAndrew Lee headerTopBound, 4771f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee isLayoutRtl ? rightBound : leftBound + mHeaderWidth, 4786fdf16941587a222f554482fb72531783a924b6eAndrew Lee headerTopBound + headerHeight); 4791f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 4801f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee if (isLayoutRtl) { 4811f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee rightBound -= mHeaderWidth; 4821f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } else { 4831f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee leftBound += mHeaderWidth; 4841f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 485d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 486d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 487f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati mBoundsWithoutHeader.set(left + leftBound, topBound, left + rightBound, bottomBound); 488f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati mLeftOffset = left + leftBound; 489f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati mRightOffset = left + rightBound; 490ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (mIsSectionHeaderEnabled) { 491ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee if (isLayoutRtl) { 492ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee rightBound -= mGapBetweenImageAndText; 493ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } else { 494ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee leftBound += mGapBetweenImageAndText; 495ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 496ceb851d9c2d5c73bdd9c60ca47be0902516636aaAndrew Lee } 497d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 498d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 499d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setBounds(mBoundsWithoutHeader); 500d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 501d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 502d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final View photoView = mQuickContact != null ? mQuickContact : mPhotoView; 503d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 504d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the left most view. All the other Views should on the right of the photo. 505d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 506d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 507d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 508d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 509d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound, 510d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 511d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound + mPhotoViewWidth, 512d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 513d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 514d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else if (mKeepHorizontalPaddingForPhotoView) { 515d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Draw nothing but keep the padding. 516d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mPhotoViewWidth + mGapBetweenImageAndText; 517d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 518d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 519d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Photo is the right most view. Right bound should be adjusted that way. 520d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (photoView != null) { 521d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Center the photo vertically 522d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int photoTop = topBound + (bottomBound - topBound - mPhotoViewHeight) / 2; 523d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoView.layout( 524d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound - mPhotoViewWidth, 525d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop, 526d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 527d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng photoTop + mPhotoViewHeight); 528d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 5299f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else if (mKeepHorizontalPaddingForPhotoView) { 5309f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio // Draw nothing but keep the padding. 5319f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound -= (mPhotoViewWidth + mGapBetweenImageAndText); 532d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 533d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 534d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Add indent between left-most padding and texts. 535d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng leftBound += mTextIndent; 536d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 537d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 5387961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee // Center text vertically, then apply the top offset. 539d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final int totalTextHeight = mNameTextViewHeight + mPhoneticNameTextViewHeight + 540d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelAndDataViewMaxHeight + mSnippetTextViewHeight + mStatusTextViewHeight; 5417961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee int textTopBound = (bottomBound + topBound - totalTextHeight) / 2 + mTextOffsetTop; 542d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 543d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Layout all text view and presence icon 544d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Put name TextView first 545d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mNameTextView)) { 546d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.layout(leftBound, 547d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 548d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 549d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mNameTextViewHeight); 550d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mNameTextViewHeight; 551d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 552d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 553d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Presence and status 5549f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isLayoutRtl) { 5559f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusRightBound = rightBound; 5569f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 5579f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 5589f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 5599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound - iconWidth, 5609f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5619f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 5629f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5639f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound -= (iconWidth + mPresenceIconMargin); 5649f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 565d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 5669f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 5679f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(leftBound, 5689f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5699f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusRightBound, 5709f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5719f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 5729f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } else { 5739f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int statusLeftBound = leftBound; 5749f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mPresenceIcon)) { 5759f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio int iconWidth = mPresenceIcon.getMeasuredWidth(); 5769f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPresenceIcon.layout( 5779f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound, 5789f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5799f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio leftBound + iconWidth, 5809f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5819f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio statusLeftBound += (iconWidth + mPresenceIconMargin); 5829f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 5839f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio 5849f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio if (isVisible(mStatusView)) { 5859f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.layout(statusLeftBound, 5869f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound, 5879f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio rightBound, 5889f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio textTopBound + mStatusTextViewHeight); 5899f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 590d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 591d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 592d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mStatusView) || isVisible(mPresenceIcon)) { 593d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mStatusTextViewHeight; 594d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 595d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 596d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Rest of text views 597d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int dataLeftBound = leftBound; 598d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mPhoneticNameTextView)) { 599d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.layout(leftBound, 600d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 601d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 602d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mPhoneticNameTextViewHeight); 603d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mPhoneticNameTextViewHeight; 604d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 605d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 606d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Label and Data align bottom. 607d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView)) { 608d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 609d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on left, label is placed on the right edge of the list item. 610d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(rightBound - mLabelView.getMeasuredWidth(), 611d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 612d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 613d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 614d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound -= mLabelView.getMeasuredWidth(); 615d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 616d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // When photo is on right, label is placed on the left of data view. 617d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound = leftBound + mLabelView.getMeasuredWidth(); 618d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.layout(leftBound, 619d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mLabelViewHeight, 620d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound, 621d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 622d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng dataLeftBound += mGapBetweenLabelAndData; 623d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 624d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 625d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 626d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mDataView)) { 627d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.layout(dataLeftBound, 628d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight - mDataViewHeight, 629d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 630d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mLabelAndDataViewMaxHeight); 631d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 632d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mLabelView) || isVisible(mDataView)) { 633d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound += mLabelAndDataViewMaxHeight; 634d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 635d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 636d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (isVisible(mSnippetView)) { 637d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.layout(leftBound, 638d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound, 639d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng rightBound, 640d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textTopBound + mSnippetTextViewHeight); 641d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 642d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 643d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 644d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 645d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void adjustListItemSelectionBounds(Rect bounds) { 646fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee if (mAdjustSelectionBoundsEnabled) { 647fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee bounds.top += mBoundsWithoutHeader.top; 648fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee bounds.bottom = bounds.top + mBoundsWithoutHeader.height(); 649fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee bounds.left = mBoundsWithoutHeader.left; 650fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee bounds.right = mBoundsWithoutHeader.right; 651fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee } 652d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 653d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 654d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean isVisible(View view) { 655d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return view != null && view.getVisibility() == View.VISIBLE; 656d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 657d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 658d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 659d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Extracts width and height from the style 660d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 661d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void ensurePhotoViewSize() { 662d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mPhotoViewWidthAndHeightAreReady) { 663d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = mPhotoViewHeight = getDefaultPhotoViewSize(); 664d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled && mPhotoView == null) { 665d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepHorizontalPaddingForPhotoView) { 666d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidth = 0; 667d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 668d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mKeepVerticalPaddingForPhotoView) { 669d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewHeight = 0; 670d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 671d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 672d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 673d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = true; 674d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 675d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 676d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 677d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected int getDefaultPhotoViewSize() { 678d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDefaultPhotoViewSize; 679d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 680d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 681d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 682d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Gets a LayoutParam that corresponds to the default photo size. 683d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 684d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @return A new LayoutParam. 685d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 686d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private LayoutParams getDefaultPhotoLayoutParams() { 687d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng LayoutParams params = generateDefaultLayoutParams(); 688d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.width = getDefaultPhotoViewSize(); 689d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng params.height = params.width; 690d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return params; 691d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 692d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 693d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 694d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected void drawableStateChanged() { 695d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.drawableStateChanged(); 696d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 697d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.setState(getDrawableState()); 698d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 699d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 700d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 701d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 702d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng protected boolean verifyDrawable(Drawable who) { 703d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return who == mActivatedBackgroundDrawable || super.verifyDrawable(who); 704d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 705d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 706d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 707d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void jumpDrawablesToCurrentState() { 708d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.jumpDrawablesToCurrentState(); 709d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported) { 710d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.jumpToCurrentState(); 711d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 712d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 713d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 714d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 715d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void dispatchDraw(Canvas canvas) { 716d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mActivatedStateSupported && isActivated()) { 717d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mActivatedBackgroundDrawable.draw(canvas); 718d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 719d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 720d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng super.dispatchDraw(canvas); 721d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 722d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 723d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 724d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets section header or makes it invisible if the title is null. 725d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 726d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSectionHeader(String title) { 727d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(title)) { 728d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mHeaderTextView == null) { 729e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView = new TextView(getContext()); 730e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mHeaderTextView.setTextAppearance(getContext(), R.style.SectionHeaderStyle); 7316fdf16941587a222f554482fb72531783a924b6eAndrew Lee mHeaderTextView.setGravity( 7326fdf16941587a222f554482fb72531783a924b6eAndrew Lee ViewUtil.isViewLayoutRtl(this) ? Gravity.RIGHT : Gravity.LEFT); 733d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mHeaderTextView); 734d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 735d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mHeaderTextView, title); 736d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setVisibility(View.VISIBLE); 737d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHeaderTextView.setAllCaps(true); 7381f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } else if (mHeaderTextView != null) { 7391f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mHeaderTextView.setVisibility(View.GONE); 740d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 741d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 742d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 7431f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee public void setIsSectionHeaderEnabled(boolean isSectionHeaderEnabled) { 7441f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee mIsSectionHeaderEnabled = isSectionHeaderEnabled; 7451f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee } 7461f1e90d36fe914a7ce51e6f9884199580115d891Andrew Lee 747d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 748d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the quick contact badge, creating it if necessary. 749d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 750d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public QuickContactBadge getQuickContact() { 751d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!mQuickContactEnabled) { 752d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng throw new IllegalStateException("QuickContact is disabled for this view"); 753d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 754d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact == null) { 755e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact = new QuickContactBadge(getContext()); 7563f9c2f426058413055fa54c08c69ad9461717658Yorke Lee mQuickContact.setOverlay(null); 757d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams()); 758d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 759e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 760d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng R.string.description_quick_contact_for, mNameTextView.getText())); 761d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 762d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 763d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mQuickContact); 764d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 765d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 766d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mQuickContact; 767d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 768d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 769d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 770d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the photo view, creating it if necessary. 771d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 772d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public ImageView getPhotoView() { 773d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView == null) { 774e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhotoView = new ImageView(getContext()); 775d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams()); 776d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Quick contact style used above will set a background - remove it 777d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView.setBackground(null); 778d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhotoView); 779d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 780d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 781d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoView; 782d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 783d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 784d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 785d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 786d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 787d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView() { 788d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removePhotoView(false, true); 789d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 790d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 791d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 792d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Removes the photo view. 793d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * 794d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepHorizontalPadding True means data on the right side will have 795d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * padding on left, pretending there is still a photo view. 796d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * @param keepVerticalPadding True means the View will have some height 797d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * enough for accommodating a photo view. 798d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 799d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void removePhotoView(boolean keepHorizontalPadding, boolean keepVerticalPadding) { 800d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoViewWidthAndHeightAreReady = false; 801d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepHorizontalPaddingForPhotoView = keepHorizontalPadding; 802d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mKeepVerticalPaddingForPhotoView = keepVerticalPadding; 803d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoView != null) { 804d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhotoView); 805d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoView = null; 806d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 807d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mQuickContact != null) { 808d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mQuickContact); 809d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mQuickContact = null; 810d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 811d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 812d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 813d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 814d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets a word prefix that will be highlighted if encountered in fields like 815a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * name and search snippet. This will disable the mask highlighting for names. 816d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * <p> 817d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * NOTE: must be all upper-case 818d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 819bd80fd64b9ff94c9ffbdb843beb4b363bb209463Chiao Cheng public void setHighlightedPrefix(String upperCasePrefix) { 820d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mHighlightedPrefix = upperCasePrefix; 821a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 822a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 823a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 824f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Clears previously set highlight sequences for the view. 825a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 826f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void clearHighlightSequences() { 827f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.clear(); 828f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.clear(); 829a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mHighlightedPrefix = null; 830a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 831a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 832a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 833f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the name highlighter. 834f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 835f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 836f99a990be713ed35afe64ba8133c5428816390c6Christine Chen */ 837f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNameHighlightSequence(int start, int end) { 838f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNameHighlightSequence.add(new HighlightSequence(start, end)); 839f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 840f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 841f99a990be713ed35afe64ba8133c5428816390c6Christine Chen /** 842f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * Adds a highlight sequence to the number highlighter. 843f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param start The start position of the highlight sequence. 844f99a990be713ed35afe64ba8133c5428816390c6Christine Chen * @param end The end position of the highlight sequence. 845a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 846f99a990be713ed35afe64ba8133c5428816390c6Christine Chen public void addNumberHighlightSequence(int start, int end) { 847f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mNumberHighlightSequence.add(new HighlightSequence(start, end)); 848d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 849d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 850d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 851d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the contact name, creating it if necessary. 852d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 853d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getNameTextView() { 854d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView == null) { 855e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mNameTextView = new TextView(getContext()); 856d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setSingleLine(true); 857d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setEllipsize(getTextEllipsis()); 858f88b7b9d1a07414053a4a90d13d453a02bd58ac7Nancy Chen mNameTextView.setTextColor(mNameTextViewTextColor); 8593bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati mNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 8603bc19a3bb1ed23b03352fff6de69a89e763a315eSai Cheemalapati mNameTextViewTextSize); 861d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Manually call setActivated() since this view may be added after the first 862d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // setActivated() call toward this whole item view. 863d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setActivated(isActivated()); 864d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView.setGravity(Gravity.CENTER_VERTICAL); 8659f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 8669f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mNameTextView.setId(R.id.cliv_name_textview); 8677961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee mNameTextView.setElegantTextHeight(false); 868d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mNameTextView); 869d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 870d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mNameTextView; 871d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 872d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 873d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 874d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the phonetic name. 875d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 876d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhoneticName(char[] text, int size) { 877d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 878d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 879d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(View.GONE); 880d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 881d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 882d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getPhoneticNameTextView(); 883d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mPhoneticNameTextView, text, size); 884d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setVisibility(VISIBLE); 885d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 886d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 887d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 888d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 889d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the phonetic name, creating it if necessary. 890d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 891d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getPhoneticNameTextView() { 892d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView == null) { 893e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView = new TextView(getContext()); 894d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setSingleLine(true); 895d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setEllipsize(getTextEllipsis()); 896e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPhoneticNameTextView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 897d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD); 898d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView.setActivated(isActivated()); 8999f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mPhoneticNameTextView.setId(R.id.cliv_phoneticname_textview); 900d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPhoneticNameTextView); 901d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 902d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhoneticNameTextView; 903d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 904d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 905d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 906d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data label. 907d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 908d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setLabel(CharSequence text) { 909d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 910d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView != null) { 911d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(View.GONE); 912d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 913d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 914d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getLabelView(); 915d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mLabelView, text); 916d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setVisibility(VISIBLE); 917d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 918d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 919d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 920d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 921d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data label, creating it if necessary. 922d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 923d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getLabelView() { 924d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mLabelView == null) { 925e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mLabelView = new TextView(getContext()); 926d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setSingleLine(true); 927d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setEllipsize(getTextEllipsis()); 92890a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mLabelView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 929d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhotoPosition == PhotoPosition.LEFT) { 930d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setAllCaps(true); 9319f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setGravity(Gravity.END); 932d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 933d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD); 934d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 935d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mLabelView.setActivated(isActivated()); 9369f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mLabelView.setId(R.id.cliv_label_textview); 937d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mLabelView); 938d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 939d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mLabelView; 940d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 941d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 942d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 943d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the data element. 944d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 945a81953a2b1818066ef5e44817f374ac288bab343Christine Chen public void setData(char[] text, int size) { 946d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (text == null || size == 0) { 947d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView != null) { 948d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(View.GONE); 949d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 950d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 951d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getDataView(); 952d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mDataView, text, size); 953d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setVisibility(VISIBLE); 954a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 955a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 956a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 957a81953a2b1818066ef5e44817f374ac288bab343Christine Chen /** 958a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * Sets phone number for a list item. This takes care of number highlighting if the highlight 959a81953a2b1818066ef5e44817f374ac288bab343Christine Chen * mask exists. 960a81953a2b1818066ef5e44817f374ac288bab343Christine Chen */ 96162dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee public void setPhoneNumber(String text, String countryIso) { 962a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (text == null) { 963a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mDataView != null) { 964a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(View.GONE); 9659f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio } 966a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } else { 967a81953a2b1818066ef5e44817f374ac288bab343Christine Chen getDataView(); 96862dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee 969eabf27292960173c0600e022c64919453741c93fYorke Lee // TODO: Format number using PhoneNumberUtils.formatNumber before assigning it to 970eabf27292960173c0600e022c64919453741c93fYorke Lee // mDataView. Make sure that determination of the highlight sequences are done only 971eabf27292960173c0600e022c64919453741c93fYorke Lee // after number formatting. 97262dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee 973a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Sets phone number texts for display after highlighting it, if applicable. 97462dbbf2f10e0e3bcb4d699d859a71a68c896f4a7Andrew Lee // CharSequence textToSet = text; 975f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString textToSet = new SpannableString(text); 976f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 977f99a990be713ed35afe64ba8133c5428816390c6Christine Chen if (mNumberHighlightSequence.size() != 0) { 978f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final HighlightSequence highlightSequence = mNumberHighlightSequence.get(0); 979f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(textToSet, highlightSequence.start, 980f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 981a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 982f99a990be713ed35afe64ba8133c5428816390c6Christine Chen 983a81953a2b1818066ef5e44817f374ac288bab343Christine Chen setMarqueeText(mDataView, textToSet); 984a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setVisibility(VISIBLE); 985a81953a2b1818066ef5e44817f374ac288bab343Christine Chen 986a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // We have a phone number as "mDataView" so make it always LTR and VIEW_START 987a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextDirection(View.TEXT_DIRECTION_LTR); 988a81953a2b1818066ef5e44817f374ac288bab343Christine Chen mDataView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 989d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 990d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 991d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 992d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, char[] text, int size) { 993d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 994d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(textView, new String(text, 0, size)); 995d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 996d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text, 0, size); 997d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 998d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 999d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1000d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private void setMarqueeText(TextView textView, CharSequence text) { 1001d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (getTextEllipsis() == TruncateAt.MARQUEE) { 1002d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // To show MARQUEE correctly (with END effect during non-active state), we need 1003d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // to build Spanned with MARQUEE in addition to TextView's ellipsize setting. 1004d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng final SpannableString spannable = new SpannableString(text); 1005d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng spannable.setSpan(TruncateAt.MARQUEE, 0, spannable.length(), 1006d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 1007d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(spannable); 1008d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1009d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng textView.setText(text); 1010d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1011d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1012d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1013d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1014d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the data text, creating it if necessary. 1015d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1016d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getDataView() { 1017d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mDataView == null) { 1018e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mDataView = new TextView(getContext()); 1019d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setSingleLine(true); 1020d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setEllipsize(getTextEllipsis()); 102190a368279bb3e94291e12fc0c7dc8676f194c33dYorke Lee mDataView.setTextAppearance(getContext(), R.style.TextAppearanceSmall); 1022d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mDataView.setActivated(isActivated()); 10239f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mDataView.setId(R.id.cliv_data_view); 10247961175eb7b8b8d6f990bd8e510f59fe48c5ef4bAndrew Lee mDataView.setElegantTextHeight(false); 1025d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mDataView); 1026d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1027d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mDataView; 1028d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1029d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1030d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1031d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the search snippet. 1032d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1033d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setSnippet(String text) { 1034d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1035d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView != null) { 1036d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(View.GONE); 1037d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1038d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1039f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix); 1040d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setVisibility(VISIBLE); 1041d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1042d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1043d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1044d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1045d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the search snippet, creating it if necessary. 1046d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1047d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getSnippetView() { 1048d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mSnippetView == null) { 1049e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView = new TextView(getContext()); 1050d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setSingleLine(true); 1051d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setEllipsize(getTextEllipsis()); 1052e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mSnippetView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1053d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mSnippetView.setActivated(isActivated()); 1054d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mSnippetView); 1055d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1056d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mSnippetView; 1057d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1058d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1059d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1060d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Returns the text view for the status, creating it if necessary. 1061d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1062d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public TextView getStatusView() { 1063d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView == null) { 1064e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView = new TextView(getContext()); 1065d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setSingleLine(true); 1066d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setEllipsize(getTextEllipsis()); 1067e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mStatusView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small); 1068d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setTextColor(mSecondaryTextColor); 1069d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setActivated(isActivated()); 10709f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio mStatusView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); 1071d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mStatusView); 1072d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1073d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mStatusView; 1074d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1075d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1076d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1077d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates a text view for the status. 1078d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1079d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setStatus(CharSequence text) { 1080d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (TextUtils.isEmpty(text)) { 1081d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mStatusView != null) { 1082d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(View.GONE); 1083d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1084d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1085d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng getStatusView(); 1086d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(mStatusView, text); 1087d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mStatusView.setVisibility(VISIBLE); 1088d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1089d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1090d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1091d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1092d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Adds or updates the presence icon view. 1093d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1094d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPresence(Drawable icon) { 1095d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (icon != null) { 1096d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon == null) { 1097e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mPresenceIcon = new ImageView(getContext()); 1098d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng addView(mPresenceIcon); 1099d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1100d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setImageDrawable(icon); 1101d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setScaleType(ScaleType.CENTER); 1102d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.VISIBLE); 1103d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1104d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPresenceIcon != null) { 1105d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPresenceIcon.setVisibility(View.GONE); 1106d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1107d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1108d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1109d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1110d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng private TruncateAt getTextEllipsis() { 1111d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return TruncateAt.MARQUEE; 1112d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1113d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1114d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showDisplayName(Cursor cursor, int nameColumnIndex, int displayOrder) { 1115d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng CharSequence name = cursor.getString(nameColumnIndex); 111627330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 111727330d80bb6575df2964112d34143125c8af9b78Yorke Lee 111827330d80bb6575df2964112d34143125c8af9b78Yorke Lee // Since the quick contact content description is derived from the display name and there is 111927330d80bb6575df2964112d34143125c8af9b78Yorke Lee // no guarantee that when the quick contact is initialized the display name is already set, 112027330d80bb6575df2964112d34143125c8af9b78Yorke Lee // do it here too. 112127330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (mQuickContact != null) { 1122e9736747aa45ed6091a5479b38e3311823675853Yorke Lee mQuickContact.setContentDescription(getContext().getString( 112327330d80bb6575df2964112d34143125c8af9b78Yorke Lee R.string.description_quick_contact_for, mNameTextView.getText())); 112427330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 112527330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 112627330d80bb6575df2964112d34143125c8af9b78Yorke Lee 112727330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name, boolean highlight) { 112827330d80bb6575df2964112d34143125c8af9b78Yorke Lee if (!TextUtils.isEmpty(name) && highlight) { 112927330d80bb6575df2964112d34143125c8af9b78Yorke Lee clearHighlightSequences(); 113027330d80bb6575df2964112d34143125c8af9b78Yorke Lee addNameHighlightSequence(0, name.length()); 113127330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 113227330d80bb6575df2964112d34143125c8af9b78Yorke Lee setDisplayName(name); 113327330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 113427330d80bb6575df2964112d34143125c8af9b78Yorke Lee 113527330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDisplayName(CharSequence name) { 1136d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!TextUtils.isEmpty(name)) { 1137a81953a2b1818066ef5e44817f374ac288bab343Christine Chen // Chooses the available highlighting method for highlighting. 1138a81953a2b1818066ef5e44817f374ac288bab343Christine Chen if (mHighlightedPrefix != null) { 1139a81953a2b1818066ef5e44817f374ac288bab343Christine Chen name = mTextHighlighter.applyPrefixHighlight(name, mHighlightedPrefix); 1140f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } else if (mNameHighlightSequence.size() != 0) { 1141f99a990be713ed35afe64ba8133c5428816390c6Christine Chen final SpannableString spannableName = new SpannableString(name); 1142f99a990be713ed35afe64ba8133c5428816390c6Christine Chen for (HighlightSequence highlightSequence : mNameHighlightSequence) { 1143f99a990be713ed35afe64ba8133c5428816390c6Christine Chen mTextHighlighter.applyMaskingHighlight(spannableName, highlightSequence.start, 1144f99a990be713ed35afe64ba8133c5428816390c6Christine Chen highlightSequence.end); 1145f99a990be713ed35afe64ba8133c5428816390c6Christine Chen } 1146f99a990be713ed35afe64ba8133c5428816390c6Christine Chen name = spannableName; 1147a81953a2b1818066ef5e44817f374ac288bab343Christine Chen } 1148d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1149d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng name = mUnknownNameText; 1150d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1151d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setMarqueeText(getNameTextView(), name); 1152d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1153d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1154d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hideDisplayName() { 1155d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mNameTextView != null) { 1156d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mNameTextView); 1157d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mNameTextView = null; 1158d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1159d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1160d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1161d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPhoneticName(Cursor cursor, int phoneticNameColumnIndex) { 1162d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(phoneticNameColumnIndex, mPhoneticNameBuffer); 1163d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int phoneticNameSize = mPhoneticNameBuffer.sizeCopied; 1164d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (phoneticNameSize != 0) { 1165d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(mPhoneticNameBuffer.data, phoneticNameSize); 1166d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } else { 1167d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPhoneticName(null, 0); 1168d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1169d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1170d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1171d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void hidePhoneticName() { 1172d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (mPhoneticNameTextView != null) { 1173d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng removeView(mPhoneticNameTextView); 1174d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhoneticNameTextView = null; 1175d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1176d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1177d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1178d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1179d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Sets the proper icon (star or presence or nothing) and/or status message. 1180d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1181d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showPresenceAndStatusMessage(Cursor cursor, int presenceColumnIndex, 1182d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int contactStatusColumnIndex) { 1183d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng Drawable icon = null; 1184d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng int presence = 0; 1185d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (!cursor.isNull(presenceColumnIndex)) { 1186d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng presence = cursor.getInt(presenceColumnIndex); 1187d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng icon = ContactPresenceIconUtil.getPresenceIcon(getContext(), presence); 1188d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1189d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setPresence(icon); 1190d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1191d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng String statusMessage = null; 1192d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (contactStatusColumnIndex != 0 && !cursor.isNull(contactStatusColumnIndex)) { 1193d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = cursor.getString(contactStatusColumnIndex); 1194d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1195d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // If there is no status message from the contact, but there was a presence value, then use 1196d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // the default status message string 1197d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (statusMessage == null && presence != 0) { 1198d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng statusMessage = ContactStatusUtil.getStatusString(getContext(), presence); 1199d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1200d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setStatus(statusMessage); 1201d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1202d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1203d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 1204d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng * Shows search snippet. 1205d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1206d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showSnippet(Cursor cursor, int summarySnippetColumnIndex) { 1207d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (cursor.getColumnCount() <= summarySnippetColumnIndex) { 1208d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(null); 1209d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return; 1210d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1211d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 121205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng String snippet = cursor.getString(summarySnippetColumnIndex); 1213cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1214d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // Do client side snippeting if provider didn't do it 121505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Bundle extras = cursor.getExtras(); 1216d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng if (extras.getBoolean(ContactsContract.DEFERRED_SNIPPETING)) { 1217d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 121805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final String query = extras.getString(ContactsContract.DEFERRED_SNIPPETING_QUERY); 1219cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1220cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng String displayName = null; 1221cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int displayNameIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME); 1222cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (displayNameIndex >= 0) { 1223cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng displayName = cursor.getString(displayNameIndex); 122405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1225cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1226cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng snippet = updateSnippet(snippet, query, displayName); 1227cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 122805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 122905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (snippet != null) { 123005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int from = 0; 123105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int to = snippet.length(); 123205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int start = snippet.indexOf(DefaultContactListAdapter.SNIPPET_START_MATCH); 123305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (start == -1) { 123405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = null; 123505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } else { 123605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int firstNl = snippet.lastIndexOf('\n', start); 123705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (firstNl != -1) { 123805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng from = firstNl + 1; 123905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 124005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int end = snippet.lastIndexOf(DefaultContactListAdapter.SNIPPET_END_MATCH); 124105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (end != -1) { 124205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng int lastNl = snippet.indexOf('\n', end); 124305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (lastNl != -1) { 124405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng to = lastNl; 124505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 124605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1247d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 124805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng StringBuilder sb = new StringBuilder(); 124905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng for (int i = from; i < to; i++) { 125005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng char c = snippet.charAt(i); 125105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng if (c != DefaultContactListAdapter.SNIPPET_START_MATCH && 125205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng c != DefaultContactListAdapter.SNIPPET_END_MATCH) { 125305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng sb.append(c); 125405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 1255d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 125605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng snippet = sb.toString(); 1257d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1258d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1259d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1260cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1261d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng setSnippet(snippet); 1262d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1263d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1264cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng /** 1265cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * Used for deferred snippets from the database. The contents come back as large strings which 1266cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * need to be extracted for display. 1267cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * 1268cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param snippet The snippet from the database. 1269cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param query The search query substring. 1270cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @param displayName The contact display name. 1271cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng * @return The proper snippet to display. 1272cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng */ 1273cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String updateSnippet(String snippet, String query, String displayName) { 1274cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1275cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (TextUtils.isEmpty(snippet) || TextUtils.isEmpty(query)) { 1276cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1277cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1278cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng query = SearchUtil.cleanStartAndEndOfSearchQuery(query.toLowerCase()); 1279cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1280cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // If the display name already contains the query term, return empty - snippets should 1281cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // not be needed in that case. 1282cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!TextUtils.isEmpty(displayName)) { 1283cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final String lowerDisplayName = displayName.toLowerCase(); 1284cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final List<String> nameTokens = split(lowerDisplayName); 1285cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng for (String nameToken : nameTokens) { 1286cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (nameToken.startsWith(query)) { 1287cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1288cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1289cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1290cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1291cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1292cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // The snippet may contain multiple data lines. 1293cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show the first line that matches the query. 1294cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final SearchUtil.MatchedLine matched = SearchUtil.findMatchingLine(snippet, query); 1295cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1296cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched != null && matched.line != null) { 1297cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Tokenize for long strings since the match may be at the end of it. 1298cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Skip this part for short strings since the whole string will be displayed. 1299cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Most contact strings are short so the snippetize method will be called infrequently. 1300cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final int lengthThreshold = getResources().getInteger( 1301cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng R.integer.snippet_length_before_tokenize); 1302cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (matched.line.length() > lengthThreshold) { 1303cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return snippetize(matched.line, matched.startIndex, lengthThreshold); 1304cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } else { 1305cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return matched.line; 1306cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1307cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1308cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1309cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // No match found. 1310cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return null; 1311cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1312cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1313cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng private String snippetize(String line, int matchIndex, int maxLength) { 1314cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Show up to maxLength characters. But we only show full tokens so show the last full token 1315cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // up to maxLength characters. So as many starting tokens as possible before trying ending 1316cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // tokens. 1317cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int remainingLength = maxLength; 1318cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int tempRemainingLength = remainingLength; 1319cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1320cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Start the end token after the matched query. 1321cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int index = matchIndex; 1322cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int endTokenIndex = index; 1323cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1324cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find the match token first. 1325cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length()) { 1326cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1327cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1328cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1329cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng break; 1330cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1331cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1332cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1333cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1334cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1335cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find as much content before the match. 1336cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = matchIndex - 1; 1337cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1338cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng int startTokenIndex = matchIndex; 1339cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index > -1 && tempRemainingLength > 0) { 1340cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1341cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng startTokenIndex = index; 1342cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng remainingLength = tempRemainingLength; 1343cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1344cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1345cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index--; 1346cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1347cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 1348cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index = endTokenIndex; 1349cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength = remainingLength; 1350cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Find remaining content at after match. 1351cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng while (index < line.length() && tempRemainingLength > 0) { 1352cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (!Character.isLetterOrDigit(line.charAt(index))) { 1353cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng endTokenIndex = index; 1354cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1355cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng tempRemainingLength--; 1356cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng index++; 1357cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1358cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng // Append ellipse if there is content before or after. 1359cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng final StringBuilder sb = new StringBuilder(); 1360cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (startTokenIndex > 0) { 1361cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1362cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1363cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append(line.substring(startTokenIndex, endTokenIndex)); 1364cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng if (endTokenIndex < line.length()) { 1365cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng sb.append("..."); 1366cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1367cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng return sb.toString(); 1368cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng } 1369cae605bed4d43e1925fc8c1803def0ef1d0924a5Chiao Cheng 137005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static final Pattern SPLIT_PATTERN = Pattern.compile( 137105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng "([\\w-\\.]+)@((?:[\\w]+\\.)+)([a-zA-Z]{2,4})|[\\w]+"); 137205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 137305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng /** 137405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * Helper method for splitting a string into tokens. The lists passed in are populated with 137505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * the 137605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * tokens and offsets into the content of each token. The tokenization function parses e-mail 137705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * addresses as a single token; otherwise it splits on any non-alphanumeric character. 137805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * 137905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @param content Content to split. 138005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng * @return List of token strings. 138105897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng */ 138205897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng private static List<String> split(String content) { 138305897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final Matcher matcher = SPLIT_PATTERN.matcher(content); 138405897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng final ArrayList<String> tokens = Lists.newArrayList(); 138505897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng while (matcher.find()) { 138605897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng tokens.add(matcher.group()); 138705897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 138805897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng return tokens; 138905897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng } 139005897c8e016942e10f0ef6f0da02d339480d4748Chiao Cheng 1391d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 13927a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner * Shows data element. 1393d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng */ 1394d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void showData(Cursor cursor, int dataColumnIndex) { 1395d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng cursor.copyStringToBuffer(dataColumnIndex, mDataBuffer); 13967a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner setData(mDataBuffer.data, mDataBuffer.sizeCopied); 13977a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner } 13987a160466a38bb631da02b7e93ab907eb2b3a2558Jay Shrauner 1399d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setActivatedStateSupported(boolean flag) { 1400d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng this.mActivatedStateSupported = flag; 1401d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1402d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1403fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee public void setAdjustSelectionBoundsEnabled(boolean enabled) { 1404fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee mAdjustSelectionBoundsEnabled = enabled; 1405fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee } 1406fc9221ef57bfb9311dda798f67030d40215be859Andrew Lee 1407d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng @Override 1408d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void requestLayout() { 1409d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // We will assume that once measured this will not need to resize 1410d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // itself, so there is no need to pass the layout request to the parent 1411d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng // view (ListView). 1412d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng forceLayout(); 1413d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1414d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1415d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public void setPhotoPosition(PhotoPosition photoPosition) { 1416d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng mPhotoPosition = photoPosition; 1417d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1418d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1419d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng public PhotoPosition getPhotoPosition() { 1420d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng return mPhotoPosition; 1421d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng } 1422d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng 1423d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng /** 142427330d80bb6575df2964112d34143125c8af9b78Yorke Lee * Set drawable resources directly for both the background and the drawable resource 142527330d80bb6575df2964112d34143125c8af9b78Yorke Lee * of the photo view 142627330d80bb6575df2964112d34143125c8af9b78Yorke Lee * 142727330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param backgroundId Id of background resource 142827330d80bb6575df2964112d34143125c8af9b78Yorke Lee * @param drawableId Id of drawable resource 142927330d80bb6575df2964112d34143125c8af9b78Yorke Lee */ 143027330d80bb6575df2964112d34143125c8af9b78Yorke Lee public void setDrawableResource(int backgroundId, int drawableId) { 143127330d80bb6575df2964112d34143125c8af9b78Yorke Lee final ImageView photo = getPhotoView(); 143227330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setScaleType(ImageView.ScaleType.CENTER); 143327330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setBackgroundResource(backgroundId); 143427330d80bb6575df2964112d34143125c8af9b78Yorke Lee photo.setImageResource(drawableId); 143527330d80bb6575df2964112d34143125c8af9b78Yorke Lee } 143610349f190691f802b8935175dbf38bff74a8a703Yorke Lee 143710349f190691f802b8935175dbf38bff74a8a703Yorke Lee @Override 143810349f190691f802b8935175dbf38bff74a8a703Yorke Lee public boolean onTouchEvent(MotionEvent event) { 143910349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float x = event.getX(); 144010349f190691f802b8935175dbf38bff74a8a703Yorke Lee final float y = event.getY(); 1441538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // If the touch event's coordinates are not within the view's header, then delegate 1442538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // to super.onTouchEvent so that regular view behavior is preserved. Otherwise, consume 1443538e05b3bbde399f25ccf1aad251fca6d7f4d6b3Yorke Lee // and ignore the touch event. 1444bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointIsInView(x, y)) { 144510349f190691f802b8935175dbf38bff74a8a703Yorke Lee return super.onTouchEvent(event); 144610349f190691f802b8935175dbf38bff74a8a703Yorke Lee } else { 144710349f190691f802b8935175dbf38bff74a8a703Yorke Lee return true; 144810349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 144910349f190691f802b8935175dbf38bff74a8a703Yorke Lee } 1450bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee 1451bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee private final boolean pointIsInView(float localX, float localY) { 1452f7a205fdcb17161c454bee673cc2fce5b23d0760Sai Cheemalapati return localX >= mLeftOffset && localX < mRightOffset 14533d7e2893cb55dc0f1bc4f7e731322973ee09bc1fYorke Lee && localY >= 0 && localY < (getBottom() - getTop()); 1454bded9d078784569efef4aec2d636ce3f733601d7Yorke Lee } 1455d6bba124836ec2f528b329759e38fda6297fec49Chiao Cheng} 1456