NavigationMenuItemView.java revision f3865fbd67715b07d43da357dea742edf3bf9913
1/*
2 * Copyright (C) 2015 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 android.support.design.internal;
18
19import android.content.Context;
20import android.content.res.ColorStateList;
21import android.graphics.Color;
22import android.graphics.drawable.ColorDrawable;
23import android.graphics.drawable.Drawable;
24import android.graphics.drawable.StateListDrawable;
25import android.support.design.R;
26import android.support.v4.content.res.ResourcesCompat;
27import android.support.v4.graphics.drawable.DrawableCompat;
28import android.support.v4.widget.TextViewCompat;
29import android.support.v7.view.menu.MenuItemImpl;
30import android.support.v7.view.menu.MenuView;
31import android.util.AttributeSet;
32import android.util.TypedValue;
33import android.view.LayoutInflater;
34import android.view.View;
35import android.view.ViewStub;
36import android.widget.CheckedTextView;
37import android.widget.FrameLayout;
38
39/**
40 * @hide
41 */
42public class NavigationMenuItemView extends ForegroundLinearLayout implements MenuView.ItemView {
43
44    private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
45
46    private final int mIconSize;
47
48    private boolean mNeedsEmptyIcon;
49
50    private final CheckedTextView mTextView;
51
52    private FrameLayout mActionArea;
53
54    private MenuItemImpl mItemData;
55
56    private ColorStateList mIconTintList;
57
58    private Drawable mEmptyDrawable;
59
60    public NavigationMenuItemView(Context context) {
61        this(context, null);
62    }
63
64    public NavigationMenuItemView(Context context, AttributeSet attrs) {
65        this(context, attrs, 0);
66    }
67
68    public NavigationMenuItemView(Context context, AttributeSet attrs, int defStyleAttr) {
69        super(context, attrs, defStyleAttr);
70        setOrientation(HORIZONTAL);
71        LayoutInflater.from(context).inflate(R.layout.design_navigation_menu_item, this, true);
72        mIconSize = context.getResources().getDimensionPixelSize(
73                R.dimen.design_navigation_icon_size);
74        mTextView = (CheckedTextView) findViewById(R.id.design_menu_item_text);
75        mTextView.setDuplicateParentStateEnabled(true);
76    }
77
78    @Override
79    public void initialize(MenuItemImpl itemData, int menuType) {
80        mItemData = itemData;
81
82        setVisibility(itemData.isVisible() ? VISIBLE : GONE);
83
84        if (getBackground() == null) {
85            setBackgroundDrawable(createDefaultBackground());
86        }
87
88        setCheckable(itemData.isCheckable());
89        setChecked(itemData.isChecked());
90        setEnabled(itemData.isEnabled());
91        setTitle(itemData.getTitle());
92        setIcon(itemData.getIcon());
93        setActionView(itemData.getActionView());
94        adjustAppearance();
95    }
96
97    private boolean shouldExpandActionArea() {
98        return mItemData.getTitle() == null &&
99                mItemData.getIcon() == null &&
100                mItemData.getActionView() != null;
101    }
102
103    private void adjustAppearance() {
104        if (shouldExpandActionArea()) {
105            // Expand the actionView area
106            mTextView.setVisibility(View.GONE);
107            if (mActionArea != null) {
108                LayoutParams params = (LayoutParams) mActionArea.getLayoutParams();
109                params.width = LayoutParams.MATCH_PARENT;
110                mActionArea.setLayoutParams(params);
111            }
112        } else {
113            mTextView.setVisibility(View.VISIBLE);
114            if (mActionArea != null) {
115                LayoutParams params = (LayoutParams) mActionArea.getLayoutParams();
116                params.width = LayoutParams.WRAP_CONTENT;
117                mActionArea.setLayoutParams(params);
118            }
119        }
120    }
121
122    public void recycle() {
123        if (mActionArea != null) {
124            mActionArea.removeAllViews();
125        }
126        mTextView.setCompoundDrawables(null, null, null, null);
127    }
128
129    private void setActionView(View actionView) {
130        if (actionView != null) {
131            if (mActionArea == null) {
132                mActionArea = (FrameLayout) ((ViewStub) findViewById(
133                        R.id.design_menu_item_action_area_stub)).inflate();
134            }
135            mActionArea.removeAllViews();
136            mActionArea.addView(actionView);
137        }
138    }
139
140    private StateListDrawable createDefaultBackground() {
141        TypedValue value = new TypedValue();
142        if (getContext().getTheme().resolveAttribute(
143                android.support.v7.appcompat.R.attr.colorControlHighlight, value, true)) {
144            StateListDrawable drawable = new StateListDrawable();
145            drawable.addState(CHECKED_STATE_SET, new ColorDrawable(value.data));
146            drawable.addState(EMPTY_STATE_SET, new ColorDrawable(Color.TRANSPARENT));
147            return drawable;
148        }
149        return null;
150    }
151
152    @Override
153    public MenuItemImpl getItemData() {
154        return mItemData;
155    }
156
157    @Override
158    public void setTitle(CharSequence title) {
159        mTextView.setText(title);
160    }
161
162    @Override
163    public void setCheckable(boolean checkable) {
164        refreshDrawableState();
165    }
166
167    @Override
168    public void setChecked(boolean checked) {
169        refreshDrawableState();
170        mTextView.setChecked(checked);
171    }
172
173    @Override
174    public void setShortcut(boolean showShortcut, char shortcutKey) {
175    }
176
177    @Override
178    public void setIcon(Drawable icon) {
179        if (icon != null) {
180            Drawable.ConstantState state = icon.getConstantState();
181            icon = DrawableCompat.wrap(state == null ? icon : state.newDrawable()).mutate();
182            icon.setBounds(0, 0, mIconSize, mIconSize);
183            DrawableCompat.setTintList(icon, mIconTintList);
184        } else if (mNeedsEmptyIcon) {
185            if (mEmptyDrawable == null) {
186                mEmptyDrawable = ResourcesCompat.getDrawable(getResources(),
187                        R.drawable.navigation_empty_icon, getContext().getTheme());
188                if (mEmptyDrawable != null) {
189                    mEmptyDrawable.setBounds(0, 0, mIconSize, mIconSize);
190                }
191            }
192            icon = mEmptyDrawable;
193        }
194        TextViewCompat.setCompoundDrawablesRelative(mTextView, icon, null, null, null);
195    }
196
197    @Override
198    public boolean prefersCondensedTitle() {
199        return false;
200    }
201
202    @Override
203    public boolean showsIcon() {
204        return true;
205    }
206
207    @Override
208    protected int[] onCreateDrawableState(int extraSpace) {
209        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
210        if (mItemData != null && mItemData.isCheckable() && mItemData.isChecked()) {
211            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
212        }
213        return drawableState;
214    }
215
216    void setIconTintList(ColorStateList tintList) {
217        mIconTintList = tintList;
218        if (mItemData != null) {
219            // Update the icon so that the tint takes effect
220            setIcon(mItemData.getIcon());
221        }
222    }
223
224    public void setTextAppearance(Context context, int textAppearance) {
225        mTextView.setTextAppearance(context, textAppearance);
226    }
227
228    public void setTextColor(ColorStateList colors) {
229        mTextView.setTextColor(colors);
230    }
231
232    public void setNeedsEmptyIcon(boolean needsEmptyIcon) {
233        mNeedsEmptyIcon = needsEmptyIcon;
234    }
235
236}
237