ActionMenuView.java revision f75eeb28def26798682748aa5dedabebac86bb6a
1/*
2 * Copyright (C) 2010 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 */
16package com.android.internal.view.menu;
17
18import android.content.Context;
19import android.content.res.Configuration;
20import android.content.res.Resources;
21import android.content.res.TypedArray;
22import android.util.AttributeSet;
23import android.view.ViewGroup;
24import android.widget.ImageButton;
25import android.widget.LinearLayout;
26
27import java.lang.ref.WeakReference;
28import java.util.ArrayList;
29
30/**
31 * @hide
32 */
33public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
34    private static final String TAG = "ActionMenuView";
35
36    private MenuBuilder mMenu;
37
38    private int mItemPadding;
39    private int mItemMargin;
40    private int mMaxItems;
41    private boolean mReserveOverflow;
42    private OverflowMenuButton mOverflowButton;
43    private WeakReference<MenuPopupHelper> mOverflowPopup;
44
45    public ActionMenuView(Context context) {
46        this(context, null);
47    }
48
49    public ActionMenuView(Context context, AttributeSet attrs) {
50        super(context, attrs);
51
52        TypedArray a = context.obtainStyledAttributes(attrs,
53                com.android.internal.R.styleable.Theme);
54        mItemPadding = a.getDimensionPixelOffset(
55                com.android.internal.R.styleable.Theme_actionButtonPadding, 0);
56        mItemMargin = mItemPadding / 2;
57        a.recycle();
58
59        final Resources res = getResources();
60        final int size = res.getDimensionPixelSize(com.android.internal.R.dimen.action_icon_size);
61        final int spaceAvailable = res.getDisplayMetrics().widthPixels / 2;
62        final int itemSpace = size + mItemPadding;
63
64        mMaxItems = spaceAvailable / (itemSpace > 0 ? itemSpace : 1);
65
66        // TODO There has to be a better way to indicate that we don't have a hard menu key.
67        final int screen = res.getConfiguration().screenLayout;
68        mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
69                Configuration.SCREENLAYOUT_SIZE_XLARGE;
70    }
71
72    public boolean isOverflowReserved() {
73        return mReserveOverflow;
74    }
75
76    public void setOverflowReserved(boolean reserveOverflow) {
77        mReserveOverflow = reserveOverflow;
78    }
79
80    @Override
81    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
82        if (p instanceof LayoutParams) {
83            LayoutParams lp = (LayoutParams) p;
84            return lp.leftMargin == mItemMargin && lp.rightMargin == mItemMargin &&
85                    lp.width == LayoutParams.WRAP_CONTENT && lp.height == LayoutParams.WRAP_CONTENT;
86        }
87        return false;
88    }
89
90    @Override
91    protected LayoutParams generateDefaultLayoutParams() {
92        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
93                LayoutParams.WRAP_CONTENT);
94        params.leftMargin = mItemMargin;
95        params.rightMargin = mItemMargin;
96        return params;
97    }
98
99    @Override
100    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
101        return generateDefaultLayoutParams();
102    }
103
104    public int getItemMargin() {
105        return mItemMargin;
106    }
107
108    public boolean invokeItem(MenuItemImpl item) {
109        return mMenu.performItemAction(item, 0);
110    }
111
112    public int getWindowAnimations() {
113        return 0;
114    }
115
116    public void initialize(MenuBuilder menu, int menuType) {
117        menu.setMaxActionItems(mMaxItems);
118        mMenu = menu;
119        updateChildren(true);
120    }
121
122    public void updateChildren(boolean cleared) {
123        final boolean reserveOverflow = mReserveOverflow;
124        removeAllViews();
125
126        final ArrayList<MenuItemImpl> itemsToShow = mMenu.getActionItems(reserveOverflow);
127        final int itemCount = itemsToShow.size();
128
129        for (int i = 0; i < itemCount; i++) {
130            final MenuItemImpl itemData = itemsToShow.get(i);
131            addItemView((ActionMenuItemView) itemData.getItemView(MenuBuilder.TYPE_ACTION_BUTTON,
132                    this));
133        }
134
135        if (reserveOverflow) {
136            if (mMenu.getNonActionItems(true).size() > 0) {
137                OverflowMenuButton button = new OverflowMenuButton(mContext);
138                addView(button);
139                mOverflowButton = button;
140            } else {
141                mOverflowButton = null;
142            }
143        }
144    }
145
146    public boolean showOverflowMenu() {
147        if (mOverflowButton != null) {
148            MenuPopupHelper popup = new MenuPopupHelper(getContext(), mMenu, mOverflowButton, true);
149            popup.show();
150            mOverflowPopup = new WeakReference<MenuPopupHelper>(popup);
151            return true;
152        }
153        return false;
154    }
155
156    public boolean hideOverflowMenu() {
157        MenuPopupHelper popup = mOverflowPopup != null ? mOverflowPopup.get() : null;
158        if (popup != null) {
159            popup.dismiss();
160            return true;
161        }
162        return false;
163    }
164
165    private void addItemView(ActionMenuItemView view) {
166        view.setItemInvoker(this);
167        addView(view);
168    }
169
170    private class OverflowMenuButton extends ImageButton {
171        public OverflowMenuButton(Context context) {
172            super(context, null, com.android.internal.R.attr.actionButtonStyle);
173
174            final Resources res = context.getResources();
175            setClickable(true);
176            setFocusable(true);
177            // TODO setTitle() to a localized string for accessibility
178            setImageDrawable(res.getDrawable(com.android.internal.R.drawable.ic_menu_more));
179            setVisibility(VISIBLE);
180            setEnabled(true);
181        }
182
183        @Override
184        public boolean performClick() {
185            if (super.performClick()) {
186                return true;
187            }
188
189            showOverflowMenu();
190            return true;
191        }
192    }
193}
194