1/* 2 * Copyright (C) 2011 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 android.support.v7.internal.widget; 17 18import android.content.Context; 19import android.content.res.Configuration; 20import android.content.res.TypedArray; 21import android.os.Build; 22import android.support.v7.appcompat.R; 23import android.support.v7.internal.view.menu.ActionMenuPresenter; 24import android.support.v7.internal.view.menu.ActionMenuView; 25import android.util.AttributeSet; 26import android.view.View; 27import android.view.ViewGroup; 28import android.view.animation.Animation; 29import android.view.animation.AnimationUtils; 30 31abstract class AbsActionBarView extends ViewGroup { 32 33 protected ActionMenuView mMenuView; 34 35 protected ActionMenuPresenter mActionMenuPresenter; 36 37 protected ActionBarContainer mSplitView; 38 39 protected boolean mSplitActionBar; 40 41 protected boolean mSplitWhenNarrow; 42 43 protected int mContentHeight; 44 45 private static final int FADE_DURATION = 200; 46 47 AbsActionBarView(Context context) { 48 super(context); 49 } 50 51 AbsActionBarView(Context context, AttributeSet attrs) { 52 super(context, attrs); 53 } 54 55 AbsActionBarView(Context context, AttributeSet attrs, int defStyle) { 56 super(context, attrs, defStyle); 57 } 58 59 @Override 60 protected void onConfigurationChanged(Configuration newConfig) { 61 if (Build.VERSION.SDK_INT >= 8) { 62 super.onConfigurationChanged(newConfig); 63 } 64 65 // Action bar can change size on configuration changes. 66 // Reread the desired height from the theme-specified style. 67 TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar, 68 R.attr.actionBarStyle, 0); 69 setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0)); 70 a.recycle(); 71 if (mSplitWhenNarrow) { 72 setSplitActionBar(getContext().getResources().getBoolean( 73 R.bool.abc_split_action_bar_is_narrow)); 74 } 75 if (mActionMenuPresenter != null) { 76 mActionMenuPresenter.onConfigurationChanged(newConfig); 77 } 78 } 79 80 /** 81 * Sets whether the bar should be split right now, no questions asked. 82 * 83 * @param split true if the bar should split 84 */ 85 public void setSplitActionBar(boolean split) { 86 mSplitActionBar = split; 87 } 88 89 /** 90 * Sets whether the bar should split if we enter a narrow screen configuration. 91 * 92 * @param splitWhenNarrow true if the bar should check to split after a config change 93 */ 94 public void setSplitWhenNarrow(boolean splitWhenNarrow) { 95 mSplitWhenNarrow = splitWhenNarrow; 96 } 97 98 public void setContentHeight(int height) { 99 mContentHeight = height; 100 requestLayout(); 101 } 102 103 public int getContentHeight() { 104 return mContentHeight; 105 } 106 107 public void setSplitView(ActionBarContainer splitView) { 108 mSplitView = splitView; 109 } 110 111 /** 112 * @return Current visibility or if animating, the visibility being animated to. 113 */ 114 public int getAnimatedVisibility() { 115 return getVisibility(); 116 } 117 118 public void animateToVisibility(int visibility) { 119 clearAnimation(); 120 121 if (visibility != getVisibility()) { 122 Animation anim = AnimationUtils.loadAnimation(getContext(), 123 visibility == View.VISIBLE ? R.anim.abc_fade_in : R.anim.abc_fade_out); 124 125 startAnimation(anim); 126 setVisibility(visibility); 127 128 if (mSplitView != null && mMenuView != null) { 129 mMenuView.startAnimation(anim); 130 mMenuView.setVisibility(visibility); 131 } 132 } 133 } 134 135 @Override 136 public void setVisibility(int visibility) { 137 if (visibility != getVisibility()) { 138 super.setVisibility(visibility); 139 } 140 } 141 142 public boolean showOverflowMenu() { 143 if (mActionMenuPresenter != null) { 144 return mActionMenuPresenter.showOverflowMenu(); 145 } 146 return false; 147 } 148 149 public void postShowOverflowMenu() { 150 post(new Runnable() { 151 public void run() { 152 showOverflowMenu(); 153 } 154 }); 155 } 156 157 public boolean hideOverflowMenu() { 158 if (mActionMenuPresenter != null) { 159 return mActionMenuPresenter.hideOverflowMenu(); 160 } 161 return false; 162 } 163 164 public boolean isOverflowMenuShowing() { 165 if (mActionMenuPresenter != null) { 166 return mActionMenuPresenter.isOverflowMenuShowing(); 167 } 168 return false; 169 } 170 171 public boolean isOverflowReserved() { 172 return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved(); 173 } 174 175 public void dismissPopupMenus() { 176 if (mActionMenuPresenter != null) { 177 mActionMenuPresenter.dismissPopupMenus(); 178 } 179 } 180 181 protected int measureChildView(View child, int availableWidth, int childSpecHeight, 182 int spacing) { 183 child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), 184 childSpecHeight); 185 186 availableWidth -= child.getMeasuredWidth(); 187 availableWidth -= spacing; 188 189 return Math.max(0, availableWidth); 190 } 191 192 protected int positionChild(View child, int x, int y, int contentHeight) { 193 int childWidth = child.getMeasuredWidth(); 194 int childHeight = child.getMeasuredHeight(); 195 int childTop = y + (contentHeight - childHeight) / 2; 196 197 child.layout(x, childTop, x + childWidth, childTop + childHeight); 198 199 return childWidth; 200 } 201 202 protected int positionChildInverse(View child, int x, int y, int contentHeight) { 203 int childWidth = child.getMeasuredWidth(); 204 int childHeight = child.getMeasuredHeight(); 205 int childTop = y + (contentHeight - childHeight) / 2; 206 207 child.layout(x - childWidth, childTop, x, childTop + childHeight); 208 209 return childWidth; 210 } 211 212} 213