// Copyright 2015 The Project Buendia Authors
//
// 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 distrib-
// uted 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
// specific language governing permissions and limitations under the License.
package org.projectbuendia.client.ui;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
/**
* An {@link ArrayAdapter} that uses null values to indicate 'section' boundaries. Section
* boundaries are represented by an arbitrary resource (such as a horizontal divider) and are not
* clickable.
*/
public class SectionedSpinnerAdapter<T> extends ArrayAdapter<T> {
private final T[] mItems;
private final int mSectionBorderResource;
private final LayoutInflater mInflater;
/**
* Instantiates a {@link SectionedSpinnerAdapter} with the given resources and contents.
* @param context the Application or Activity context
* @param collapsedResource the {@link android.graphics.drawable.Drawable} used to display the
* selected adapter item when the list is collapsed
* @param dropDownResource the {@link android.graphics.drawable.Drawable} used to display an
* adapter item when the list is expanded
* @param sectionBorderResource the {@link android.graphics.drawable.Drawable} used to display
* section dividers (null items)
* @param items the contents of the list
*/
public SectionedSpinnerAdapter(
Context context, int collapsedResource, int dropDownResource,
int sectionBorderResource, T[] items) {
super(context, collapsedResource, items);
mItems = items;
mSectionBorderResource = sectionBorderResource;
setDropDownViewResource(dropDownResource);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (isSectionBorder(position)) {
return getSectionBorder(convertView, parent);
}
resetClickable(convertView);
if (convertView != null && convertView.getTag() != ViewType.LIST_ITEM) {
convertView = null;
}
View view = super.getDropDownView(position, convertView, parent);
// Manually manage the different types of views, since Spinners don't
// ordinarily support multiple view types and ignore getViewTypeCount().
view.setTag(ViewType.LIST_ITEM);
return view;
}
private boolean isSectionBorder(int position) {
return position < mItems.length && mItems[position] == null;
}
private View getSectionBorder(View convertView, ViewGroup parent) {
if (convertView == null || convertView.getTag() != ViewType.SECTION_BORDER) {
convertView = mInflater.inflate(mSectionBorderResource, parent, false);
}
convertView.setClickable(true);
// Manually manage the different types of views, since Spinners don't
// ordinarily support multiple view types and ignore getViewTypeCount().
convertView.setTag(ViewType.SECTION_BORDER);
return convertView;
}
private void resetClickable(View convertView) {
if (convertView != null) {
convertView.setClickable(false);
}
}
@Override public View getView(int position, View convertView, ViewGroup parent) {
if (isSectionBorder(position)) {
return getSectionBorder(convertView, parent);
}
resetClickable(convertView);
if (convertView != null && convertView.getTag() != ViewType.LIST_ITEM) {
convertView = null;
}
View view = super.getView(position, convertView, parent);
// Manually manage the different types of views, since Spinners don't
// ordinarily support multiple view types and ignore getViewTypeCount().
view.setTag(ViewType.LIST_ITEM);
return view;
}
@Override public int getViewTypeCount() {
return 2;
}
/**
* Returns the type for the view at the given position, where valid types are ordinal values of
* the {@link ViewType} enum.
* @param position the position of the view in the adapter
*/
public int getItemViewType(int position) {
return isSectionBorder(position)
? ViewType.SECTION_BORDER.ordinal()
: ViewType.LIST_ITEM.ordinal();
}
private enum ViewType {
SECTION_BORDER, LIST_ITEM
}
}