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