/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.widget;
import java.util.ArrayList;
import java.util.List;
import tws.component.log.TwsLog;
import android.app.LocalActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import com.tencent.tws.assistant.support.v4.app.Fragment;
import com.tencent.tws.assistant.support.v4.app.FragmentManager;
import com.tencent.tws.assistant.support.v4.app.FragmentTransaction;
import com.tencent.tws.assistant.support.v4.view.PagerAdapter;
import com.tencent.tws.assistant.support.v4.view.ViewPager;
import com.tencent.tws.assistant.widget.TabIndicator;
import com.tencent.tws.framework.HostProxy;
import com.tencent.tws.sharelib.R;
/**
* Container for a tabbed window view. This object holds two children: a set of
* tab labels that the user clicks to select a specific tab, and a FrameLayout
* object that displays the contents of that page. The individual elements are
* typically controlled using this container object, rather than setting values
* on the child elements themselves.
*
* <p>
* See the <a href="{@docRoot}
* resources/tutorials/views/hello-tabwidget.html">Tab Layout tutorial</a>.
* </p>
*/
public class TwsTabHost extends FrameLayout implements ViewTreeObserver.OnTouchModeChangeListener {
private static final String TAG = "TabHost";
private TwsTabWidget mTabWidget;
private FrameLayout mTabContent;
private List<TabSpec> mTabSpecs = new ArrayList<TabSpec>(2);
/**
* This field should be made private, so it is hidden from the SDK. {@hide
*
*
* }
*/
protected int mCurrentTab = -1;
private View mCurrentView = null;
/**
* This field should be made private, so it is hidden from the SDK. {@hide
*
*
* }
*/
protected LocalActivityManager mLocalActivityManager = null;
private OnTabChangeListener mOnTabChangeListener;
private OnKeyListener mTabKeyListener;
private int mTabLayoutId;
// //tws-start add tabIndicator::2014-9-23
private TabIndicator mTabIndicator = null;
// tws-end add tabIndicator::2014-9-23
// tws-start::support slide to switch tabs2013-05-06
private FragmentManager mFragmentManager;
private ViewPager mViewPager;
private ViewPagerAdapter mViewPagerAdapter;
private ViewPager.OnPageChangeListener mPagerListener;
// tws-start add smooth scroll feature to tab::2014-11-18
private boolean mInit = false;
private int mSelectedColor = 0;
private int mNormalColor = 0;
private ColorStateList mTextColors = null;
// private ColorStateList mNormalColors;
// tws-end add smooth scroll feature to tab ::2014-11-18
public static TwsTabHost inflateFromHost() {
final LayoutInflater li = (LayoutInflater) HostProxy.getApplication().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
return (TwsTabHost) li.inflate(R.layout.tab_content, null);
}
public static TwsTabHost inflateFromHost(String layoutResName) {
final LayoutInflater li = (LayoutInflater) HostProxy.getApplication().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
final int id = HostProxy.getShareLayoutId(layoutResName);
if (0 == id)
return null;
else {
return (TwsTabHost) li.inflate(id, null);
}
}
private ViewPager.OnPageChangeListener mViewPagerListener = new ViewPager.OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {
if (mPagerListener != null) {
mPagerListener.onPageScrollStateChanged(state);
}
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mPagerListener != null) {
mPagerListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
// determin all tab indicator suppport text fade animation
for (TabSpec tabSpec : mTabSpecs) {
if (tabSpec.mIndicatorStrategy == null && tabSpec.mIndicatorStrategy.supportTextFade() == false)
return;
}
if (position < 0 || position >= mTabSpecs.size() - 1)
return;
if (positionOffset < 0 || positionOffset > 1)
return;
if (positionOffset == 0.0 || positionOffset == 1.0 || position == mTabSpecs.size() - 1) {
cancelScrollState();
return;
}
if (mInit == false) {
mInit = true;
int normalIndex = 0;
int selectIndex = mCurrentTab;
if (normalIndex == selectIndex)
normalIndex = 1;
mNormalColor = mTabSpecs.get(normalIndex).mIndicatorStrategy.getTextColor(mTabWidget.getChildTabViewAt(normalIndex));
mSelectedColor = mTabSpecs.get(selectIndex).mIndicatorStrategy.getTextColor(mTabWidget.getChildTabViewAt(selectIndex));
mTextColors = mTabSpecs.get(normalIndex).mIndicatorStrategy.getTextColors(mTabWidget.getChildTabViewAt(normalIndex));
}
float la = ((float) ((mSelectedColor >> 24) & 0xFF)) * (1 - positionOffset) + ((float) ((mNormalColor >> 24) & 0xFF)) * positionOffset;
float lr = ((float) ((mSelectedColor >> 16) & 0xFF)) * (1 - positionOffset) + ((float) ((mNormalColor >> 16) & 0xFF)) * positionOffset;
float lg = ((float) ((mSelectedColor >> 8) & 0xFF)) * (1 - positionOffset) + ((float) ((mNormalColor >> 8) & 0xFF)) * positionOffset;
float lb = ((float) ((mSelectedColor >> 0) & 0xFF)) * (1 - positionOffset) + ((float) ((mNormalColor >> 0) & 0xFF)) * positionOffset;
float ra = ((float) ((mSelectedColor >> 24) & 0xFF)) * positionOffset + ((float) ((mNormalColor >> 24) & 0xFF)) * (1 - positionOffset);
float rr = ((float) ((mSelectedColor >> 16) & 0xFF)) * positionOffset + ((float) ((mNormalColor >> 16) & 0xFF)) * (1 - positionOffset);
float rg = ((float) ((mSelectedColor >> 8) & 0xFF)) * positionOffset + ((float) ((mNormalColor >> 8) & 0xFF)) * (1 - positionOffset);
float rb = ((float) ((mSelectedColor >> 0) & 0xFF)) * positionOffset + ((float) ((mNormalColor >> 0) & 0xFF)) * (1 - positionOffset);
int leftColor = android.graphics.Color.argb((int) la, (int) lr, (int) lg, (int) lb);
int rightColor = android.graphics.Color.argb((int) ra, (int) rr, (int) rg, (int) rb);
mTabSpecs.get(position).mIndicatorStrategy.setTextColor(mTabWidget.getChildTabViewAt(position), leftColor);
mTabSpecs.get(position + 1).mIndicatorStrategy.setTextColor(mTabWidget.getChildTabViewAt(position + 1), rightColor);
}
public void onPageSelected(int position) {
if (mPagerListener != null) {
mPagerListener.onPageSelected(position);
}
setCurrentTab(position);
}
};
private void cancelScrollState() {
final int tabCount = mTabSpecs.size();
for (int i = 0; i < tabCount; i++) {
mTabSpecs.get(i).mIndicatorStrategy.setTextColors(mTabWidget.getChildTabViewAt(i), mTextColors);
}
}
// tws-end::support slide to switch tabs2013-05-06
private int mInitialTabIndex = 0;
//DM 固定逻辑 两个tab之间的间距固定16dp
boolean needMarginLeft = false;
private int mTabspecSpace = 0;
public TwsTabHost(Context context) {
super(context);
initTabHost();
}
public TwsTabHost(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabWidget, R.attr.tabWidgetStyle, 0);
mTabLayoutId = a.getResourceId(R.styleable.TabWidget_tabLayout, R.layout.tws_tab_indicator_holo);
a.recycle();
mTabspecSpace = getResources().getDimensionPixelSize(R.dimen.tws_tabspec_space);
initTabHost();
}
private void initTabHost() {
setFocusableInTouchMode(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
mCurrentTab = -1;
mCurrentView = null;
}
/**
* Get a new {@link TabSpec} associated with this tab host.
*
* @param tag
* required tag of tab.
*/
public TabSpec newTabSpec(String tag) {
return new TabSpec(tag, this);
}
/**
* <p>
* Call setup() before adding tabs if loading TabHost using findViewById().
* <i><b>However</i></b>: You do not need to call setup() after getTabHost()
* in {@link android.app.TabActivity TabActivity}. Example:
* </p>
*
* <pre>
* mTabHost = (TabHost) findViewById(R.id.tabhost);
* mTabHost.setup();
* mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
*/
public void setup() {
mTabWidget = (TwsTabWidget) findViewById(R.id.tabs);
if (mTabWidget == null) {
throw new RuntimeException("Your TabHost must have a TabWidget whose id attribute is 'R.id.tabs'");
}
// KeyListener to attach to all tabs. Detects non-navigation keys
// and relays them to the tab content.
mTabKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_ENTER:
return false;
}
mTabContent.requestFocus(View.FOCUS_FORWARD);
return mTabContent.dispatchKeyEvent(event);
}
};
mTabWidget.setTabSelectionListener(new TwsTabWidget.OnTabSelectionChanged() {
public void onTabSelectionChanged(int tabIndex, boolean clicked) {
setCurrentTab(tabIndex);
if (clicked) {
mTabContent.requestFocus(View.FOCUS_FORWARD);
}
}
});
mTabContent = (FrameLayout) findViewById(R.id.tabcontent);
if (mTabContent == null) {
throw new RuntimeException("Your TabHost must have a FrameLayout whose id attribute is " + "'R.id.tabcontent'");
}
// if FragmentManager is not passed in when setup, then not support
// slide tab switch
TwsLog.d(TAG, "mFragmentManager:"+mFragmentManager);
if (mFragmentManager != null) {
// R.id.tabviewpager is a ViewPager used for slide tab switch
mViewPager = (ViewPager) findViewById(R.id.tabviewpager);
if (mViewPager != null) {
mViewPagerAdapter = new ViewPagerAdapter();
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setOffscreenPageLimit(2);
// tws-start add tabIndicator::2014-9-23
mTabIndicator = (TabIndicator) findViewById(R.id.tab_indicator);
if (mTabIndicator != null) {
mTabIndicator.setViewPager(mViewPager);
mTabIndicator.setOnPageChangeListener(mViewPagerListener);
// 当前Tab是不等分居中的,这样indicator就需要知道tab的位置信息
mTabWidget.setOnTabItemCenterPosListener(mTabIndicator);
} else {
mViewPager.setOnPageChangeListener(mViewPagerListener);
}
// tws-end add tabIndicator::2014-9-23
} else {
Log.w(TAG, "cannot find a ViewPager named R.id.tabviewpager, " + "slide to switch tab will be N/A");
}
}
}
@Override
public void sendAccessibilityEvent(int eventType) {
/* avoid super class behavior - TabWidget sends the right events */
}
/**
* If you are using {@link TabSpec#setContent(android.content.Intent)}, this
* must be called since the activityGroup is needed to launch the local
* activity.
*
* This is done for you if you extend {@link android.app.TabActivity}.
*
* @param activityGroup
* Used to launch activities for tab content.
*/
// public void setup(LocalActivityManager activityGroup) {
// mLocalActivityManager = activityGroup;
// Activity curActivity = mLocalActivityManager.getCurrentActivity();
// setup(curActivity != null ? curActivity.getFragmentManager() : null);
// }
// if you want to enable slide tab switch, pass in a valid FragmentManager
public void setup(LocalActivityManager activityGroup, FragmentManager fragmentManager) {
setup(fragmentManager);
mLocalActivityManager = activityGroup;
}
// if you want to enable slide tab switch, pass in a valid FragmentManager
public void setup(FragmentManager fragmentManager) {
if (fragmentManager == null) {
Log.w(TAG, "fragment manager not provided, slide switch will be N/A");
} else {
mFragmentManager = fragmentManager;
}
setup();
}
// setup methods with initial index specified
public void setup(int initialTab) {
mInitialTabIndex = initialTab;
setup();
}
// public void setup(LocalActivityManager activityGroup, int initialTab) {
// mInitialTabIndex = initialTab;
// setup(activityGroup);
// }
public void setup(LocalActivityManager activityGroup, FragmentManager fragmentManager, int initialTab) {
mInitialTabIndex = initialTab;
setup(activityGroup, fragmentManager);
}
public void setup(FragmentManager fragmentManager, int initialTab) {
mInitialTabIndex = initialTab;
setup(fragmentManager);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
treeObserver.addOnTouchModeChangeListener(this);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
treeObserver.removeOnTouchModeChangeListener(this);
}
/**
* {@inheritDoc}
*/
public void onTouchModeChanged(boolean isInTouchMode) {
if (!isInTouchMode) {
// leaving touch mode.. if nothing has focus, let's give it to
// the indicator of the current tab
if (mCurrentView != null && (!mCurrentView.hasFocus() || mCurrentView.isFocused())) {
mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
}
}
}
/**
* Add a tab.
*
* @param tabSpec
* Specifies how to create the indicator and content.
*/
public void addTab(TabSpec tabSpec) {
if (tabSpec.mIndicatorStrategy == null) {
throw new IllegalArgumentException("you must specify a way to create the tab indicator.");
}
if (tabSpec.mContentStrategy == null) {
throw new IllegalArgumentException("you must specify a way to create the tab content");
}
View tabIndicator = tabSpec.mIndicatorStrategy.createIndicatorView();
tabIndicator.setOnKeyListener(mTabKeyListener);
// If this is a custom view, then do not draw the bottom strips for
// the tab indicators.
if (tabSpec.mIndicatorStrategy instanceof ViewIndicatorStrategy) {
mTabWidget.setStripEnabled(false);
}
// a bug in the original android source, the LinearLayout divider will
// offset right
// here set tab indicator's left margin to make up
if ((tabIndicator instanceof LinearLayout) && (mTabWidget.getShowDividers() & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabIndicator.getLayoutParams();
lp.leftMargin += mTabWidget.getDividerWidth();
if (needMarginLeft)
lp.leftMargin += mTabspecSpace;
tabIndicator.setLayoutParams(lp);
tabIndicator.requestLayout();
}
if (tabIndicator.getLayoutParams() != null) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabIndicator.getLayoutParams();
tabIndicator.setLayoutParams(lp);
tabIndicator.requestLayout();
} else {
mTabIndicator.setVisibility(View.GONE);
}
mTabWidget.addView(tabIndicator);
mTabSpecs.add(tabSpec);
needMarginLeft = true;
if (mCurrentTab == -1) {
if (mTabSpecs.size() > mInitialTabIndex) {
setCurrentTab(mInitialTabIndex);
}
}
}
/**
* Removes all tabs from the tab widget associated with this tab host.
*/
public void clearAllTabs() {
mTabWidget.removeAllViews();
needMarginLeft = false;
initTabHost();
mTabContent.removeAllViews();
mTabSpecs.clear();
requestLayout();
invalidate();
}
public TwsTabWidget getTabWidget() {
return mTabWidget;
}
public int getCurrentTab() {
return mCurrentTab;
}
public String getCurrentTabTag() {
if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
return mTabSpecs.get(mCurrentTab).getTag();
}
return null;
}
public View getCurrentTabView() {
if (mCurrentTab >= 0 && mCurrentTab < mTabSpecs.size()) {
return mTabWidget.getChildTabViewAt(mCurrentTab);
}
return null;
}
public View getCurrentView() {
return mCurrentView;
}
public void setCurrentTabByTag(String tag) {
int i;
for (i = 0; i < mTabSpecs.size(); i++) {
if (mTabSpecs.get(i).getTag().equals(tag)) {
setCurrentTab(i);
break;
}
}
}
/**
* Get the FrameLayout which holds tab content
*/
public FrameLayout getTabContentView() {
return mTabContent;
}
public ViewPager getViewPager() {
return mViewPager;
}
public TabIndicator getTabIndicator() {
return mTabIndicator;
}
/**
* get single tab content view by tag
*/
public View getTabContentViewByTag(String tag) {
for (int i = 0; i < mTabSpecs.size(); i++) {
if (mTabSpecs.get(i).getTag().equals(tag)) {
return mTabSpecs.get(i).mContentStrategy.getContentView();
}
}
return null;
}
/**
* get tab indicator view by tag
*/
public View getIndicatorViewByTag(String tag) {
for (int i = 0; i < mTabSpecs.size(); i++) {
if (mTabSpecs.get(i).getTag().equals(tag)) {
return mTabSpecs.get(i).mIndicatorStrategy.getIndicatorView();
}
}
return null;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final boolean handled = super.dispatchKeyEvent(event);
// unhandled key ups change focus to tab indicator for embedded
// activities
// when there is nothing that will take focus from default focus
// searching
if (!handled && (event.getAction() == KeyEvent.ACTION_DOWN) && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) && (mCurrentView != null) && (mCurrentView.isRootNamespace())
&& (mCurrentView.hasFocus()) && (mCurrentView.findFocus().focusSearch(View.FOCUS_UP) == null)) {
mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
return true;
}
return handled;
}
@Override
public void dispatchWindowFocusChanged(boolean hasFocus) {
if (mCurrentView != null) {
mCurrentView.dispatchWindowFocusChanged(hasFocus);
}
}
public void setCurrentTab(int index) {
if (index < 0 || index >= mTabSpecs.size()) {
return;
}
if (index == mCurrentTab) {
return;
}
switchToTab(index);
}
/**
* Register a callback to be invoked when the selected state of any of the
* items in this list changes
*
* @param l
* The callback that will run
*/
public void setOnTabChangedListener(OnTabChangeListener l) {
mOnTabChangeListener = l;
}
private void invokeOnTabChangeListener() {
if (mOnTabChangeListener != null) {
mOnTabChangeListener.onTabChanged(getCurrentTabTag());
}
}
/**
* Interface definition for a callback to be invoked when tab changed
*/
public interface OnTabChangeListener {
void onTabChanged(String tabId);
}
/**
* Makes the content of a tab when it is selected. Use this if your tab
* content needs to be created on demand, i.e. you are not showing an
* existing view or starting an activity.
*/
public interface TabContentFactory {
/**
* Callback to make the tab contents
*
* @param tag
* Which tab was selected.
* @return The view to display the contents of the selected tab.
*/
View createTabContent(String tag);
}
/**
* A tab has a tab indicator, content, and a tag that is used to keep track
* of it. This builder helps choose among these options.
*
* For the tab indicator, your choices are: 1) set a label 2) set a label
* and an icon
*
* For the tab content, your choices are: 1) the id of a {@link View} 2) a
* {@link TabContentFactory} that creates the {@link View} content. 3) an
* {@link Intent} that launches an {@link android.app.Activity}.
*/
public class TabSpec {
private String mTag;
private IndicatorStrategy mIndicatorStrategy;
private ContentStrategy mContentStrategy;
private TwsTabHost mTabHost;
private TabSpec(String tag, TwsTabHost tabHost) {
mTag = tag;
mTabHost = tabHost;
}
/**
* Specify a label as the tab indicator.
*/
public TabSpec setIndicator(CharSequence label) {
mIndicatorStrategy = new LabelIndicatorStrategy(label);
return this;
}
/**
* Specify a label and icon as the tab indicator.
*/
public TabSpec setIndicator(CharSequence label, Drawable icon) {
mIndicatorStrategy = new LabelAndIconIndicatorStrategy(label, icon);
return this;
}
/**
* Specify a view as the tab indicator.
*/
public TabSpec setIndicator(View view) {
mIndicatorStrategy = new ViewIndicatorStrategy(view);
return this;
}
/**
* Specify the id of the view that should be used as the content of the
* tab.
*/
public TabSpec setContent(int viewId) {
if (mFragmentManager == null) {
// traditional tab style
mContentStrategy = new ViewIdContentStrategy(viewId);
} else {
// tws tab style, with animation
mContentStrategy = new ViewIdContentStrategy2(viewId, mTag);
}
return this;
}
/**
* Specify a
* {@link com.tencent.tws.assistant.widget.TabHost.TabContentFactory} to
* use to create the content of the tab.
*/
public TabSpec setContent(TabContentFactory contentFactory) {
if (mFragmentManager == null) {
// traditional tab style
mContentStrategy = new FactoryContentStrategy(mTag, contentFactory);
} else {
// tws tab style, with animation
mContentStrategy = new FactoryContentStrategy2(mTag, contentFactory);
}
return this;
}
/**
* Specify an intent to use to launch an activity as the tab content.
*/
public TabSpec setContent(Intent intent) {
mContentStrategy = new IntentContentStrategy(mTag, intent);
return this;
}
// support user-defined fragment as content
public TabSpec setContent(Fragment fragment) {
mContentStrategy = new FragmentContentStrategy(fragment, mTag, mTabHost);
return this;
}
public String getTag() {
return mTag;
}
}
/**
* Specifies what you do to create a tab indicator.
*/
private static interface IndicatorStrategy {
/**
* Return the view for the indicator.
*/
View createIndicatorView();
// return the view of the indicator
View getIndicatorView();
// TODO: should add another interface
/**
* is support text fade animation?
*/
boolean supportTextFade();
int getTextColor(View view);
ColorStateList getTextColors(View view);
void setTextColor(View view, int color);
void setTextColors(View view, ColorStateList colors);
}
/**
* Specifies what you do to manage the tab content.
*/
private static interface ContentStrategy {
/**
* Return the content view. The view should may be cached locally.
*/
View getContentView();
/**
* Perhaps do something when the tab associated with this content has
* been closed (i.e make it invisible, or remove it).
*/
void tabClosed();
}
/**
* How to create a tab indicator that just has a label.
*/
private class LabelIndicatorStrategy implements IndicatorStrategy {
private final CharSequence mLabel;
private View mView;
private LabelIndicatorStrategy(CharSequence label) {
mLabel = label;
}
public View createIndicatorView() {
final Context context = getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View tabIndicator = inflater.inflate(mTabLayoutId, mTabWidget, false);
final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
tv.setText(mLabel);
mView = tabIndicator;
return tabIndicator;
}
public View getIndicatorView() {
return mView;
}
public boolean supportTextFade() {
return true;
}
public int getTextColor(View view) {
if (view == null)
return 0;
final TextView tv = (TextView) view.findViewById(R.id.title);
return tv.getCurrentTextColor();
}
public void setTextColor(View view, int color) {
if (view == null)
return;
final TextView tv = (TextView) view.findViewById(R.id.title);
tv.setTextColor(color);
}
public ColorStateList getTextColors(View view) {
if (view == null)
return null;
final TextView tv = (TextView) view.findViewById(R.id.title);
return tv.getTextColors();
}
public void setTextColors(View view, ColorStateList colors) {
if (view == null || colors == null)
return;
final TextView tv = (TextView) view.findViewById(R.id.title);
tv.setTextColor(colors);
}
}
/**
* How we create a tab indicator that has a label and an icon
*/
private class LabelAndIconIndicatorStrategy implements IndicatorStrategy {
private final CharSequence mLabel;
private final Drawable mIcon;
private View mView;
private LabelAndIconIndicatorStrategy(CharSequence label, Drawable icon) {
mLabel = label;
mIcon = icon;
}
public View createIndicatorView() {
final Context context = getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View tabIndicator = inflater.inflate(mTabLayoutId, mTabWidget, false);
final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
// when icon is gone by default, we're in exclusive mode
final boolean exclusive = iconView.getVisibility() == View.GONE;
final boolean bindIcon = !exclusive || TextUtils.isEmpty(mLabel);
tv.setText(mLabel);
if (bindIcon && mIcon != null) {
iconView.setImageDrawable(mIcon);
iconView.setVisibility(VISIBLE);
}
mView = tabIndicator;
return tabIndicator;
}
public View getIndicatorView() {
return mView;
}
public boolean supportTextFade() {
return false;
}
public int getTextColor(View view) {
return 0;
}
public void setTextColor(View view, int color) {
}
public ColorStateList getTextColors(View view) {
return null;
}
public void setTextColors(View view, ColorStateList colors) {
}
}
/**
* How to create a tab indicator by specifying a view.
*/
private class ViewIndicatorStrategy implements IndicatorStrategy {
private final View mView;
private ViewIndicatorStrategy(View view) {
mView = view;
}
public View createIndicatorView() {
return mView;
}
public View getIndicatorView() {
return mView;
}
public boolean supportTextFade() {
return false;
}
public int getTextColor(View view) {
return 0;
}
public void setTextColor(View view, int color) {
}
public ColorStateList getTextColors(View view) {
return null;
}
public void setTextColors(View view, ColorStateList colors) {
}
}
/**
* How to create the tab content via a view id.
*/
private class ViewIdContentStrategy implements ContentStrategy {
private final View mView;
private ViewIdContentStrategy(int viewId) {
mView = mTabContent.findViewById(viewId);
if (mView != null) {
mView.setVisibility(View.GONE);
} else {
throw new RuntimeException("Could not create tab content because " + "could not find view with id " + viewId);
}
}
public View getContentView() {
mView.setVisibility(View.VISIBLE);
return mView;
}
public void tabClosed() {
mView.setVisibility(View.GONE);
}
}
/**
* How tab content is managed using {@link TabContentFactory}.
*/
private class FactoryContentStrategy implements ContentStrategy {
private View mTabContent;
private final CharSequence mTag;
private TabContentFactory mFactory;
public FactoryContentStrategy(CharSequence tag, TabContentFactory factory) {
mTag = tag;
mFactory = factory;
}
public View getContentView() {
if (mTabContent == null) {
mTabContent = mFactory.createTabContent(mTag.toString());
}
mTabContent.setVisibility(View.VISIBLE);
return mTabContent;
}
public void tabClosed() {
mTabContent.setVisibility(View.GONE);
}
}
/**
* How tab content is managed via an {@link Intent}: the content view is the
* decorview of the launched activity.
*/
private class IntentContentStrategy implements ContentStrategy {
private final String mTag;
private final Intent mIntent;
private View mLaunchedView;
private IntentContentStrategy(String tag, Intent intent) {
mTag = tag;
mIntent = intent;
}
public View getContentView() {
if (mLocalActivityManager == null) {
throw new IllegalStateException("Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?");
}
final Window w = mLocalActivityManager.startActivity(mTag, mIntent);
final View wd = w != null ? w.getDecorView() : null;
if (mLaunchedView != wd && mLaunchedView != null) {
if (mLaunchedView.getParent() != null) {
mTabContent.removeView(mLaunchedView);
}
}
mLaunchedView = wd;
// XXX Set FOCUS_AFTER_DESCENDANTS on embedded activities for now so
// they can get
// focus if none of their children have it. They need focus to be
// able to
// display menu items.
//
// Replace this with something better when Bug 628886 is fixed...
//
if (mLaunchedView != null) {
mLaunchedView.setVisibility(View.VISIBLE);
mLaunchedView.setFocusableInTouchMode(true);
((ViewGroup) mLaunchedView).setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
}
return mLaunchedView;
}
public void tabClosed() {
if (mLaunchedView != null) {
mLaunchedView.setVisibility(View.GONE);
}
}
}
/**
* tws view id content strategy, the view specified by id will be combined
* with fragment thus can be added to a ViewPager and be switched by sliding
*/
private class ViewIdContentStrategy2 extends Fragment implements ContentStrategy {
private final View mView;
private Fragment mFragment;
private ViewIdContentStrategy2(int viewId, String tag) {
mView = mTabContent.findViewById(viewId);
if (mView != null) {
// in case use viewpager to switch view, remove it from
// tabcontent first
// because a view cannot be placed in more than 1 parent view
((ViewGroup) mView.getParent()).removeView(mView);
mFragment = new Fragment() {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return mView;
}
};
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.add(R.id.tabviewpager, mFragment, tag);
// transaction.hide(mFragment);
transaction.commit();
// mFragmentManager.executePendingTransactions();
} else {
throw new RuntimeException("Could not create tab content because " + "could not find view with id 0x" + Integer.toHexString(viewId));
}
}
public View getContentView() {
return mView;
}
public void tabClosed() {
// do nothing
}
}
/**
* fragment content strategy, tab users can directly set fragment as tab
* content
*/
private class FragmentContentStrategy implements ContentStrategy {
private Fragment mFragment;
private FragmentContentStrategy(Fragment fragment, String tag, TwsTabHost tabHost) {
mFragment = fragment;
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.add(R.id.tabviewpager, fragment, tag);
// transaction.hide(fragment);
transaction.commit();
// mFragmentManager.executePendingTransactions();
}
public View getContentView() {
return mFragment.getView();
}
public void tabClosed() {
// do nothing
}
}
/**
* tws factory content strategy, the content view created by caller will be
* combined with a fragment
*/
private class FactoryContentStrategy2 implements ContentStrategy {
private View mTabContent;
private String mTag;
private TabContentFactory mFactory;
private TwsFactoryContentStrategy2FragmentV4 mFragment;
public FactoryContentStrategy2(String tag, TabContentFactory factory) {
mTag = tag;
mFactory = factory;
mTabContent = mFactory.createTabContent(mTag);
// tws-start modify fragment not an empty
// constructor::2014-12-19
mFragment = new TwsFactoryContentStrategy2FragmentV4(mTabContent);
// tws-end modify fragment not an empty
// constructor::2014-12-19
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.add(R.id.tabviewpager, mFragment, tag);
// transaction.hide(mFragment);
transaction.commit();
// mFragmentManager.executePendingTransactions();
}
public View getContentView() {
return mTabContent;
}
public void tabClosed() {
// do nothing
}
}
/**
* show the tab indicator animcation
*/
void switchToTab(int index) {
// notify old tab content
if (mCurrentTab != -1) {
mTabSpecs.get(mCurrentTab).mContentStrategy.tabClosed();
}
mCurrentTab = index;
final TwsTabHost.TabSpec spec = mTabSpecs.get(index);
// Call the tab widget's focusCurrentTab(), instead of just
// selecting the tab.
mTabWidget.focusCurrentTab(index);
if (mFragmentManager == null) {
// no fragment manager specified, do traditional tab content switch
// tab content
mCurrentView = spec.mContentStrategy.getContentView();
if (mCurrentView.getParent() == null) {
mTabContent.addView(mCurrentView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
if (!mTabWidget.hasFocus()) {
// if the tab widget didn't take focus (likely because we're in
// touch mode)
// give the current tab content view a shot
mCurrentView.requestFocus();
}
} else {
// show target tab content via ViewPager
mViewPager.setCurrentItem(index);
}
// mTabContent.requestFocus(View.FOCUS_FORWARD);
invokeOnTabChangeListener();
}
/**
* Adapter for ViewPager, implements only necessary abstract methods
*/
private class ViewPagerAdapter extends PagerAdapter {
private FragmentTransaction mCurTransaction;
public ViewPagerAdapter() {
}
@Override
public void destroyItem(View container, int position, Object object) {
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
mCurTransaction.detach((Fragment) object);
}
@Override
public void finishUpdate(View container) {
}
public void finishUpdate(ViewGroup container) {
}
@Override
public Object instantiateItem(View container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = mFragmentManager.findFragmentByTag(mTabSpecs.get(position).getTag());
if (fragment != null) {
mCurTransaction.attach(fragment);
}
return fragment;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((Fragment) object).getView();
}
@Override
public int getCount() {
return mTabSpecs.size();
}
}
/**
* get ViewPager callback
*
* @param ViewPager
* .OnPageChangeListener
*/
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mPagerListener = listener;
}
}