/* * Copyright (C) 2006 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 android.widget; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.view.View; /** * An easy adapter to map columns from a cursor to TextViews or ImageViews * defined in an XML file. You can specify which columns you want, which views * you want to display the columns, and the XML file that defines the appearance * of these views. Separate XML files for child and groups are possible. * * Binding occurs in two phases. First, if a * {@link android.widget.SimpleCursorTreeAdapter.ViewBinder} is available, * {@link ViewBinder#setViewValue(android.view.View, android.database.Cursor, int)} * is invoked. If the returned value is true, binding has occurred. If the * returned value is false and the view to bind is a TextView, * {@link #setViewText(TextView, String)} is invoked. If the returned value * is false and the view to bind is an ImageView, * {@link #setViewImage(ImageView, String)} is invoked. If no appropriate * binding can be found, an {@link IllegalStateException} is thrown. */ public abstract class SimpleCursorTreeAdapter extends ResourceCursorTreeAdapter { /** The name of the columns that contain the data to display for a group. */ private String[] mGroupFromNames; /** The indices of columns that contain data to display for a group. */ private int[] mGroupFrom; /** * The View IDs that will display a group's data fetched from the * corresponding column. */ private int[] mGroupTo; /** The name of the columns that contain the data to display for a child. */ private String[] mChildFromNames; /** The indices of columns that contain data to display for a child. */ private int[] mChildFrom; /** * The View IDs that will display a child's data fetched from the * corresponding column. */ private int[] mChildTo; /** * View binder, if supplied */ private ViewBinder mViewBinder; /** * Constructor. * * @param context The context where the {@link ExpandableListView} * associated with this {@link SimpleCursorTreeAdapter} is * running * @param cursor The database cursor * @param collapsedGroupLayout The resource identifier of a layout file that * defines the views for a collapsed group. The layout file * should include at least those named views defined in groupTo. * @param expandedGroupLayout The resource identifier of a layout file that * defines the views for an expanded group. The layout file * should include at least those named views defined in groupTo. * @param groupFrom A list of column names that will be used to display the * data for a group. * @param groupTo The group views (from the group layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. * @param childLayout The resource identifier of a layout file that defines * the views for a child (except the last). The layout file * should include at least those named views defined in childTo. * @param lastChildLayout The resource identifier of a layout file that * defines the views for the last child within a group. The * layout file should include at least those named views defined * in childTo. * @param childFrom A list of column names that will be used to display the * data for a child. * @param childTo The child views (from the child layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. */ public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, int expandedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout, int lastChildLayout, String[] childFrom, int[] childTo) { super(context, cursor, collapsedGroupLayout, expandedGroupLayout, childLayout, lastChildLayout); init(groupFrom, groupTo, childFrom, childTo); } /** * Constructor. * * @param context The context where the {@link ExpandableListView} * associated with this {@link SimpleCursorTreeAdapter} is * running * @param cursor The database cursor * @param collapsedGroupLayout The resource identifier of a layout file that * defines the views for a collapsed group. The layout file * should include at least those named views defined in groupTo. * @param expandedGroupLayout The resource identifier of a layout file that * defines the views for an expanded group. The layout file * should include at least those named views defined in groupTo. * @param groupFrom A list of column names that will be used to display the * data for a group. * @param groupTo The group views (from the group layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. * @param childLayout The resource identifier of a layout file that defines * the views for a child. The layout file * should include at least those named views defined in childTo. * @param childFrom A list of column names that will be used to display the * data for a child. * @param childTo The child views (from the child layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. */ public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, int expandedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom, int[] childTo) { super(context, cursor, collapsedGroupLayout, expandedGroupLayout, childLayout); init(groupFrom, groupTo, childFrom, childTo); } /** * Constructor. * * @param context The context where the {@link ExpandableListView} * associated with this {@link SimpleCursorTreeAdapter} is * running * @param cursor The database cursor * @param groupLayout The resource identifier of a layout file that defines * the views for a group. The layout file should include at least * those named views defined in groupTo. * @param groupFrom A list of column names that will be used to display the * data for a group. * @param groupTo The group views (from the group layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. * @param childLayout The resource identifier of a layout file that defines * the views for a child. The layout file should include at least * those named views defined in childTo. * @param childFrom A list of column names that will be used to display the * data for a child. * @param childTo The child views (from the child layouts) that should * display column in the "from" parameter. These should all be * TextViews or ImageViews. The first N views in this list are * given the values of the first N columns in the from parameter. */ public SimpleCursorTreeAdapter(Context context, Cursor cursor, int groupLayout, String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom, int[] childTo) { super(context, cursor, groupLayout, childLayout); init(groupFrom, groupTo, childFrom, childTo); } private void init(String[] groupFromNames, int[] groupTo, String[] childFromNames, int[] childTo) { mGroupFromNames = groupFromNames; mGroupTo = groupTo; mChildFromNames = childFromNames; mChildTo = childTo; } /** * Returns the {@link ViewBinder} used to bind data to views. * * @return a ViewBinder or null if the binder does not exist * * @see #setViewBinder(android.widget.SimpleCursorTreeAdapter.ViewBinder) */ public ViewBinder getViewBinder() { return mViewBinder; } /** * Sets the binder used to bind data to views. * * @param viewBinder the binder used to bind data to views, can be null to * remove the existing binder * * @see #getViewBinder() */ public void setViewBinder(ViewBinder viewBinder) { mViewBinder = viewBinder; } private void bindView(View view, Context context, Cursor cursor, int[] from, int[] to) { final ViewBinder binder = mViewBinder; for (int i = 0; i < to.length; i++) { View v = view.findViewById(to[i]); if (v != null) { boolean bound = false; if (binder != null) { bound = binder.setViewValue(v, cursor, from[i]); } if (!bound) { String text = cursor.getString(from[i]); if (text == null) { text = ""; } if (v instanceof TextView) { setViewText((TextView) v, text); } else if (v instanceof ImageView) { setViewImage((ImageView) v, text); } else { throw new IllegalStateException("SimpleCursorTreeAdapter can bind values" + " only to TextView and ImageView!"); } } } } } private void initFromColumns(Cursor cursor, String[] fromColumnNames, int[] fromColumns) { for (int i = fromColumnNames.length - 1; i >= 0; i--) { fromColumns[i] = cursor.getColumnIndexOrThrow(fromColumnNames[i]); } } @Override protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) { if (mChildFrom == null) { mChildFrom = new int[mChildFromNames.length]; initFromColumns(cursor, mChildFromNames, mChildFrom); } bindView(view, context, cursor, mChildFrom, mChildTo); } @Override protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) { if (mGroupFrom == null) { mGroupFrom = new int[mGroupFromNames.length]; initFromColumns(cursor, mGroupFromNames, mGroupFrom); } bindView(view, context, cursor, mGroupFrom, mGroupTo); } /** * Called by bindView() to set the image for an ImageView. By default, the * value will be treated as a Uri. Intended to be overridden by Adapters * that need to filter strings retrieved from the database. * * @param v ImageView to receive an image * @param value the value retrieved from the cursor */ protected void setViewImage(ImageView v, String value) { try { v.setImageResource(Integer.parseInt(value)); } catch (NumberFormatException nfe) { v.setImageURI(Uri.parse(value)); } } /** * Called by bindView() to set the text for a TextView but only if * there is no existing ViewBinder or if the existing ViewBinder cannot * handle binding to a TextView. * * Intended to be overridden by Adapters that need to filter strings * retrieved from the database. * * @param v TextView to receive text * @param text the text to be set for the TextView */ public void setViewText(TextView v, String text) { v.setText(text); } /** * This class can be used by external clients of SimpleCursorTreeAdapter * to bind values from the Cursor to views. * * You should use this class to bind values from the Cursor to views * that are not directly supported by SimpleCursorTreeAdapter or to * change the way binding occurs for views supported by * SimpleCursorTreeAdapter. * * @see SimpleCursorTreeAdapter#setViewImage(ImageView, String) * @see SimpleCursorTreeAdapter#setViewText(TextView, String) */ public static interface ViewBinder { /** * Binds the Cursor column defined by the specified index to the specified view. * * When binding is handled by this ViewBinder, this method must return true. * If this method returns false, SimpleCursorTreeAdapter will attempts to handle * the binding on its own. * * @param view the view to bind the data to * @param cursor the cursor to get the data from * @param columnIndex the column at which the data can be found in the cursor * * @return true if the data was bound to the view, false otherwise */ boolean setViewValue(View view, Cursor cursor, int columnIndex); } }