Back to project page UsarActionBarSherlockAndroidStudio.
The source code is released under:
GNU General Public License
If you think the Android project UsarActionBarSherlockAndroidStudio listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2011 The Android Open Source Project *//from w w w . j a va 2 s.com * 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 com.actionbarsherlock.internal.widget; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.text.TextUtils.TruncateAt; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import com.actionbarsherlock.R; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; import com.actionbarsherlock.internal.nineoldandroids.widget.NineHorizontalScrollView; /** * This widget implements the dynamic action bar tab behavior that can change * across different configurations or circumstances. */ public class ScrollingTabContainerView extends NineHorizontalScrollView implements IcsAdapterView.OnItemSelectedListener { //UNUSED private static final String TAG = "ScrollingTabContainerView"; Runnable mTabSelector; private TabClickListener mTabClickListener; private IcsLinearLayout mTabLayout; private IcsSpinner mTabSpinner; private boolean mAllowCollapse; private LayoutInflater mInflater; int mMaxTabWidth; private int mContentHeight; private int mSelectedTabIndex; protected Animator mVisibilityAnim; protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator(); private static final int FADE_DURATION = 200; public ScrollingTabContainerView(Context context) { super(context); setHorizontalScrollBarEnabled(false); TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, R.attr.actionBarStyle, 0); setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); a.recycle(); mInflater = LayoutInflater.from(context); mTabLayout = createTabLayout(); addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; setFillViewport(lockedExpanded); final int childCount = mTabLayout.getChildCount(); if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { if (childCount > 2) { mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); } else { mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; } } else { mMaxTabWidth = -1; } heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY); final boolean canCollapse = !lockedExpanded && mAllowCollapse; if (canCollapse) { // See if we should expand mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec); if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) { performCollapse(); } else { performExpand(); } } else { performExpand(); } final int oldWidth = getMeasuredWidth(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int newWidth = getMeasuredWidth(); if (lockedExpanded && oldWidth != newWidth) { // Recenter the tab display if we're at a new (scrollable) size. setTabSelected(mSelectedTabIndex); } } /** * Indicates whether this view is collapsed into a dropdown menu instead * of traditional tabs. * @return true if showing as a spinner */ private boolean isCollapsed() { return mTabSpinner != null && mTabSpinner.getParent() == this; } public void setAllowCollapse(boolean allowCollapse) { mAllowCollapse = allowCollapse; } private void performCollapse() { if (isCollapsed()) return; if (mTabSpinner == null) { mTabSpinner = createSpinner(); } removeView(mTabLayout); addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); if (mTabSpinner.getAdapter() == null) { mTabSpinner.setAdapter(new TabAdapter()); } if (mTabSelector != null) { removeCallbacks(mTabSelector); mTabSelector = null; } mTabSpinner.setSelection(mSelectedTabIndex); } private boolean performExpand() { if (!isCollapsed()) return false; removeView(mTabSpinner); addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); setTabSelected(mTabSpinner.getSelectedItemPosition()); return false; } public void setTabSelected(int position) { mSelectedTabIndex = position; final int tabCount = mTabLayout.getChildCount(); for (int i = 0; i < tabCount; i++) { final View child = mTabLayout.getChildAt(i); final boolean isSelected = i == position; child.setSelected(isSelected); if (isSelected) { animateToTab(position); } } } public void setContentHeight(int contentHeight) { mContentHeight = contentHeight; requestLayout(); } private IcsLinearLayout createTabLayout() { final TabsLinearLayout tabLayout = (TabsLinearLayout) LayoutInflater.from(getContext()) .inflate(R.layout.abs__action_bar_tab_bar_view, null); tabLayout.setMeasureWithLargestChildEnabled(true); tabLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); return tabLayout; } private IcsSpinner createSpinner() { final IcsSpinner spinner = new IcsSpinner(getContext(), null, R.attr.actionDropDownStyle); spinner.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); spinner.setOnItemSelectedListener(this); return spinner; } @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Action bar can change size on configuration changes. // Reread the desired height from the theme-specified style. TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, R.attr.actionBarStyle, 0); setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); a.recycle(); } public void animateToVisibility(int visibility) { if (mVisibilityAnim != null) { mVisibilityAnim.cancel(); } if (visibility == VISIBLE) { if (getVisibility() != VISIBLE) { setAlpha(0); } ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); anim.setDuration(FADE_DURATION); anim.setInterpolator(sAlphaInterpolator); anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); anim.start(); } else { ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); anim.setDuration(FADE_DURATION); anim.setInterpolator(sAlphaInterpolator); anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); anim.start(); } } public void animateToTab(final int position) { final View tabView = mTabLayout.getChildAt(position); if (mTabSelector != null) { removeCallbacks(mTabSelector); } mTabSelector = new Runnable() { public void run() { final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; smoothScrollTo(scrollPos, 0); mTabSelector = null; } }; post(mTabSelector); } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); if (mTabSelector != null) { // Re-post the selector we saved post(mTabSelector); } } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mTabSelector != null) { removeCallbacks(mTabSelector); } } private TabView createTabView(ActionBar.Tab tab, boolean forAdapter) { //Workaround for not being able to pass a defStyle on pre-3.0 final TabView tabView = (TabView)mInflater.inflate(R.layout.abs__action_bar_tab, null); tabView.init(this, tab, forAdapter); if (forAdapter) { tabView.setBackgroundDrawable(null); tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, mContentHeight)); } else { tabView.setFocusable(true); if (mTabClickListener == null) { mTabClickListener = new TabClickListener(); } tabView.setOnClickListener(mTabClickListener); } return tabView; } public void addTab(ActionBar.Tab tab, boolean setSelected) { TabView tabView = createTabView(tab, false); mTabLayout.addView(tabView, new IcsLinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1)); if (mTabSpinner != null) { ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); } if (setSelected) { tabView.setSelected(true); } if (mAllowCollapse) { requestLayout(); } } public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { final TabView tabView = createTabView(tab, false); mTabLayout.addView(tabView, position, new IcsLinearLayout.LayoutParams( 0, LayoutParams.MATCH_PARENT, 1)); if (mTabSpinner != null) { ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); } if (setSelected) { tabView.setSelected(true); } if (mAllowCollapse) { requestLayout(); } } public void updateTab(int position) { ((TabView) mTabLayout.getChildAt(position)).update(); if (mTabSpinner != null) { ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); } if (mAllowCollapse) { requestLayout(); } } public void removeTabAt(int position) { mTabLayout.removeViewAt(position); if (mTabSpinner != null) { ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); } if (mAllowCollapse) { requestLayout(); } } public void removeAllTabs() { mTabLayout.removeAllViews(); if (mTabSpinner != null) { ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); } if (mAllowCollapse) { requestLayout(); } } @Override public void onItemSelected(IcsAdapterView<?> parent, View view, int position, long id) { TabView tabView = (TabView) view; tabView.getTab().select(); } @Override public void onNothingSelected(IcsAdapterView<?> parent) { } public static class TabView extends LinearLayout { private ScrollingTabContainerView mParent; private ActionBar.Tab mTab; private CapitalizingTextView mTextView; private ImageView mIconView; private View mCustomView; public TabView(Context context, AttributeSet attrs) { //TODO super(context, null, R.attr.actionBarTabStyle); super(context, attrs); } public void init(ScrollingTabContainerView parent, ActionBar.Tab tab, boolean forList) { mParent = parent; mTab = tab; if (forList) { setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); } update(); } public void bindTab(ActionBar.Tab tab) { mTab = tab; update(); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // Re-measure if we went beyond our maximum size. if (mParent.mMaxTabWidth > 0 && getMeasuredWidth() > mParent.mMaxTabWidth) { super.onMeasure(MeasureSpec.makeMeasureSpec(mParent.mMaxTabWidth, MeasureSpec.EXACTLY), heightMeasureSpec); } } public void update() { final ActionBar.Tab tab = mTab; final View custom = tab.getCustomView(); if (custom != null) { final ViewParent customParent = custom.getParent(); if (customParent != this) { if (customParent != null) ((ViewGroup) customParent).removeView(custom); addView(custom); } mCustomView = custom; if (mTextView != null) mTextView.setVisibility(GONE); if (mIconView != null) { mIconView.setVisibility(GONE); mIconView.setImageDrawable(null); } } else { if (mCustomView != null) { removeView(mCustomView); mCustomView = null; } final Drawable icon = tab.getIcon(); final CharSequence text = tab.getText(); if (icon != null) { if (mIconView == null) { ImageView iconView = new ImageView(getContext()); LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); lp.gravity = Gravity.CENTER_VERTICAL; iconView.setLayoutParams(lp); addView(iconView, 0); mIconView = iconView; } mIconView.setImageDrawable(icon); mIconView.setVisibility(VISIBLE); } else if (mIconView != null) { mIconView.setVisibility(GONE); mIconView.setImageDrawable(null); } if (text != null) { if (mTextView == null) { CapitalizingTextView textView = new CapitalizingTextView(getContext(), null, R.attr.actionBarTabTextStyle); textView.setEllipsize(TruncateAt.END); LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); lp.gravity = Gravity.CENTER_VERTICAL; textView.setLayoutParams(lp); addView(textView); mTextView = textView; } mTextView.setTextCompat(text); mTextView.setVisibility(VISIBLE); } else if (mTextView != null) { mTextView.setVisibility(GONE); mTextView.setText(null); } if (mIconView != null) { mIconView.setContentDescription(tab.getContentDescription()); } } } public ActionBar.Tab getTab() { return mTab; } } private class TabAdapter extends BaseAdapter { @Override public int getCount() { return mTabLayout.getChildCount(); } @Override public Object getItem(int position) { return ((TabView) mTabLayout.getChildAt(position)).getTab(); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = createTabView((ActionBar.Tab) getItem(position), true); } else { ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position)); } return convertView; } } private class TabClickListener implements OnClickListener { public void onClick(View view) { TabView tabView = (TabView) view; tabView.getTab().select(); final int tabCount = mTabLayout.getChildCount(); for (int i = 0; i < tabCount; i++) { final View child = mTabLayout.getChildAt(i); child.setSelected(child == view); } } } protected class VisibilityAnimListener implements Animator.AnimatorListener { private boolean mCanceled = false; private int mFinalVisibility; public VisibilityAnimListener withFinalVisibility(int visibility) { mFinalVisibility = visibility; return this; } @Override public void onAnimationStart(Animator animation) { setVisibility(VISIBLE); mVisibilityAnim = animation; mCanceled = false; } @Override public void onAnimationEnd(Animator animation) { if (mCanceled) return; mVisibilityAnim = null; setVisibility(mFinalVisibility); } @Override public void onAnimationCancel(Animator animation) { mCanceled = true; } @Override public void onAnimationRepeat(Animator animation) { } } }