Android自定义Viewpager指示器PagerIndicator-仿微博头条效果
来源:互联网 发布:淘宝月老祠堂怎么样 编辑:程序博客网 时间:2024/04/30 01:58
平时工作之余,喜欢看看新闻,手机难免会装了几个新闻阅读类的app。新闻类的app风格大致一致,可以选择不同栏目,栏目可以切换。最近就在用微博头条,感觉界面挺清新的。而且它使用的PagerIndicator挺好看的。昨晚居然准时下班了,趁着早就实现了下。今天用博客好好记录下
上图
效果分析
1 每个tab都包含色块和文字,而且文字的显示个数不同
2 文字:由未选中到被选中的文字颜色从黑色变成白色;由选中到未被选中的文字颜色从白色变成黑色
3 色块:由未选中到被选中的色块显示高度越来越大;由选中到未被选中的色块显示高度越来越小
4 让处于中间的tab自动滑动到中间显示
实现思路
1 tab实现
1.1 自定义UpDownView,该View继承RelativeLayout
1.2 文字使用TextView显示,色块使用ImageView显示
public UpDownView(Context context, AttributeSet attrs) { super(context, attrs); imageView = new ImageView(context); // 设置ImageView的大小为每个父View(tab)的大小 LayoutParams imageParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); addView(imageView, imageParams); textView = new TextView(context); // 设置TextView的文字居中显示 textView.setGravity(Gravity.CENTER); // 设置TextView的高度为每个父View(tab)的高度 LayoutParams textParams = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); textParams.addRule(RelativeLayout.CENTER_IN_PARENT); textView.setPadding(40, 10, 40, 10); addView(textView, textParams);}
1.3 ImageView显示设置
// 当控件的宽高发生变化时回调该方法,可在这里获取控件的高度@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); height = textView.getMeasuredHeight(); // 通过setTranslationY让ImageView开始时只显示总高度的0.2f imageView.setTranslationY((int) (height * 0.8f)); LayoutParams imageParams = (LayoutParams) imageView .getLayoutParams(); imageParams.width = textView.getMeasuredWidth();}
1.4 该View对外提供的方法
// 设置ImageView的颜色public void setImageColor(int color) { imageView.setImageResource(color);}// 设置文字public void setText(String text) { textView.setText(text);}// 设置文字的颜色public void setTextColor(int color) { textView.setTextColor(color);}// 显示色块public void show() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationY", 0); objectAnimator.setDuration(300); objectAnimator.start();}// 设置ImageView的偏移量,即改变色块显示的高度public void setTranslation(float direction) { imageView.setTranslationY(direction);}// 隐藏色块public void hide() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationY", (int) (height * 0.8f)); objectAnimator.setDuration(300); objectAnimator.start();}// 主要用于获取当前色块所在的位置public int getmIndex() { return mIndex;}
2 PagerIndicator指示器的实现
2.1 指示器可以装载很多的tab,而且支持横向滑动,于是可以选择继承HorizontalScrollView
2.2 由于HorizontalScrollView只能有一个子View,所以在初始化的时候,为该View添加一个默认的子View,当需要添加tab时,将其添加到默认的子View中即可。
public PagerIndicatorTwo(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; // 设置横向滚动条不显示 setHorizontalScrollBarEnabled(false); // 添加一个LinearLayout作为默认的子View linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); LayoutParams liLayoutParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); addView(linearLayout, liLayoutParams);}
2.3 与ViewPager绑定
public void setmViewPager(ViewPager viewPager) { this.mViewPager = viewPager; if (mViewPager.getAdapter() == null) { throw new NullPointerException(); } // 该PagerIndicator实现了OnPageChangeListener接口,当ViewPager发生变化时,会回调OnPageChangeListener相应的方法,通过这些方法,可以完成指示器相应的变化 this.mViewPager.setOnPageChangeListener(this);}
2.4 设置tab
public void setIndicators(List<String> indicators) { this.indicators.clear(); this.indicators.addAll(indicators); linearLayout.removeAllViews(); // 创建对应个数的UpDownView,并添加到linearLayout中去 for (int i = 0; i < indicators.size(); i++) { UpDownView upDownView = new UpDownView(context); upDownView.setGravity(Gravity.CENTER); upDownView.setImageColor(colors[i % 3]); // 设置每个tab所在的位置 upDownView.mIndex = i; upDownView.setText(indicators.get(i)); // 为每个tab增加点击事件 upDownView.setOnClickListener(onTadClickListener); LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); linearLayout.addView(upDownView, params); } requestLayout();}
2.5 tab点击事件
private OnClickListener onTadClickListener = new OnClickListener() { @Override public void onClick(View view) { tabClick = true; UpDownView upDownView = (UpDownView) view; // 获取到tab所在的位置,调用ViewPager的setCurrentItem切换页面 mViewPager.setCurrentItem(upDownView.mIndex); }};
2.6 onPageScrolled的回调(即滑动ViewPager产生的变化处理):该方法有三个参数,通过这三个参数的变化,改变每个tab对应的变化即可;这里有个学习点,就是颜色的变化可以通过ArgbEvaluator这个类实现
leftDownView = (UpDownView) linearLayout.getChildAt(arg0);rightDownView = (UpDownView) linearLayout.getChildAt(arg0 + 1);// 色条变化leftDownView.setTranslation(arg1 * leftDownView.height * 0.8f);rightDownView.setTranslation((1 - arg1) * rightDownView.height * 0.8f);// 文字颜色变化int leftColor = (Integer) new ArgbEvaluator().evaluate(arg1, Color.WHITE, Color.BLACK);leftDownView.setTextColor(leftColor);int rightColor = (Integer) new ArgbEvaluator().evaluate(1 - arg1, Color.WHITE, Color.BLACK);rightDownView.setTextColor(rightColor);
2.7 自动滑动到中间位置
// 当某一项被选中时会回调onPageSelected方法,在这里我们可以让该PagerIndicator自动滚动:这里主要涉及到移动距离的计算public void changePager(final int last) { final UpDownView lastChild = (UpDownView) linearLayout.getChildAt(last); int[] location = new int[2]; lastChild.getLocationOnScreen(location); final int scrollPos = location[0] - (getMeasuredWidth() - lastChild.getMeasuredWidth()) / 2; smoothScroll(scrollPos, new AnimatorListenerAdapter() { });}
3 外边调用OnPageChangeListener问题
由于该PagerIndicator需要根据OnPageChangeListener的回调变化,所以需要在PagerIndicator中实现该接口,并设置给ViewPager。这就产生个问题,假如项目在使用ViewPager时也需要根据OnPageChangeListener的回调进行某些处理该怎么处理。这个问题可以这样子处理
3.1 在项目中,不调用ViewPager.setOnPageChangeListener,而是PagerIndicator.setOnPageChangeListener,即将回调设置给PagerIndicator,这样就可以正常监听该接口了
3.2 看内部处理
// 将传递进来的OnPageChangeListener对象保存到onPageChangeListener中private OnPageChangeListener onPageChangeListener;public void setOnPageChangeListener( OnPageChangeListener onPageChangeListener) { this.onPageChangeListener = onPageChangeListener;}// 当PagerIndicator中的onPageScrollStateChanged方法被调用时,我们手动调用传进来的onPageChangeListener的onPageScrollStateChanged(arg0)方法,其他回调方法一样@Overridepublic void onPageScrollStateChanged(int arg0) { if (mViewPager.getAdapter().getCount() != indicators.size()) { return; } onPageChangeListener.onPageScrollStateChanged(arg0);}
总结
至此,一个仿微博头条效果的PagerIndicator就实现了。当然我们可以自定义一些属性,例如文字颜色和大小,ImageView的颜色等,用于设置想要的一些显示。提高该View的灵活性
0 0
- Android自定义Viewpager指示器PagerIndicator-仿微博头条效果
- Android 自制ViewPager的指示器PagerIndicator
- Android自定义ViewPager指示器
- Android-自定义ViewPager指示器
- Android自定义ViewPager指示器
- 配合viewpager使用的指示器PagerIndicator
- 自定义ViewPager和弹性圆PagerIndicator
- Android 自定义View实现ViewPager指示器
- Android---自定义ViewPager指示器(一)
- Android自定义View--Flyme6的Viewpager指示器
- Android 自定义控件ViewPager 指示器 ViewPagerIndicator
- Android——自定义ViewPager指示器
- 一行代码调用Android自定义ViewPager指示器
- 自定义ViewPager指示器
- 自定义viewpager指示器
- Android_自定义ViewPager指示器
- 自定义ViewPager指示器
- 自定义ViewPager指示器
- ListView分页功能(2) 自定义View实现分页功能
- 数据结构之-栈(Java实现)
- session 如 mysql
- Handler 闪屏页小应用
- 当file_get_contents 或者 simplexml_load_file的时候乱码
- Android自定义Viewpager指示器PagerIndicator-仿微博头条效果
- USACO 4.2.1 iSap + gap优化
- JAVA实现快速排序
- 从头到尾彻底理解KMP
- NYOJ矩形的个数
- http请求状态码
- 190. Reverse Bits
- ajax 多文件上传
- C语言实现简单的面向对象例子