1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts.list; 18 19 import com.android.contacts.R; 20 21 import android.content.Context; 22 import android.content.res.TypedArray; 23 import android.graphics.Color; 24 import android.graphics.Typeface; 25 import android.text.TextUtils; 26 import android.util.AttributeSet; 27 import android.util.TypedValue; 28 import android.view.Gravity; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.TextView; 32 33 /** 34 * A custom view for the pinned section header shown at the top of the contact list. 35 */ 36 public class ContactListPinnedHeaderView extends ViewGroup { 37 38 protected final Context mContext; 39 40 private final int mHeaderTextColor; 41 private final int mHeaderTextIndent; 42 private final int mHeaderTextSize; 43 private final int mHeaderUnderlineHeight; 44 private final int mHeaderUnderlineColor; 45 private final int mPaddingRight; 46 private final int mPaddingLeft; 47 private final int mContactsCountTextColor; 48 private final int mCountViewTextSize; 49 50 private int mHeaderBackgroundHeight; 51 private TextView mHeaderTextView; 52 private TextView mCountTextView = null; 53 private View mHeaderDivider; 54 55 public ContactListPinnedHeaderView(Context context, AttributeSet attrs) { 56 super(context, attrs); 57 mContext = context; 58 59 TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ContactListItemView); 60 61 mHeaderTextIndent = a.getDimensionPixelOffset( 62 R.styleable.ContactListItemView_list_item_header_text_indent, 0); 63 mHeaderTextColor = a.getColor( 64 R.styleable.ContactListItemView_list_item_header_text_color, Color.BLACK); 65 mHeaderTextSize = a.getDimensionPixelSize( 66 R.styleable.ContactListItemView_list_item_header_text_size, 12); 67 mHeaderUnderlineHeight = a.getDimensionPixelSize( 68 R.styleable.ContactListItemView_list_item_header_underline_height, 1); 69 mHeaderUnderlineColor = a.getColor( 70 R.styleable.ContactListItemView_list_item_header_underline_color, 0); 71 mHeaderBackgroundHeight = a.getDimensionPixelSize( 72 R.styleable.ContactListItemView_list_item_header_height, 30); 73 mPaddingLeft = a.getDimensionPixelOffset( 74 R.styleable.ContactListItemView_list_item_padding_left, 0); 75 mPaddingRight = a.getDimensionPixelOffset( 76 R.styleable.ContactListItemView_list_item_padding_right, 0); 77 mContactsCountTextColor = a.getColor( 78 R.styleable.ContactListItemView_list_item_contacts_count_text_color, Color.BLACK); 79 mCountViewTextSize = (int)a.getDimensionPixelSize( 80 R.styleable.ContactListItemView_list_item_contacts_count_text_size, 12); 81 82 a.recycle(); 83 84 mHeaderTextView = new TextView(mContext); 85 mHeaderTextView.setTextColor(mHeaderTextColor); 86 mHeaderTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mHeaderTextSize); 87 mHeaderTextView.setTypeface(mHeaderTextView.getTypeface(), Typeface.BOLD); 88 mHeaderTextView.setGravity(Gravity.CENTER_VERTICAL); 89 mHeaderTextView.setAllCaps(true); 90 addView(mHeaderTextView); 91 mHeaderDivider = new View(mContext); 92 mHeaderDivider.setBackgroundColor(mHeaderUnderlineColor); 93 addView(mHeaderDivider); 94 } 95 96 @Override 97 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 98 99 // We will match parent's width and wrap content vertically. 100 int width = resolveSize(0, widthMeasureSpec); 101 102 mHeaderTextView.measure( 103 MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 104 MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY)); 105 if (isViewMeasurable(mCountTextView)) { 106 mCountTextView.measure( 107 MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), 108 MeasureSpec.makeMeasureSpec(mHeaderBackgroundHeight, MeasureSpec.EXACTLY)); 109 } 110 111 setMeasuredDimension(width, mHeaderBackgroundHeight + mHeaderUnderlineHeight); 112 } 113 114 @Override 115 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 116 int width = right - left; 117 118 // Take into account left and right padding when laying out the below views. 119 mHeaderTextView.layout(mHeaderTextIndent + mPaddingLeft, 120 0, 121 mHeaderTextView.getMeasuredWidth() + mHeaderTextIndent + mPaddingLeft, 122 mHeaderBackgroundHeight); 123 124 if (isViewMeasurable(mCountTextView)) { 125 mCountTextView.layout(width - mPaddingRight - mCountTextView.getMeasuredWidth(), 126 0, 127 width - mPaddingRight, 128 mHeaderBackgroundHeight); 129 } 130 131 mHeaderDivider.layout(mPaddingLeft, 132 mHeaderBackgroundHeight, 133 width - mPaddingRight, 134 mHeaderBackgroundHeight + mHeaderUnderlineHeight); 135 } 136 137 /** 138 * Sets section header or makes it invisible if the title is null. 139 */ 140 public void setSectionHeader(String title) { 141 if (!TextUtils.isEmpty(title)) { 142 mHeaderTextView.setText(title); 143 mHeaderTextView.setVisibility(View.VISIBLE); 144 mHeaderDivider.setVisibility(View.VISIBLE); 145 } else { 146 mHeaderTextView.setVisibility(View.GONE); 147 mHeaderDivider.setVisibility(View.GONE); 148 } 149 } 150 151 @Override 152 public void requestLayout() { 153 // We will assume that once measured this will not need to resize 154 // itself, so there is no need to pass the layout request to the parent 155 // view (ListView). 156 forceLayout(); 157 } 158 159 public void setCountView(String count) { 160 if (mCountTextView == null) { 161 mCountTextView = new TextView(mContext); 162 mCountTextView.setTextColor(mContactsCountTextColor); 163 mCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCountViewTextSize); 164 mCountTextView.setGravity(Gravity.CENTER_VERTICAL); 165 addView(mCountTextView); 166 } 167 mCountTextView.setText(count); 168 if (count == null || count.isEmpty()) { 169 mCountTextView.setVisibility(View.GONE); 170 } else { 171 mCountTextView.setVisibility(View.VISIBLE); 172 } 173 } 174 175 private boolean isViewMeasurable(View view) { 176 return (view != null && view.getVisibility() == View.VISIBLE); 177 } 178 } 179