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 */ 16 17 package com.android.launcher3; 18 19 import android.content.Context; 20 import android.graphics.Rect; 21 import android.util.AttributeSet; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.view.accessibility.AccessibilityManager; 25 import android.widget.FrameLayout; 26 27 public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransitionable, Insettable { 28 static final String LOG_TAG = "AppsCustomizeTabHost"; 29 30 private static final String APPS_TAB_TAG = "APPS"; 31 private static final String WIDGETS_TAB_TAG = "WIDGETS"; 32 33 private AppsCustomizePagedView mPagedView; 34 private View mContent; 35 private boolean mInTransition = false; 36 37 private final Rect mInsets = new Rect(); 38 39 public AppsCustomizeTabHost(Context context, AttributeSet attrs) { 40 super(context, attrs); 41 } 42 43 /** 44 * Convenience methods to select specific tabs. We want to set the content type immediately 45 * in these cases, but we note that we still call setCurrentTabByTag() so that the tab view 46 * reflects the new content (but doesn't do the animation and logic associated with changing 47 * tabs manually). 48 */ 49 void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) { 50 mPagedView.setContentType(type); 51 } 52 53 public void setCurrentTabFromContent(AppsCustomizePagedView.ContentType type) { 54 setContentTypeImmediate(type); 55 } 56 57 @Override 58 public void setInsets(Rect insets) { 59 mInsets.set(insets); 60 LayoutParams flp = (LayoutParams) mContent.getLayoutParams(); 61 flp.topMargin = insets.top; 62 flp.bottomMargin = insets.bottom; 63 flp.leftMargin = insets.left; 64 flp.rightMargin = insets.right; 65 mContent.setLayoutParams(flp); 66 } 67 68 /** 69 * Setup the tab host and create all necessary tabs. 70 */ 71 @Override 72 protected void onFinishInflate() { 73 mPagedView = (AppsCustomizePagedView) findViewById(R.id.apps_customize_pane_content); 74 mContent = findViewById(R.id.content); 75 } 76 77 public String getContentTag() { 78 return getTabTagForContentType(mPagedView.getContentType()); 79 } 80 81 /** 82 * Returns the content type for the specified tab tag. 83 */ 84 public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) { 85 if (tag.equals(APPS_TAB_TAG)) { 86 return AppsCustomizePagedView.ContentType.Applications; 87 } else if (tag.equals(WIDGETS_TAB_TAG)) { 88 return AppsCustomizePagedView.ContentType.Widgets; 89 } 90 return AppsCustomizePagedView.ContentType.Applications; 91 } 92 93 /** 94 * Returns the tab tag for a given content type. 95 */ 96 public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) { 97 if (type == AppsCustomizePagedView.ContentType.Applications) { 98 return APPS_TAB_TAG; 99 } else if (type == AppsCustomizePagedView.ContentType.Widgets) { 100 return WIDGETS_TAB_TAG; 101 } 102 return APPS_TAB_TAG; 103 } 104 105 /** 106 * Disable focus on anything under this view in the hierarchy if we are not visible. 107 */ 108 @Override 109 public int getDescendantFocusability() { 110 if (getVisibility() != View.VISIBLE) { 111 return ViewGroup.FOCUS_BLOCK_DESCENDANTS; 112 } 113 return super.getDescendantFocusability(); 114 } 115 116 void reset() { 117 // Reset immediately 118 mPagedView.reset(); 119 } 120 121 void trimMemory() { 122 mPagedView.trimMemory(); 123 } 124 125 public void onWindowVisible() { 126 if (getVisibility() == VISIBLE) { 127 mContent.setVisibility(VISIBLE); 128 // We unload the widget previews when the UI is hidden, so need to reload pages 129 // Load the current page synchronously, and the neighboring pages asynchronously 130 mPagedView.loadAssociatedPages(mPagedView.getCurrentPage(), true); 131 mPagedView.loadAssociatedPages(mPagedView.getCurrentPage()); 132 } 133 } 134 @Override 135 public ViewGroup getContent() { 136 return mPagedView; 137 } 138 139 public boolean isInTransition() { 140 return mInTransition; 141 } 142 143 /* LauncherTransitionable overrides */ 144 @Override 145 public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) { 146 mPagedView.onLauncherTransitionPrepare(l, animated, toWorkspace); 147 mInTransition = true; 148 149 if (toWorkspace) { 150 // Going from All Apps -> Workspace 151 setVisibilityOfSiblingsWithLowerZOrder(VISIBLE); 152 } else { 153 // Going from Workspace -> All Apps 154 mContent.setVisibility(VISIBLE); 155 156 // Make sure the current page is loaded (we start loading the side pages after the 157 // transition to prevent slowing down the animation) 158 // TODO: revisit this 159 mPagedView.loadAssociatedPages(mPagedView.getCurrentPage()); 160 } 161 } 162 163 @Override 164 public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) { 165 mPagedView.onLauncherTransitionStart(l, animated, toWorkspace); 166 } 167 168 @Override 169 public void onLauncherTransitionStep(Launcher l, float t) { 170 mPagedView.onLauncherTransitionStep(l, t); 171 } 172 173 @Override 174 public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { 175 mPagedView.onLauncherTransitionEnd(l, animated, toWorkspace); 176 mInTransition = false; 177 178 if (!toWorkspace) { 179 // Make sure adjacent pages are loaded (we wait until after the transition to 180 // prevent slowing down the animation) 181 mPagedView.loadAssociatedPages(mPagedView.getCurrentPage()); 182 183 // Opening apps, need to announce what page we are on. 184 AccessibilityManager am = (AccessibilityManager) 185 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 186 if (am.isEnabled()) { 187 // Notify the user when the page changes 188 announceForAccessibility(mPagedView.getCurrentPageDescription()); 189 } 190 191 // Going from Workspace -> All Apps 192 // NOTE: We should do this at the end since we check visibility state in some of the 193 // cling initialization/dismiss code above. 194 setVisibilityOfSiblingsWithLowerZOrder(INVISIBLE); 195 } 196 } 197 198 private void setVisibilityOfSiblingsWithLowerZOrder(int visibility) { 199 ViewGroup parent = (ViewGroup) getParent(); 200 if (parent == null) return; 201 202 View overviewPanel = ((Launcher) getContext()).getOverviewPanel(); 203 final int count = parent.getChildCount(); 204 if (!isChildrenDrawingOrderEnabled()) { 205 for (int i = 0; i < count; i++) { 206 final View child = parent.getChildAt(i); 207 if (child == this) { 208 break; 209 } else { 210 if (child.getVisibility() == GONE || child == overviewPanel) { 211 continue; 212 } 213 child.setVisibility(visibility); 214 } 215 } 216 } else { 217 throw new RuntimeException("Failed; can't get z-order of views"); 218 } 219 } 220 } 221