1d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin/* 2d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Copyright (C) 2012 The Android Open Source Project 3d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * 4d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * you may not use this file except in compliance with the License. 6d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * You may obtain a copy of the License at 7d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * 8d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * 10d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * Unless required by applicable law or agreed to in writing, software 11d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * See the License for the specific language governing permissions and 14d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin * limitations under the License. 15d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin */ 1644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 1744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linpackage com.android.gallery3d.ui; 1844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 1944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.content.Context; 2044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.graphics.Rect; 2144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.LayoutInflater; 2244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.View; 2344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.View.MeasureSpec; 2444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewGroup; 2544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewTreeObserver; 2644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.view.ViewTreeObserver.OnGlobalLayoutListener; 2744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.AdapterView; 2844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.AdapterView.OnItemClickListener; 2944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.BaseAdapter; 3044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.ListView; 3144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.PopupWindow; 3244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport android.widget.TextView; 3344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 3444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport com.android.gallery3d.R; 3544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 3644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linimport java.util.ArrayList; 3744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 3844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Linpublic class PopupList { 3944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 4044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public static interface OnPopupItemClickListener { 4144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public boolean onPopupItemClick(int itemId); 4244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 4344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 4444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public static class Item { 4544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public final int id; 4644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public String title; 4744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 4844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public Item(int id, String title) { 4944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin this.id = id; 5044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin this.title = title; 5144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 5244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 5344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void setTitle(String title) { 5444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin this.title = title; 5544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 5644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 5744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 5844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final Context mContext; 5944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final View mAnchorView; 6044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final ArrayList<Item> mItems = new ArrayList<Item>(); 6144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private PopupWindow mPopupWindow; 6244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private ListView mContentList; 6344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private OnPopupItemClickListener mOnPopupItemClickListener; 6444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private int mPopupOffsetX; 6544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private int mPopupOffsetY; 6644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private int mPopupWidth; 6744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private int mPopupHeight; 6844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 6944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public PopupList(Context context, View anchorView) { 7044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mContext = context; 7144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mAnchorView = anchorView; 7244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 7344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 7444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void setOnPopupItemClickListener(OnPopupItemClickListener listener) { 7544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mOnPopupItemClickListener = listener; 7644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 7744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 7844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void addItem(int id, String title) { 7944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mItems.add(new Item(id, title)); 8044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 8144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 82d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin public void clearItems() { 83d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin mItems.clear(); 84d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin } 85d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin 8644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final PopupWindow.OnDismissListener mOnDismissListener = 8744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin new PopupWindow.OnDismissListener() { 8844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @SuppressWarnings("deprecation") 8944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 9044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void onDismiss() { 9144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (mPopupWindow == null) return; 9244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow = null; 9344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin ViewTreeObserver observer = mAnchorView.getViewTreeObserver(); 9444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (observer.isAlive()) { 9544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin // We used the deprecated function for backward compatibility 9644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin // The new "removeOnGlobalLayoutListener" is introduced in API level 16 9744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin observer.removeGlobalOnLayoutListener(mOnGLobalLayoutListener); 9844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 9944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 10044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin }; 10144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 10244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final OnItemClickListener mOnItemClickListener = 10344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin new OnItemClickListener() { 10444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 10544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 10644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (mPopupWindow == null) return; 10744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow.dismiss(); 10844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (mOnPopupItemClickListener != null) { 10944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mOnPopupItemClickListener.onPopupItemClick((int) id); 11044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 11144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 11244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin }; 11344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 11444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private final OnGlobalLayoutListener mOnGLobalLayoutListener = 11544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin new OnGlobalLayoutListener() { 11644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 11744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void onGlobalLayout() { 11844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (mPopupWindow == null) return; 11944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin updatePopupLayoutParams(); 12044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin // Need to update the position of the popup window 12144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow.update(mAnchorView, 12244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupOffsetX, mPopupOffsetY, mPopupWidth, mPopupHeight); 12344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 12444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin }; 12544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 12644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public void show() { 12744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (mPopupWindow != null) return; 12844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mAnchorView.getViewTreeObserver() 12944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin .addOnGlobalLayoutListener(mOnGLobalLayoutListener); 13044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow = createPopupWindow(); 13144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin updatePopupLayoutParams(); 13244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow.setWidth(mPopupWidth); 13344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow.setHeight(mPopupHeight); 13444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWindow.showAsDropDown(mAnchorView, mPopupOffsetX, mPopupOffsetY); 13544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 13644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 13744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private void updatePopupLayoutParams() { 13844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin ListView content = mContentList; 13944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin PopupWindow popup = mPopupWindow; 14044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 14144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin Rect p = new Rect(); 14244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.getBackground().getPadding(p); 14344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 14444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin int maxHeight = mPopupWindow.getMaxAvailableHeight(mAnchorView) - p.top - p.bottom; 14544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mContentList.measure( 14644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 14744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST)); 14844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupWidth = content.getMeasuredWidth() + p.top + p.bottom; 14944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupHeight = Math.min(maxHeight, content.getMeasuredHeight() + p.left + p.right); 15044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupOffsetX = -p.left; 15144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mPopupOffsetY = -p.top; 15244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 15344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 15444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private PopupWindow createPopupWindow() { 155d84941f0649c751c0cc5fd2f6b233380e878ca26Owen Lin PopupWindow popup = new PopupWindow(mContext); 15644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.setOnDismissListener(mOnDismissListener); 15744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 15844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.setBackgroundDrawable(mContext.getResources().getDrawable( 15944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin R.drawable.menu_dropdown_panel_holo_dark)); 1603fa6947fc3909020f3a37cc1fd9a9b9d4d9f93e8Owen Lin 1613fa6947fc3909020f3a37cc1fd9a9b9d4d9f93e8Owen Lin mContentList = new ListView(mContext, null, 1622abaaf7caa9a83ba1ea759868aabde7f21387184John Reck android.R.attr.dropDownListViewStyle); 16344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mContentList.setAdapter(new ItemDataAdapter()); 16444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin mContentList.setOnItemClickListener(mOnItemClickListener); 16544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.setContentView(mContentList); 16644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.setFocusable(true); 16744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin popup.setOutsideTouchable(true); 16844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 16944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return popup; 17044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 17144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 17244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public Item findItem(int id) { 17344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin for (Item item : mItems) { 17444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (item.id == id) return item; 17544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 17644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return null; 17744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 17844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 17944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin private class ItemDataAdapter extends BaseAdapter { 18044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 18144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public int getCount() { 18244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return mItems.size(); 18344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 18444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 18544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 18644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public Object getItem(int position) { 18744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return mItems.get(position); 18844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 18944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 19044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 19144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public long getItemId(int position) { 19244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return mItems.get(position).id; 19344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 19444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin 19544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin @Override 19644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin public View getView(int position, View convertView, ViewGroup parent) { 19744ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin if (convertView == null) { 19844ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin convertView = LayoutInflater.from(mContext) 19944ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin .inflate(R.layout.popup_list_item, null); 20044ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 20144ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin TextView text = (TextView) convertView.findViewById(android.R.id.text1); 20244ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin text.setText(mItems.get(position).title); 20344ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin return convertView; 20444ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 20544ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin } 20644ef42f215d68ade8b63d18fede944c244a2a1ddOwen Lin} 207