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

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



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



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

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

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

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

@Override
	public 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的最大宽度为屏幕的一半:

@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)) {
			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);
		// 设置宽度,使得只显示两个tabview
		mTabLayout.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)然后修改相关属性值:

@Override
	public void onPageSelected(int arg0) {
		setCurrentItem(arg0);
		final int tabCounts = mTabLayout.getChildCount();//得到的tab数,为了能循环滚动,增加了一个空的,因此得到的个数会加1
		if (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;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	@AfterViews
	public 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;
        }
    }

}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值