Android——自定义ViewPager指示器
来源:互联网 发布:问道登陆器源码 编辑:程序博客网 时间:2024/05/17 03:40
很多ViewPager和下面的图形绑定一块来滚动,也就是指示器,指示器可以是很多,正
方形,长方形,三角形,圆形等。
这里举一个三角形例子:
效果图:未滑动
滑动中:
这里滑动只要超过倒数第二个就自动向后滑动。
上代码:
自定义view:
public class ViewPagerIndicator extends LinearLayout { private Paint paint; private Path path; private int triangleWidth; private int triangleHeight; private static final float RADIO_TRIANGLE_WIDTH = 1 / 6f; private static final int HIGHCOLOR = 0xffffffff; private static final int LOWERCOLOR = 0x88ffffff; private int initTranslationX; private int moveTranslationX; private int TabVisibleCount; private static final int COUNT_DEFAULT_TAB = 4; private List<String> titles = new ArrayList<String>(); public ViewPagerIndicator(Context context, AttributeSet attrs) { super(context, attrs); // 获取可见Tab的数量 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator); TabVisibleCount = ta.getInt(R.styleable.ViewPagerIndicator_visible_tab_count, COUNT_DEFAULT_TAB); if (TabVisibleCount < 0) { TabVisibleCount = COUNT_DEFAULT_TAB; } ta.recycle(); // 初始化画笔 paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.WHITE); paint.setStyle(Style.FILL); paint.setPathEffect(new CornerPathEffect(5)); } public ViewPagerIndicator(Context context) { super(context, null); // TODO Auto-generated constructor stub } /** * 绘制三角形 */ /** * 没有背景时直接调用的是dispatchDraw()方法,draw()方法里包含了dispatchDraw()方法的调用。 * 因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法 */ @Override protected void dispatchDraw(Canvas canvas) { // TODO Auto-generated method stub super.dispatchDraw(canvas); /* * 如果有save()和restore(), 那么平移、缩放、旋转等操作只对save()和restore()作用域之间的代码有效。 * 当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作, * 那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态, * 当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响 */ canvas.save(); canvas.translate(initTranslationX + moveTranslationX, getHeight()); canvas.drawPath(path, paint); canvas.restore(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // TODO Auto-generated method stub super.onSizeChanged(w, h, oldw, oldh); triangleWidth = (int) (w / TabVisibleCount * RADIO_TRIANGLE_WIDTH); initTranslationX = w / TabVisibleCount / 2 - triangleWidth / 2; initTrangle(); } /** * 在xml加载完成以后调用此方法 */ @Override protected void onFinishInflate() { // TODO Auto-generated method stub super.onFinishInflate(); int count = getChildCount(); if (count == 0) return; for (int i = 0; i < count; i++) { View view = getChildAt(i); LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams(); // 如果之前设有weight 都设置为0 lp.weight = 0; lp.width = getScreenWidth() / TabVisibleCount; view.setLayoutParams(lp); } setItemClickEvent(); } private int getScreenWidth() { // TODO Auto-generated method stub WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 初始化三角形 */ private void initTrangle() { // TODO Auto-generated method stub path = new Path(); triangleHeight = (int) (triangleWidth / 2 / 1.7); path.moveTo(0, 0); path.lineTo(triangleWidth, 0); path.lineTo(triangleWidth / 2, -triangleHeight); path.close(); } /** * 指示器跟随手指移动 * * @param position * 当前页 * @param offset(0~1) * 偏移量 */ public void scoll(int position, float offset) { // TODO Auto-generated method stub int tabWidth = getWidth() / TabVisibleCount; moveTranslationX = (int) (tabWidth * (position + offset)); // 容器移动,当tab处于移动至最后一个时 if (position >= (TabVisibleCount - 2) && offset > 0 && getChildCount() > TabVisibleCount) { if (TabVisibleCount != 1) { scrollTo((position - (TabVisibleCount - 2)) * tabWidth + (int) (tabWidth * offset), 0); } else { scrollTo(position * tabWidth + (int) (tabWidth * offset), 0); } } // 请求重绘三角形 invalidate(); } // 该方法需要在setTabitemTitles方法之前调用有效,因为用到了TabVisibleCount public void setVisibleTab(int count) { this.TabVisibleCount = count; } /** * 根据title动态创建TextView * * @param title * @return */ public void setTabitemTitles(List<String> titles) { if (titles != null && titles.size() > 0) { this.titles = titles; } for (String title : titles) { addView(getTextView(title)); } setItemClickEvent(); } private View getTextView(String title) { // TODO Auto-generated method stub TextView tv = new TextView(getContext()); LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.width = getScreenWidth() / TabVisibleCount; tv.setText(title); tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); tv.setGravity(Gravity.CENTER); tv.setLayoutParams(lp); tv.setTextColor(LOWERCOLOR); return tv; } /** * 用户的setOnPageChangeListener回调方法供外部使用 * * @author lpl * */ public interface PageChangeListener { public void onPageScrollStateChanged(int arg0); public void onPageScrolled(int arg0, float arg1, int arg2); public void onPageSelected(int arg0); } private PageChangeListener listener; public void setOnPageChangeListener(PageChangeListener listener) { this.listener = listener; } /** * 关联ViewPager * * @param pager * @param pos * 默认选中页 */ private ViewPager pager; public void setViewPager(final ViewPager pager, int pos) { this.pager = pager; pager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // 总偏移量:arg0(position)*tabWidth+arg1(positionoffset)*tabWidth if (listener != null) { listener.onPageScrolled(arg0, arg1, arg2); } scoll(arg0, arg1); } @Override public void onPageSelected(int arg0) { // TODO Auto-generated method stub if (listener != null) { listener.onPageSelected(arg0); } HighTextView(arg0); } }); pager.setCurrentItem(pos); HighTextView(pos); } public void resetColorTextView() { for (int i = 0; i < getChildCount(); i++) { TextView tv = (TextView) getChildAt(i); tv.setTextColor(LOWERCOLOR); } } /** * 设置高亮的TextView * * @param position */ public void HighTextView(int position) { resetColorTextView(); TextView tv = (TextView) getChildAt(position); tv.setTextColor(HIGHCOLOR); } /** * 设置tab的点击事件 */ public void setItemClickEvent() { for (int i = 0; i < getChildCount(); i++) { final int j = i; TextView tv = (TextView) getChildAt(i); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub pager.setCurrentItem(j); } }); } }}
在Activity中onCreate调用此控件:
// setVisibleTab该方法需要在setTabitemTitles方法之前调用有效,//因为用到了TabVisibleCount // indicator.setVisibleTab(3);设置可见的title个数 //titles是List容器存放TextView indicator.setTabitemTitles(titles); //默认0是第一个title为高亮选中 indicator.setViewPager(viewpager, 0); viewpager.setAdapter(adapter);
阅读全文
0 0
- Android——自定义ViewPager指示器
- Android自定义ViewPager指示器
- Android-自定义ViewPager指示器
- Android自定义ViewPager指示器
- Android自定义view之ViewPager指示器——1
- Android自定义view之ViewPager指示器——2
- 【笔记】自定义控件——ViewPager指示器
- Android自定义Viewpager指示器PagerIndicator-仿微博头条效果
- Android 自定义View实现ViewPager指示器
- Android---自定义ViewPager指示器(一)
- Android自定义View--Flyme6的Viewpager指示器
- Android 自定义控件ViewPager 指示器 ViewPagerIndicator
- 一行代码调用Android自定义ViewPager指示器
- 自定义ViewPager指示器
- 自定义viewpager指示器
- Android_自定义ViewPager指示器
- 自定义ViewPager指示器
- 自定义ViewPager指示器
- javascript的面向对象见解
- qsort快速排序
- matlab 图像显示 命令 image imshow
- ideal常用设置
- [LeetCode] Find Median from Data Stream
- Android——自定义ViewPager指示器
- HTML5学习笔记
- 【啊哈!算法】算法10:二叉树
- displayposition 和 float 的相互关系
- 欢迎使用CSDN-markdown编辑器
- scala 枚举类
- Spring Boot大纲
- 欢迎使用CSDN-markdown编辑器
- 一道值得分享(interesting)的题目