AppsCustomizeTabHost.java revision 32174c878c77b4e0f13449f4c26ff6b487bc7ca6
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 17package com.android.launcher2; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ObjectAnimator; 22import android.content.Context; 23import android.content.res.Resources; 24import android.util.AttributeSet; 25import android.view.LayoutInflater; 26import android.view.MotionEvent; 27import android.view.View; 28import android.view.ViewGroup; 29import android.view.ViewPropertyAnimator; 30import android.widget.TabHost; 31import android.widget.TabWidget; 32import android.widget.TextView; 33 34import com.android.launcher.R; 35 36public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable, 37 TabHost.OnTabChangeListener { 38 static final String LOG_TAG = "AppsCustomizeTabHost"; 39 40 private static final String APPS_TAB_TAG = "APPS"; 41 private static final String WIDGETS_TAB_TAG = "WIDGETS"; 42 private static final int sTabBarFadeInDuration = 150; 43 44 private final LayoutInflater mLayoutInflater; 45 private ViewGroup mTabs; 46 private ViewGroup mTabsContainer; 47 private AppsCustomizePagedView mAppsCustomizePane; 48 49 public AppsCustomizeTabHost(Context context, AttributeSet attrs) { 50 super(context, attrs); 51 mLayoutInflater = LayoutInflater.from(context); 52 } 53 54 /** 55 * Convenience methods to select specific tabs 56 */ 57 void selectAppsTab() { 58 setCurrentTabByTag(APPS_TAB_TAG); 59 } 60 void selectWidgetsTab() { 61 setCurrentTabByTag(WIDGETS_TAB_TAG); 62 } 63 64 /** 65 * Setup the tab host and create all necessary tabs. 66 */ 67 @Override 68 protected void onFinishInflate() { 69 // Setup the tab host 70 setup(); 71 72 final ViewGroup tabsContainer = (ViewGroup) findViewById(R.id.tabs_container); 73 final TabWidget tabs = (TabWidget) findViewById(com.android.internal.R.id.tabs); 74 final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView) 75 findViewById(R.id.apps_customize_pane_content); 76 mTabs = tabs; 77 mTabsContainer = tabsContainer; 78 mAppsCustomizePane = appsCustomizePane; 79 if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException(); 80 81 // Configure the tabs content factory to return the same paged view (that we change the 82 // content filter on) 83 TabContentFactory contentFactory = new TabContentFactory() { 84 public View createTabContent(String tag) { 85 return appsCustomizePane; 86 } 87 }; 88 89 // Create the tabs 90 TextView tabView; 91 tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); 92 tabView.setText(mContext.getString(R.string.all_apps_button_label)); 93 addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); 94 tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); 95 tabView.setText(mContext.getString(R.string.widgets_tab_label)); 96 addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); 97 setOnTabChangedListener(this); 98 99 // Setup the key listener to jump between the last tab view and the market icon 100 AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener(); 101 View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1); 102 lastTab.setOnKeyListener(keyListener); 103 View shopButton = findViewById(R.id.market_button); 104 shopButton.setOnKeyListener(keyListener); 105 106 // Hide the tab bar until we measure 107 mTabsContainer.setAlpha(0f); 108 } 109 110 @Override 111 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 112 boolean remeasureTabWidth = (mTabs.getLayoutParams().width <= 0); 113 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 114 115 // Set the width of the tab list to the content width 116 if (remeasureTabWidth) { 117 int contentWidth = mAppsCustomizePane.getPageContentWidth(); 118 if (contentWidth > 0) { 119 // Set the width and show the tab bar (if we have a loading graphic, we can switch 120 // it off here) 121 mTabs.getLayoutParams().width = contentWidth; 122 mTabsContainer.animate().alpha(1f).setDuration(sTabBarFadeInDuration); 123 } 124 } 125 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 126 } 127 128 @Override 129 public boolean onTouchEvent(MotionEvent event) { 130 // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall 131 // through to the workspace and trigger showWorkspace() 132 if (event.getY() < mAppsCustomizePane.getBottom()) { 133 return true; 134 } 135 return super.onTouchEvent(event); 136 } 137 138 @Override 139 public void onTabChanged(String tabId) { 140 final AppsCustomizePagedView.ContentType type = getContentTypeForTabTag(tabId); 141 if (!mAppsCustomizePane.isContentType(type)) { 142 // Animate the changing of the tab content by fading pages in and out 143 final Resources res = getResources(); 144 final int duration = res.getInteger(R.integer.config_tabTransitionDuration); 145 146 ObjectAnimator anim = ObjectAnimator.ofFloat(mAppsCustomizePane, "alpha", 0f); 147 anim.setDuration(duration); 148 anim.addListener(new AnimatorListenerAdapter() { 149 @Override 150 public void onAnimationStart(android.animation.Animator animation) { 151 mAppsCustomizePane.hideScrollingIndicator(false); 152 } 153 @Override 154 public void onAnimationEnd(android.animation.Animator animation) { 155 mAppsCustomizePane.setContentType(type); 156 157 ObjectAnimator anim = ObjectAnimator.ofFloat(mAppsCustomizePane, "alpha", 1f); 158 anim.setDuration(duration); 159 anim.addListener(new AnimatorListenerAdapter() { 160 @Override 161 public void onAnimationEnd(android.animation.Animator animation) { 162 mAppsCustomizePane.flashScrollingIndicator(); 163 } 164 }); 165 anim.start(); 166 } 167 }); 168 anim.start(); 169 } 170 } 171 172 /** 173 * Returns the content type for the specified tab tag. 174 */ 175 public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) { 176 if (tag.equals(APPS_TAB_TAG)) { 177 return AppsCustomizePagedView.ContentType.Applications; 178 } else if (tag.equals(WIDGETS_TAB_TAG)) { 179 return AppsCustomizePagedView.ContentType.Widgets; 180 } 181 return AppsCustomizePagedView.ContentType.Applications; 182 } 183 184 /** 185 * Returns the tab tag for a given content type. 186 */ 187 public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) { 188 if (type == AppsCustomizePagedView.ContentType.Applications) { 189 return APPS_TAB_TAG; 190 } else if (type == AppsCustomizePagedView.ContentType.Widgets) { 191 return WIDGETS_TAB_TAG; 192 } 193 return APPS_TAB_TAG; 194 } 195 196 /** 197 * Disable focus on anything under this view in the hierarchy if we are not visible. 198 */ 199 @Override 200 public int getDescendantFocusability() { 201 if (getVisibility() != View.VISIBLE) { 202 return ViewGroup.FOCUS_BLOCK_DESCENDANTS; 203 } 204 return super.getDescendantFocusability(); 205 } 206 207 /* LauncherTransitionable overrides */ 208 @Override 209 public void onLauncherTransitionStart(Animator animation) { 210 if (animation != null) { 211 // Turn on hardware layers for performance 212 setLayerType(LAYER_TYPE_HARDWARE, null); 213 214 // force building the layer at the beginning of the animation, so you don't get a 215 // blip early in the animation 216 buildLayer(); 217 } 218 } 219 220 @Override 221 public void onLauncherTransitionEnd(Animator animation) { 222 if (animation != null) { 223 setLayerType(LAYER_TYPE_NONE, null); 224 } 225 226 mAppsCustomizePane.flashScrollingIndicator(); 227 } 228} 229