BaseMenuPresenter.java revision f35d049b9953fbd1cd24887bac57b5e148c97846
1/* 2 * Copyright (C) 2011 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 17package com.android.internal.view.menu; 18 19import android.content.Context; 20import android.view.LayoutInflater; 21import android.view.View; 22import android.view.ViewGroup; 23 24import java.util.ArrayList; 25 26/** 27 * Base class for MenuPresenters that have a consistent container view and item 28 * views. Behaves similarly to an AdapterView in that existing item views will 29 * be reused if possible when items change. 30 */ 31public abstract class BaseMenuPresenter implements MenuPresenter { 32 protected Context mContext; 33 protected MenuBuilder mMenu; 34 protected LayoutInflater mInflater; 35 private Callback mCallback; 36 37 private int mMenuLayoutRes; 38 private int mItemLayoutRes; 39 40 protected MenuView mMenuView; 41 42 private int mId; 43 44 /** 45 * Construct a new BaseMenuPresenter. 46 * 47 * @param menuLayoutRes Layout resource ID for the menu container view 48 * @param itemLayoutRes Layout resource ID for a single item view 49 */ 50 public BaseMenuPresenter(int menuLayoutRes, int itemLayoutRes) { 51 mMenuLayoutRes = menuLayoutRes; 52 mItemLayoutRes = itemLayoutRes; 53 } 54 55 @Override 56 public void initForMenu(Context context, MenuBuilder menu) { 57 mContext = context; 58 mInflater = LayoutInflater.from(mContext); 59 mMenu = menu; 60 } 61 62 @Override 63 public MenuView getMenuView(ViewGroup root) { 64 if (mMenuView == null) { 65 mMenuView = (MenuView) mInflater.inflate(mMenuLayoutRes, root, false); 66 mMenuView.initialize(mMenu); 67 updateMenuView(true); 68 } 69 70 return mMenuView; 71 } 72 73 /** 74 * Reuses item views when it can 75 */ 76 public void updateMenuView(boolean cleared) { 77 final ViewGroup parent = (ViewGroup) mMenuView; 78 if (parent == null) return; 79 80 int childIndex = 0; 81 if (mMenu != null) { 82 mMenu.flagActionItems(); 83 ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems(); 84 final int itemCount = visibleItems.size(); 85 for (int i = 0; i < itemCount; i++) { 86 MenuItemImpl item = visibleItems.get(i); 87 if (shouldIncludeItem(childIndex, item)) { 88 final View convertView = parent.getChildAt(childIndex); 89 final View itemView = getItemView(item, convertView, parent); 90 if (itemView != convertView) { 91 addItemView(itemView, childIndex); 92 } 93 childIndex++; 94 } 95 } 96 } 97 98 // Remove leftover views. 99 while (childIndex < parent.getChildCount()) { 100 if (!filterLeftoverView(parent, childIndex)) { 101 childIndex++; 102 } 103 } 104 } 105 106 /** 107 * Add an item view at the given index. 108 * 109 * @param itemView View to add 110 * @param childIndex Index within the parent to insert at 111 */ 112 protected void addItemView(View itemView, int childIndex) { 113 final ViewGroup currentParent = (ViewGroup) itemView.getParent(); 114 if (currentParent != null) { 115 currentParent.removeView(itemView); 116 } 117 ((ViewGroup) mMenuView).addView(itemView, childIndex); 118 } 119 120 /** 121 * Filter the child view at index and remove it if appropriate. 122 * @param parent Parent to filter from 123 * @param childIndex Index to filter 124 * @return true if the child view at index was removed 125 */ 126 protected boolean filterLeftoverView(ViewGroup parent, int childIndex) { 127 parent.removeViewAt(childIndex); 128 return true; 129 } 130 131 public void setCallback(Callback cb) { 132 mCallback = cb; 133 } 134 135 /** 136 * Create a new item view that can be re-bound to other item data later. 137 * 138 * @return The new item view 139 */ 140 public MenuView.ItemView createItemView(ViewGroup parent) { 141 return (MenuView.ItemView) mInflater.inflate(mItemLayoutRes, parent, false); 142 } 143 144 /** 145 * Prepare an item view for use. See AdapterView for the basic idea at work here. 146 * This may require creating a new item view, but well-behaved implementations will 147 * re-use the view passed as convertView if present. The returned view will be populated 148 * with data from the item parameter. 149 * 150 * @param item Item to present 151 * @param convertView Existing view to reuse 152 * @param parent Intended parent view - use for inflation. 153 * @return View that presents the requested menu item 154 */ 155 public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { 156 MenuView.ItemView itemView; 157 if (convertView instanceof MenuView.ItemView) { 158 itemView = (MenuView.ItemView) convertView; 159 } else { 160 itemView = createItemView(parent); 161 } 162 bindItemView(item, itemView); 163 return (View) itemView; 164 } 165 166 /** 167 * Bind item data to an existing item view. 168 * 169 * @param item Item to bind 170 * @param itemView View to populate with item data 171 */ 172 public abstract void bindItemView(MenuItemImpl item, MenuView.ItemView itemView); 173 174 /** 175 * Filter item by child index and item data. 176 * 177 * @param childIndex Indended presentation index of this item 178 * @param item Item to present 179 * @return true if this item should be included in this menu presentation; false otherwise 180 */ 181 public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { 182 return true; 183 } 184 185 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 186 if (mCallback != null) { 187 mCallback.onCloseMenu(menu, allMenusAreClosing); 188 } 189 } 190 191 public boolean onSubMenuSelected(SubMenuBuilder menu) { 192 if (mCallback != null) { 193 return mCallback.onOpenSubMenu(menu); 194 } 195 return false; 196 } 197 198 public boolean flagActionItems() { 199 return false; 200 } 201 202 public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 203 return false; 204 } 205 206 public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 207 return false; 208 } 209 210 public int getId() { 211 return mId; 212 } 213 214 public void setId(int id) { 215 mId = id; 216 } 217} 218