1 /* 2 * Copyright (C) 2012 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.gallery3d.ui; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.view.LayoutInflater; 22 import android.view.View; 23 import android.view.View.MeasureSpec; 24 import android.view.ViewGroup; 25 import android.view.ViewTreeObserver; 26 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 27 import android.widget.AdapterView; 28 import android.widget.AdapterView.OnItemClickListener; 29 import android.widget.BaseAdapter; 30 import android.widget.ListView; 31 import android.widget.PopupWindow; 32 import android.widget.TextView; 33 34 import com.android.gallery3d.R; 35 36 import java.util.ArrayList; 37 38 public class PopupList { 39 40 public static interface OnPopupItemClickListener { onPopupItemClick(int itemId)41 public boolean onPopupItemClick(int itemId); 42 } 43 44 public static class Item { 45 public final int id; 46 public String title; 47 Item(int id, String title)48 public Item(int id, String title) { 49 this.id = id; 50 this.title = title; 51 } 52 setTitle(String title)53 public void setTitle(String title) { 54 this.title = title; 55 } 56 } 57 58 private final Context mContext; 59 private final View mAnchorView; 60 private final ArrayList<Item> mItems = new ArrayList<Item>(); 61 private PopupWindow mPopupWindow; 62 private ListView mContentList; 63 private OnPopupItemClickListener mOnPopupItemClickListener; 64 private int mPopupOffsetX; 65 private int mPopupOffsetY; 66 private int mPopupWidth; 67 private int mPopupHeight; 68 PopupList(Context context, View anchorView)69 public PopupList(Context context, View anchorView) { 70 mContext = context; 71 mAnchorView = anchorView; 72 } 73 setOnPopupItemClickListener(OnPopupItemClickListener listener)74 public void setOnPopupItemClickListener(OnPopupItemClickListener listener) { 75 mOnPopupItemClickListener = listener; 76 } 77 addItem(int id, String title)78 public void addItem(int id, String title) { 79 mItems.add(new Item(id, title)); 80 } 81 clearItems()82 public void clearItems() { 83 mItems.clear(); 84 } 85 86 private final PopupWindow.OnDismissListener mOnDismissListener = 87 new PopupWindow.OnDismissListener() { 88 @SuppressWarnings("deprecation") 89 @Override 90 public void onDismiss() { 91 if (mPopupWindow == null) return; 92 mPopupWindow = null; 93 ViewTreeObserver observer = mAnchorView.getViewTreeObserver(); 94 if (observer.isAlive()) { 95 // We used the deprecated function for backward compatibility 96 // The new "removeOnGlobalLayoutListener" is introduced in API level 16 97 observer.removeGlobalOnLayoutListener(mOnGLobalLayoutListener); 98 } 99 } 100 }; 101 102 private final OnItemClickListener mOnItemClickListener = 103 new OnItemClickListener() { 104 @Override 105 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 106 if (mPopupWindow == null) return; 107 mPopupWindow.dismiss(); 108 if (mOnPopupItemClickListener != null) { 109 mOnPopupItemClickListener.onPopupItemClick((int) id); 110 } 111 } 112 }; 113 114 private final OnGlobalLayoutListener mOnGLobalLayoutListener = 115 new OnGlobalLayoutListener() { 116 @Override 117 public void onGlobalLayout() { 118 if (mPopupWindow == null) return; 119 updatePopupLayoutParams(); 120 // Need to update the position of the popup window 121 mPopupWindow.update(mAnchorView, 122 mPopupOffsetX, mPopupOffsetY, mPopupWidth, mPopupHeight); 123 } 124 }; 125 show()126 public void show() { 127 if (mPopupWindow != null) return; 128 mAnchorView.getViewTreeObserver() 129 .addOnGlobalLayoutListener(mOnGLobalLayoutListener); 130 mPopupWindow = createPopupWindow(); 131 updatePopupLayoutParams(); 132 mPopupWindow.setWidth(mPopupWidth); 133 mPopupWindow.setHeight(mPopupHeight); 134 mPopupWindow.showAsDropDown(mAnchorView, mPopupOffsetX, mPopupOffsetY); 135 } 136 updatePopupLayoutParams()137 private void updatePopupLayoutParams() { 138 ListView content = mContentList; 139 PopupWindow popup = mPopupWindow; 140 141 Rect p = new Rect(); 142 popup.getBackground().getPadding(p); 143 144 int maxHeight = mPopupWindow.getMaxAvailableHeight(mAnchorView) - p.top - p.bottom; 145 mContentList.measure( 146 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 147 MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST)); 148 mPopupWidth = content.getMeasuredWidth() + p.top + p.bottom; 149 mPopupHeight = Math.min(maxHeight, content.getMeasuredHeight() + p.left + p.right); 150 mPopupOffsetX = -p.left; 151 mPopupOffsetY = -p.top; 152 } 153 createPopupWindow()154 private PopupWindow createPopupWindow() { 155 PopupWindow popup = new PopupWindow(mContext); 156 popup.setOnDismissListener(mOnDismissListener); 157 158 popup.setBackgroundDrawable(mContext.getResources().getDrawable( 159 R.drawable.menu_dropdown_panel_holo_dark)); 160 161 mContentList = new ListView(mContext, null, 162 android.R.attr.dropDownListViewStyle); 163 mContentList.setAdapter(new ItemDataAdapter()); 164 mContentList.setOnItemClickListener(mOnItemClickListener); 165 popup.setContentView(mContentList); 166 popup.setFocusable(true); 167 popup.setOutsideTouchable(true); 168 169 return popup; 170 } 171 findItem(int id)172 public Item findItem(int id) { 173 for (Item item : mItems) { 174 if (item.id == id) return item; 175 } 176 return null; 177 } 178 179 private class ItemDataAdapter extends BaseAdapter { 180 @Override getCount()181 public int getCount() { 182 return mItems.size(); 183 } 184 185 @Override getItem(int position)186 public Object getItem(int position) { 187 return mItems.get(position); 188 } 189 190 @Override getItemId(int position)191 public long getItemId(int position) { 192 return mItems.get(position).id; 193 } 194 195 @Override getView(int position, View convertView, ViewGroup parent)196 public View getView(int position, View convertView, ViewGroup parent) { 197 if (convertView == null) { 198 convertView = LayoutInflater.from(mContext) 199 .inflate(R.layout.popup_list_item, null); 200 } 201 TextView text = (TextView) convertView.findViewById(android.R.id.text1); 202 text.setText(mItems.get(position).title); 203 return convertView; 204 } 205 } 206 } 207