blob: 6a7642123fc19cf916966666525fb386aeb9fc56 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.contacts.list;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import com.android.common.widget.CompositeCursorAdapter;
/**
* A subclass of {@link CompositeCursorAdapter} that manages pinned partition headers.
*/
public abstract class PinnedHeaderListAdapter extends CompositeCursorAdapter
implements PinnedHeaderListView.PinnedHeaderAdapter {
public static final int PARTITION_HEADER_TYPE = 0;
private boolean mPinnedPartitionHeadersEnabled;
private boolean mHeaderVisibility[];
public PinnedHeaderListAdapter(Context context) {
super(context);
}
public PinnedHeaderListAdapter(Context context, int initialCapacity) {
super(context, initialCapacity);
}
public boolean getPinnedPartitionHeadersEnabled() {
return mPinnedPartitionHeadersEnabled;
}
public void setPinnedPartitionHeadersEnabled(boolean flag) {
this.mPinnedPartitionHeadersEnabled = flag;
}
@Override
public int getPinnedHeaderCount() {
if (mPinnedPartitionHeadersEnabled) {
return getPartitionCount();
} else {
return 0;
}
}
protected boolean isPinnedPartitionHeaderVisible(int partition) {
return getPinnedPartitionHeadersEnabled() && hasHeader(partition)
&& !isPartitionEmpty(partition);
}
/**
* The default implementation creates the same type of view as a normal
* partition header.
*/
@Override
public View getPinnedHeaderView(int partition, View convertView, ViewGroup parent) {
if (hasHeader(partition)) {
View view = null;
if (convertView != null) {
Integer headerType = (Integer)convertView.getTag();
if (headerType != null && headerType == PARTITION_HEADER_TYPE) {
view = convertView;
}
}
if (view == null) {
view = newHeaderView(getContext(), partition, null, parent);
view.setTag(PARTITION_HEADER_TYPE);
view.setFocusable(false);
view.setEnabled(false);
}
bindHeaderView(view, partition, getCursor(partition));
view.setLayoutDirection(parent.getLayoutDirection());
return view;
} else {
return null;
}
}
@Override
public void configurePinnedHeaders(PinnedHeaderListView listView) {
if (!getPinnedPartitionHeadersEnabled()) {
return;
}
int size = getPartitionCount();
// Cache visibility bits, because we will need them several times later on
if (mHeaderVisibility == null || mHeaderVisibility.length != size) {
mHeaderVisibility = new boolean[size];
}
for (int i = 0; i < size; i++) {
boolean visible = isPinnedPartitionHeaderVisible(i);
mHeaderVisibility[i] = visible;
if (!visible) {
listView.setHeaderInvisible(i, true);
}
}
int headerViewsCount = listView.getHeaderViewsCount();
// Starting at the top, find and pin headers for partitions preceding the visible one(s)
int maxTopHeader = -1;
int topHeaderHeight = 0;
for (int i = 0; i < size; i++) {
if (mHeaderVisibility[i]) {
int position = listView.getPositionAt(topHeaderHeight) - headerViewsCount;
int partition = getPartitionForPosition(position);
if (i > partition) {
break;
}
listView.setHeaderPinnedAtTop(i, topHeaderHeight, false);
topHeaderHeight += listView.getPinnedHeaderHeight(i);
maxTopHeader = i;
}
}
// Starting at the bottom, find and pin headers for partitions following the visible one(s)
int maxBottomHeader = size;
int bottomHeaderHeight = 0;
int listHeight = listView.getHeight();
for (int i = size; --i > maxTopHeader;) {
if (mHeaderVisibility[i]) {
int position = listView.getPositionAt(listHeight - bottomHeaderHeight)
- headerViewsCount;
if (position < 0) {
break;
}
int partition = getPartitionForPosition(position - 1);
if (partition == -1 || i <= partition) {
break;
}
int height = listView.getPinnedHeaderHeight(i);
bottomHeaderHeight += height;
listView.setHeaderPinnedAtBottom(i, listHeight - bottomHeaderHeight, false);
maxBottomHeader = i;
}
}
// Headers in between the top-pinned and bottom-pinned should be hidden
for (int i = maxTopHeader + 1; i < maxBottomHeader; i++) {
if (mHeaderVisibility[i]) {
listView.setHeaderInvisible(i, isPartitionEmpty(i));
}
}
}
@Override
public int getScrollPositionForHeader(int viewIndex) {
return getPositionForPartition(viewIndex);
}
}