Java tutorial
/* * Copyright (C) 2013 Peng fei Pan <sky@xiaopan.me> * * 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.android.yijiang.kzx.widget.tab; import java.util.List; import com.android.yijiang.kzx.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; /** * ViewPager? * @version 1.1.1 */ public class PagerSlidingTabStrip extends HorizontalScrollView implements View.OnClickListener { private int currentPosition; //?? private int lastOffset; private int lastScrollX = 0; private float currentPositionOffset; //????? private boolean start; private boolean allowWidthFull; // ?Item private View currentSelectedTabView; //? private Drawable slidingBlockDrawable; //? private ViewPager viewPager; //ViewPager private ViewGroup tabsLayout; // private ViewPager.OnPageChangeListener onPageChangeListener; //??? private OnClickTabListener onClickTabListener; public PagerSlidingTabStrip(Context context) { this(context, null); } public PagerSlidingTabStrip(Context context, AttributeSet attrs) { super(context, attrs); setHorizontalScrollBarEnabled(false); //?????? if (attrs != null) { TypedArray attrsTypedArray = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip); if (attrsTypedArray != null) { allowWidthFull = attrsTypedArray.getBoolean(R.styleable.PagerSlidingTabStrip_allowWidthFull, false); slidingBlockDrawable = attrsTypedArray.getDrawable(R.styleable.PagerSlidingTabStrip_slidingBlock); attrsTypedArray.recycle(); } } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { ViewGroup tabViewGroup = getTabsLayout(); // if (tabViewGroup == null || tabViewGroup.getChildCount() <= 0) { super.onLayout(changed, l, t, r, b); return; } int viewWidth = r - l; // Item if ((measure(tabViewGroup).getMeasuredWidth() < viewWidth) && allowWidthFull) { // ?tabViewGroup?? viewWidth -= tabViewGroup.getPaddingLeft(); viewWidth -= tabViewGroup.getPaddingRight(); if (tabViewGroup.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams tabsLayoutParams = (MarginLayoutParams) tabViewGroup.getLayoutParams(); viewWidth -= tabsLayoutParams.leftMargin; viewWidth -= tabsLayoutParams.rightMargin; } // ??Tab? View tabView; for (int w = 0; w < tabViewGroup.getChildCount(); w++) { tabView = tabViewGroup.getChildAt(w); if (tabView.getLayoutParams() instanceof MarginLayoutParams) { MarginLayoutParams marginLayoutParams = (MarginLayoutParams) tabView.getLayoutParams(); viewWidth -= marginLayoutParams.leftMargin; viewWidth -= marginLayoutParams.rightMargin; } } // ? int averageWidth = viewWidth / tabViewGroup.getChildCount(); int bigTabCount = 0; // ?tab??? for (int w = 0; w < tabViewGroup.getChildCount(); w++) { tabView = tabViewGroup.getChildAt(w); // ???? if (tabView != null && tabView.getMeasuredWidth() > averageWidth) { viewWidth -= tabView.getMeasuredWidth(); bigTabCount++; } } // ? averageWidth = viewWidth / (tabViewGroup.getChildCount() - bigTabCount); // ??Item for (int w = 0; w < tabViewGroup.getChildCount(); w++) { //????? tabView = tabViewGroup.getChildAt(w); if (tabView != null) { ViewGroup.LayoutParams layoutParams = tabView.getLayoutParams(); if (layoutParams != null) { layoutParams.width = tabView.getMeasuredWidth() < averageWidth ? averageWidth : tabView.getMeasuredWidth(); tabView.setLayoutParams(layoutParams); measure(tabView); } } } measure(tabViewGroup); } // ????? currentPosition = viewPager != null ? viewPager.getCurrentItem() : 0; scrollToChild(currentPosition, 0); //?? selectedTab(currentPosition); //?TAB //?tab?Pager for (int w = 0; w < tabViewGroup.getChildCount(); w++) { View itemView = tabViewGroup.getChildAt(w); itemView.setTag(w); itemView.setOnClickListener(this); } super.onLayout(changed, l, t, r, b); } @Override public void onClick(View v) { int index = (Integer) v.getTag(); if (onClickTabListener != null) { onClickTabListener.onClickTab(v, index); } if (viewPager != null) { viewPager.setCurrentItem(index, true); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /* ? */ if (getTabsLayout() != null && getTabsLayout().getChildCount() > 0 && slidingBlockDrawable != null) { View currentTab = getTabsLayout().getChildAt(currentPosition); if (currentTab != null) { float slidingBlockLeft = currentTab.getLeft(); float slidingBlockRight = currentTab.getRight(); if (currentPositionOffset > 0f && currentPosition < getTabsLayout().getChildCount() - 1) { View nextTab = getTabsLayout().getChildAt(currentPosition + 1); if (nextTab != null) { final float nextTabLeft = nextTab.getLeft(); final float nextTabRight = nextTab.getRight(); slidingBlockLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * slidingBlockLeft); slidingBlockRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * slidingBlockRight); } } slidingBlockDrawable.setBounds((int) slidingBlockLeft, 0, (int) slidingBlockRight, getHeight()); slidingBlockDrawable.draw(canvas); } } } /** * ? */ private ViewGroup getTabsLayout() { if (tabsLayout == null) { if (getChildCount() > 0) { tabsLayout = (ViewGroup) getChildAt(0); } else { removeAllViews(); tabsLayout = new LinearLayout(getContext()); addView(tabsLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } } return tabsLayout; } /** * ? */ private void scrollToChild(int position, int offset) { if (getTabsLayout() != null && getTabsLayout().getChildCount() > 0 && position < getTabsLayout().getChildCount()) { View view = getTabsLayout().getChildAt(position); if (view != null) { //X?? int newScrollX = view.getLeft() + offset; if (position > 0 || offset > 0) { newScrollX -= 240 - getOffset(view.getWidth()) / 2; } //?X??? if (newScrollX != lastScrollX) { lastScrollX = newScrollX; scrollTo(newScrollX, 0); } } } } /** * ???? */ private int getOffset(int newOffset) { if (lastOffset < newOffset) { if (start) { lastOffset += 1; return lastOffset; } else { start = true; lastOffset += 1; return lastOffset; } } if (lastOffset > newOffset) { if (start) { lastOffset -= 1; return lastOffset; } else { start = true; lastOffset -= 1; return lastOffset; } } else { start = true; lastOffset = newOffset; return lastOffset; } } /** * ????ViewgetMeasuredXXX()???? */ private View measure(View view) { ViewGroup.LayoutParams p = view.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width); int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } view.measure(childWidthSpec, childHeightSpec); return view; } /** * ?TAB */ private void selectedTab(int currentSelectedTabPosition) { if (currentSelectedTabPosition > -1 && getTabsLayout() != null && currentSelectedTabPosition < getTabsLayout().getChildCount()) { if (currentSelectedTabView != null) { currentSelectedTabView.setSelected(false); } currentSelectedTabView = getTabsLayout().getChildAt(currentSelectedTabPosition); if (currentSelectedTabView != null) { currentSelectedTabView.setSelected(true); } } } /** * Tab */ public void addTab(View tabView, int index) { if (tabView != null) { getTabsLayout().addView(tabView, index); requestLayout(); } } /** * Tab */ public void addTab(View tabView) { addTab(tabView, -1); } /** * Tab * @param tabViews ?Tab */ public void addTab(View... tabViews) { if (tabViews != null && getTabsLayout() != null) { for (View view : tabViews) { getTabsLayout().addView(view); } requestLayout(); } } /** * Tab */ public void addTab(List<View> tabViews) { if (tabViews != null && tabViews.size() > 0 && getTabsLayout() != null) { for (View view : tabViews) { getTabsLayout().addView(view); } requestLayout(); } } /** * ViewPager * @param viewPager ViewPager */ public void setViewPager(ViewPager viewPager) { this.viewPager = viewPager; this.viewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { selectedTab(position); if (onPageChangeListener != null) { onPageChangeListener.onPageSelected(position); } } @Override public void onPageScrolled(int nextPagePosition, float positionOffset, int positionOffsetPixels) { if (nextPagePosition < getTabsLayout().getChildCount()) { View view = getTabsLayout().getChildAt(nextPagePosition); if (view != null) { currentPosition = nextPagePosition; currentPositionOffset = positionOffset; scrollToChild(nextPagePosition, (int) (positionOffset * view.getWidth())); invalidate(); if (onPageChangeListener != null) { onPageChangeListener.onPageScrolled(nextPagePosition, positionOffset, positionOffsetPixels); } } } } @Override public void onPageScrollStateChanged(int arg0) { if (onPageChangeListener != null) { onPageChangeListener.onPageScrollStateChanged(arg0); } } }); requestLayout(); } /** * Page?? * @param onPageChangeListener Page?? */ public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) { this.onPageChangeListener = onPageChangeListener; } /** * ?? * @param allowWidthFull true??Item? */ public void setAllowWidthFull(boolean allowWidthFull) { this.allowWidthFull = allowWidthFull; requestLayout(); } /** * ? */ public void setSlidingBlockDrawable(Drawable slidingBlockDrawable) { this.slidingBlockDrawable = slidingBlockDrawable; requestLayout(); } /** * ?Tab */ public int getTabCount() { return getTabsLayout() != null ? getTabsLayout().getChildCount() : 0; } /** * Tab? * @param onClickTabListener */ public void setOnClickTabListener(OnClickTabListener onClickTabListener) { this.onClickTabListener = onClickTabListener; } /** * Tab? * @author xiaopan * */ public interface OnClickTabListener { public void onClickTab(View tab, int index); } }