关于定制的viewpagerindicator,实现特殊效果

来源:互联网 发布:御马脚垫 知乎 编辑:程序博客网 时间:2024/05/20 11:25

最近收到一个任务,要仿照winPhone的样式(可以滑动时切换fragment)



说可以用viewPagerIndicator,于是我就去查了下viewPagerIndicator,发现是这样的:



这个好像离要求还挺远的,首先是界面只要求显示两个tab,一个在左一个在右,还要能循环滑动。

看了一下ViewPagerIndicator的源码,发现它的封装还是不够好,想要个性定制(就像我上面的要求它是没办法通过设置属性就修改的)还是挺困难的,而且我也没找到相应的方法去修改tab的宽度,折腾了半天后还是放弃了,只能拷贝它的源码再进行个性化修改啦。

我主要修改的是这个源码:/ViewPagerIndicator_library/src/com/viewpagerindicator/TabPageIndicator.java

为了不让tab栏能够左右滑动,在代码中添加:

@Overridepublic boolean onTouchEvent(MotionEvent ev) {// return super.onTouchEvent(ev);return false;// 使得在导航栏的手指滑动无效}


设置屏幕的宽度width,方便后面修改tab的宽度:
public CustomTabPageIndicator(Context context, AttributeSet attrs) {super(context, attrs);DisplayMetrics metric = new DisplayMetrics();((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metric);width = metric.widthPixels;// mScreenHeight = metric.heightPixels;setHorizontalScrollBarEnabled(false);mTabLayout = new IcsLinearLayout(context,R.attr.vpiTabPageIndicatorStyle);addView(mTabLayout, new ViewGroup.LayoutParams(WRAP_CONTENT,MATCH_PARENT));}


在这个方法中修改第一个if判断,使得每个tab的最大宽度为屏幕的一半:

@Overridepublic 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)) {mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;} else {mMaxTabWidth = -1;}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.setCurrentItem(mSelectedTabIndex);}}


在这个方法中修改scrollPos的值,使得每次都滑动一个TabView的宽度:
private 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();//每次都滑动一个TabView的宽度smoothScrollTo(scrollPos, 0);mTabSelector = null;}};post(mTabSelector);}


还要修改LayoutParams,使得tab的宽度就是屏幕宽度的一半:

private void addTab(int index, CharSequence text, int iconResId) {final TabView tabView = new TabView(getContext());tabView.mIndex = index;tabView.setFocusable(true);tabView.setOnClickListener(mTabClickListener);tabView.setText(text);tabView.setTextColor(Color.WHITE);tabView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 35);if (iconResId != 0) {tabView.setCompoundDrawablesWithIntrinsicBounds(iconResId, 0, 0, 0);}Log.e("mwidth=", "" + width);// 设置宽度,使得只显示两个tabviewmTabLayout.addView(tabView, new LinearLayout.LayoutParams(width / 2,MATCH_PARENT, 1));}


为了实现循环滑动,这里的for循环将count+1就行了:

public void notifyDataSetChanged() {mTabLayout.removeAllViews();PagerAdapter adapter = mViewPager.getAdapter();IconPagerAdapter iconAdapter = null;if (adapter instanceof IconPagerAdapter) {iconAdapter = (IconPagerAdapter) adapter;}final int count = adapter.getCount();for (int i = 0; i < count + 1; i++) {CharSequence title = adapter.getPageTitle(i);if (title == null) {title = EMPTY_TITLE;}int iconResId = 0;if (iconAdapter != null) {iconResId = iconAdapter.getIconResId(i);}addTab(i, title, iconResId);}if (mSelectedTabIndex > count) {mSelectedTabIndex = count - 1;}setCurrentItem(mSelectedTabIndex);requestLayout();}


最后如果要实现右边的tab显示预览字和灰体时可以在这里修改,方法就是从mTabLayout里得到当前的tab(即左边的tab)和下一个tab(右边的tab)然后修改相关属性值:

@Overridepublic void onPageSelected(int arg0) {setCurrentItem(arg0);final int tabCounts = mTabLayout.getChildCount();//得到的tab数,为了能循环滚动,增加了一个空的,因此得到的个数会加1if (arg0 == tabCounts - 2) {//滑到末尾时//左边的tab显示全全称TabView tabView1 = (TabView) mTabLayout.getChildAt((arg0)% tabCounts);tabView1.setTextColor(Color.WHITE);tabView1.setText(MainActivity.CONTENT[(arg0) % (tabCounts)]);//右边的tab显示缩写词TabView tabView2 = (TabView) mTabLayout.getChildAt((arg0 + 1)% tabCounts);tabView2.setTextColor(Color.GRAY);tabView2.setText(MainActivity.CONTENT2[(0) % tabCounts]);} else {//左边的tab显示全全称TabView tabView1 = (TabView) mTabLayout.getChildAt((arg0)% tabCounts);tabView1.setTextColor(Color.WHITE);tabView1.setText(MainActivity.CONTENT[(arg0) % (tabCounts)]);//右边的tab显示缩写词TabView tabView2 = (TabView) mTabLayout.getChildAt((arg0 + 1)% (tabCounts - 1));tabView2.setTextColor(Color.GRAY);tabView2.setText(MainActivity.CONTENT2[(arg0 + 1) % (tabCounts - 1)]);}if (mListener != null) {mListener.onPageSelected(arg0);}}


这样就大概按照要求修改好了,哦,对了,下面的viewpager也要实现循环滑动,我在网上找了一个叫LoopViewPager的开源组件,直接将ViewPager替换为LoopViewPager就行了。


<com.imbryk.viewPager.LoopViewPager        android:id="@+id/viewpager"        android:layout_width="fill_parent"        android:layout_height="0dp"        android:layout_weight="1"        />


CustomIndicatorAdapter的getItem要稍微修改下:比如要将最后一个放在首位就行了。


@EActivity(R.layout.activity_main)@WindowFeature(Window.FEATURE_NO_TITLE)public class MainActivity extends BaseActivity { public static final String[] CONTENT = new String[] { "我的视频", "我的视频群" ,"我的设置"}; public static final String[] CONTENT2 = new String[] { "视频", "视频群","设置" };  CustomIndicatorAdapter mAdapter;@ViewById(R.id.viewpager)LoopViewPager mPager;@ViewById(R.id.indicator)CustomTabPageIndicator indicator;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@AfterViewspublic void init() {mAdapter = new CustomIndicatorAdapter(getSupportFragmentManager());mPager.setAdapter(mAdapter);indicator.setViewPager(mPager);}class CustomIndicatorAdapter extends FragmentPagerAdapter {        public CustomIndicatorAdapter(FragmentManager fm) {            super(fm);        }        @Override        public Fragment getItem(int position) {        Fragment fragment=null;        switch(position % CONTENT.length){        case 0:        fragment=new MySettingFragment_();        break;        case 1:        fragment=new MyVideoFragment_();        break;        case 2:        fragment=new MyVideoGroupFragment_();        break;                }        return fragment;        }        @Override        public CharSequence getPageTitle(int position) {            return CONTENT[position % CONTENT.length];        }        @Override        public int getCount() {          return CONTENT.length;        }    }}







0 0
原创粉丝点击