package kr.kdev.dg1s.biowiki.ui; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Paint; import android.graphics.Typeface; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; import java.util.ArrayList; import kr.kdev.dg1s.biowiki.R; import kr.kdev.dg1s.biowiki.util.Utils; /** * A view that mimics the action bar tabs. It can be placed anywhere and appears * under the sliding menu, unlike the action bar tabs */ public class HorizontalTabView extends HorizontalScrollView implements OnClickListener { private static final String TAG_PREFIX = "tab:"; private ArrayList<Tab> mTabs; private ArrayList<TextView> mTextViews; private LinearLayout mTabContainer; private float mMaxTabWidth = 0f; private TabListener mTabListener; private boolean mEnableScroll = true; private LinearLayout mSelectedLayout; public HorizontalTabView(Context context) { super(context); init(); } public HorizontalTabView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public HorizontalTabView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { mTabs = new ArrayList<Tab>(); mTextViews = new ArrayList<TextView>(); setupBackground(); setupTabContainer(); } private void setupBackground() { setBackgroundColor(getResources().getColor(R.color.tab_background)); } private void setupTabContainer() { mTabContainer = new LinearLayout(getContext()); HorizontalScrollView.LayoutParams linearLayoutParams = new HorizontalScrollView.LayoutParams(HorizontalScrollView.LayoutParams.WRAP_CONTENT, HorizontalScrollView.LayoutParams.WRAP_CONTENT); mTabContainer.setLayoutParams(linearLayoutParams); mTabContainer.setOrientation(LinearLayout.HORIZONTAL); addView(mTabContainer); } public Tab newTab() { return new Tab(); } public void addTab(Tab tab) { tab.setPosition(mTabs.size()); mTabs.add(tab); int divWidth = (int) Utils.dpToPx(1); int divTopMargin = (int) Utils.dpToPx(12); int divHeight = (int) Utils.dpToPx(24); int tabPad = (int) Utils.dpToPx(16); int fontSizeSp = 12; // add dividers in the middle - not using divider property as it is API 11 if (mTextViews.size() > 0) { View divider = new View(getContext()); LinearLayout.LayoutParams separatorParams = new LinearLayout.LayoutParams(divWidth, divHeight); separatorParams.topMargin = divTopMargin; divider.setLayoutParams(separatorParams); divider.setBackgroundColor(getResources().getColor(R.color.tab_divider)); mTabContainer.addView(divider); } TextView textView = new TextView(getContext()); LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); textView.setLayoutParams(textViewParams); textView.setGravity(Gravity.CENTER); textView.setText(tab.getText()); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, fontSizeSp); textView.setTextColor(getResources().getColor(R.color.tab_text)); textView.setTypeface(null, Typeface.BOLD); mTextViews.add(textView); LinearLayout linearLayout = new LinearLayout(getContext()); LinearLayout.LayoutParams linearLayoutParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1); linearLayout.setLayoutParams(linearLayoutParams); linearLayout.addView(textView); linearLayout.setTag(TAG_PREFIX + (mTabs.size() - 1)); linearLayout.setOnClickListener(this); linearLayout.setBackgroundResource(R.drawable.tab_indicator_ab_wordpress); linearLayout.setPadding(tabPad, tabPad, tabPad, tabPad); mTabContainer.addView(linearLayout); recomputeTabWidths(); } /** * Make the tabs have the same widths, where this width is based on the longest tab title * */ private void recomputeTabWidths() { // Determine the max width for (TextView textView : mTextViews) { Paint paint = textView.getPaint(); float width = paint.measureText(textView.getText().toString()); if (mMaxTabWidth < width) mMaxTabWidth = width; } // Set the tabs to use the max width for (TextView textView : mTextViews) { LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams((int) mMaxTabWidth, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER); textView.setLayoutParams(textViewParams); } } public TabListener getTabListener() { return mTabListener; } public void setTabListener(TabListener tabListener) { this.mTabListener = tabListener; } @Override public void onClick(View v) { if (v instanceof LinearLayout) { LinearLayout layout = (LinearLayout) v; String tag = (String) layout.getTag(); int position = Integer.valueOf(tag.substring(TAG_PREFIX.length())); // It is necessary to disable scrolling upon click before informing the listener // because I've found that if setSelectedTab() was called in the listener implementation, // and that setSelectedTab() is called again after onTabSelected(), it does not smooth scroll. // The call to setSelectedTab() in this method is necessary because if there was no listener or if // it did not call setSelectedTab(), then it would appear as if nothing happened. mEnableScroll = false; if (mTabListener != null) mTabListener.onTabSelected(mTabs.get(position)); mEnableScroll = true; setSelectedTab(position); } } public void setSelectedTab(int position) { if (position >= mTextViews.size()) return; if (mEnableScroll) { scrollToTab(position); setSelectedLayout(getTabParent(position)); } } public void setTabText(int position, String text) { mTabs.get(position).mText = text; mTextViews.get(position).setText(text); } private void scrollToTab(int position) { int tabWidth = getTabParent(position).getWidth(); int parentWidth = ((View) this.getParent()).getWidth(); int offset = parentWidth / 2 - tabWidth / 2; smoothScrollTo(tabWidth * position - offset, 0); } private LinearLayout getTabParent(int position) { View tab = mTextViews.get(position); return (LinearLayout) tab.getParent(); } private void setSelectedLayout(LinearLayout layout) { if (mSelectedLayout != null) { mSelectedLayout.setSelected(false); } mSelectedLayout = (LinearLayout) layout; mSelectedLayout.setSelected(true); } public interface TabListener { public void onTabSelected(Tab tab); } public class Tab { private String mText; private int mPosition; @SuppressLint("DefaultLocale") public CharSequence getText() { return mText.toUpperCase(); } public Tab setText(CharSequence pageTitle) { mText = pageTitle.toString(); return this; } public int getPosition() { return mPosition; } public void setPosition(int position) { this.mPosition = position; } } }