ViewPager+Indicator(如何写indicator)
2015-11-23 21:02
344 查看
一:概述
这个教程好像网上挺多的。viewpager用fragment作为每一个item,但是似乎好像indicator似乎都有点不太满意,下面的滑动条是直接跳动的,不是类似动画滑动的。现在就说说这个滑动条。然后再说说其他的东西(比如activity传数据给fragment啊。这些)。先看看效果图:
二:源码解读
我们先讲讲viewpager吧。[code]private MyPageAdapter adapter ; private ViewPager pager; private List<MyFragment> listFragment ; ... //这里初始化10个fragment for(int i = 0 ;i < 10 ;i ++){ Bundle bundle = new Bundle(); bundle.putString("who","hello world "+ i); MyFragment fragment = MyFragment.getInstance(bundle); listFragment.add(fragment); }
通过activity传数据给fragment,直接调用fr.setArguments(bundle);就可以了。bundle就是数据集,然后在fragment中直接调用Bundle bundle = getArguments();就可以获得了。
[code]public static MyFragment getInstance(Bundle bundle){ MyFragment fr = new MyFragment(); fr.setArguments(bundle); return fr; }
然后为viewpager添加适配器。注意其中的getPageTitle()方法,这个方法的返回值就可以作为indicator中的值。
[code]class MyPageAdapter extends FragmentPagerAdapter { public MyPageAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return listFragment.get(position); } @Override public long getItemId(int position) { return super.getItemId(position); } @Override public int getCount() { return listFragment.size(); } @Override public CharSequence getPageTitle(int position) { return "title - "+position; } }
然后看看TestIndicatorActivity这个activity实现了MyIndicator.CustomeTextViewInter 接口
主要实现了两个方法,用来让开发者可以直接在代码中自定义indicator,被选择或者没有被选择的效果
selected():被选择的效果。
unSelect():没有被选择的效果。
两个都只是简单的修改了下背景颜色而已。(你们可以实现自己想实现的,比如加粗等等。)
[code] @Override public TextView selected(TextView tv) { tv.setBackgroundColor(Color.parseColor("#8FFF58")); return tv; } @Override public TextView unSelect(TextView tv) { tv.setBackgroundColor(Color.parseColor("#FFFFFF")); return tv; }
我们只需要写下两句代码就可以使用indicator。
[code]//自定义被选择,没被选择的接口 indicator.setCustomeTextViewInter(this); ... indicator.setViewPager(pager);
好了我们详细说说indicator的实现方法。
我写了个attr文件(好像叫自定义属性文件)
[code]<resources> <declare-styleable name="MyIndicator"> <attr name="lineHeight" format="dimension"/> <attr name="lineColor" format="color"/> </declare-styleable> </resources>
然后在布局文件中调用如下就可以
记得在Android studio 布局文件的根元素中加入
xmlns:custom=”http://schemas.android.com/apk/res-auto”
[code] <com.example.tongmin.testproject.MyIndicator android:layout_width="match_parent" android:layout_height="50dp" custom:lineColor="#5680FF" custom:lineHeight="5dp" android:id="@+id/myindicator" />
使用下面的代码就可以读取其中的数据了。
[code] TypedArray a = context.getTheme() .obtainStyledAttributes(attrs, R.styleable.MyIndicator, defStyleAttr, 0); lineHeight = a.getDimension(R.styleable.MyIndicator_lineHeight, 10); lineColor = a.getColor(R.styleable.MyIndicator_lineColor, Color.BLACK); a.recycle();
然后整个indicator时继承自 HorizontalScrollView ,因为都是横着滑动的。
然后看看下面代码。注释也看看
[code]//首先将自带的横向的滑动条禁用掉。 this.setHorizontalScrollBarEnabled(false); //因为scrollview只能有一个子元素,就添加个LinearLayout linearContain = new LinearLayout(context); linearContain.setOrientation(LinearLayout.HORIZONTAL); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); this.addView(linearContain, params);
然后看看setViewPager()这个方法,将viewpager设置进来后做了一些初始化工作。
setheader就是将有多少个fragment,然后就初始化多少个indicator的item。
[code] public void setViewPager(ViewPager viewPager) { this.viewPager = viewPager; this.viewPager.addOnPageChangeListener(this); setHeader(); changeTextView(0); }
这个就是添加一个个item的具体的方法。其中添加的其实是textview。
因为我们放出了一个接口,让用户自己实现选择,没被选择的textview。所以需要做一下判断。
[code] private void addTextView(String text , int position) { //判断用户是否自定义了textview TextView textView = new Text(context,position); if (customeTextViewInter != null) { textView = customeTextViewInter.unSelect(textView); if (textView == null) { throw new RuntimeException("customeTextViewInter textview == null"); } } textView.setText(text); linearContain.addView(textView); }
其中Text是自定义的TextView,其中的position属性是记录我这个textView是第几个item,因为要添加点击事件,点击跳转到对应fragment。
然后注意还写了params.bottomMargin = (int) lineHeight;
这个是为了下面的滑动条腾出空间来。不然把他遮挡了。
[code]private class Text extends TextView { int position; public Text(Context context , int position) { super(context); this.position = position; this.init(context); } private void init(Context context) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); this.setLayoutParams(params); int size = dip2px(context, 10); params.bottomMargin = (int) lineHeight; this.setPadding(size, 0, size, 0); this.setGravity(Gravity.CENTER); this.setTextSize(20); this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { viewPager.setCurrentItem(position); } }); } }
好了。现在我们手动为这个viewpager设置一个ViewPager.OnPageChangeListener
监听viewpager的滑动。
这个接口需要实现三个方法。
1.onPageScrolled()是在滑动的时候回调的一个接口。
[code] a).position是在滑动的时候所在的position(比如我在第一个fragment滑动到第二个fragment的时候这个position就是0,从0开始的啊。) b).positionOffset就是当前的滑动在整个viewpager的比例。 c).positionOffsetPixels。就是这个fragment滑动的总像素数。
2.onPageSelected()是在滑动到被选择的fragment回调的。
[code] a).position就是被选择的position。(从第一个滑向第二个,这个position就指向第二个)。
[code] @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { changeLinePosition(position, positionOffset); } @Override public void onPageSelected(int position) { changeTextView(position); } @Override public void onPageScrollStateChanged(int state) { }
我们触发滑动条滑动时间就是在onPageScrolled()中,然后修改textview的样式的时在onPageSelected();
我们看看changeLinePosition();方法
首先找到对应的textview然后算出他的宽度。
currentPosition 就是当前滑动条所在的 X 坐标。
this.scrollTo((int) currentPosition - scroll, 0);
是让当前HorizontalScrollView滑动到指定位置。不然会出现像滑动条已经到最右边了。但是scrollview并没有滚动过去。就看不见了。
看下图:
[code]private void changeLinePosition(int position, float offset) { int left = linearContain.getChildAt(position).getLeft(); int right = linearContain.getChildAt(position).getRight(); lineWidth = right - left; offset = lineWidth * offset; currentPosition = left + offset; this.scrollTo((int) currentPosition - scroll, 0); invalidate(); }
最后在ondraw()方法中,画出下面的滑动条就可以了。找到自己的坐标就可以了。
[code] @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int textHeight = linearContain.getHeight(); canvas.drawRect(currentPosition, textHeight - lineHeight, currentPosition + lineWidth, textHeight, linePaint); }
源码下载
加个好友共同学习(不是公众号):
因为小弟水平有限,如果有写的有问题,希望指出。
相关文章推荐
- 内存管理:内存泄漏和空悬指针
- FC400A与400B的区别
- ViewPager 详解(一)---基本入门
- MATLAB的cat()函数
- Android自定义控件之仿京东商城下拉刷新
- 用Maven构建项目&写一个简单的Mapper-Reducer
- 善於偽善
- Install Multi Neo4J-server on Single Server
- 学习之路/免费的图库推荐
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- UVA 题目401 - Palindromes(回文词)
- IOS图层Layer学习笔记(一)—— 序
- coderforce 500B New Year Permutation
- 信息安全系统设计基础实验四:外设驱动程序设计(20135229,20135234)
- 第二个Sprint冲刺第一天
- 冲刺第十天
- AngularJs $interpolate 和 $parse
- JPA通用Dao类设计
- 二次剩余
- ios:字符串与汉字的判断