【笔记】自定义控件——ViewPager指示器
来源:互联网 发布:算法交易是量化 编辑:程序博客网 时间:2024/04/30 14:29
ViewPager的用途很广,像滚动广告、引导页等就常用这个控件实现,而在这些控件里常常会需要一个指示器来表示当前所显示的是第几张广告或第几页。
不堪回首的过去
以前在滚动广告时常常在布局文件中放一个LinearLayout,然后在代码中动态创建ImageView,添加到容器中,
dotList = new ArrayList<ImageView>();for (int i=0;i<list.size();i++) {LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(10,10);lp.setMargins(5,5,5,5);ImageView imageView = new ImageView(mContext);imageView.setLayoutParams(lp);imageView.setImageResource(R.drawable.dot_normal);//添加到指示器列表中dotList.add(imageView);//添加到LinearLayout容器中llDot.addView(imageView);}
每当广告滚动就去改变一下选中的指示点
for (int i=0;i<dotList.size();i++){dotList.get(i).setImageResource(R.drawable.dot_normal);}dotList.get(position%dotList.size()).setImageResource(R.drawable.dot_light);
自定义ViewPager指示器
根据原来的做法是在代码中动态创建指示点,然后加入到LinearLayout容器中,自定义的控件也通过继承LinearLayout来实现。
定义一个选中的指示点。class SelectView extends View { private Paint mPaint; public SelectView(Context context) { super(context); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(colorSelected); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(radius * 2, radius * 2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(colorSelected); canvas.drawCircle(radius, radius, radius, mPaint); } }
为什么只定义选中的指示点呢?
这里把指示点分为选中指示点和未选中指示点,未选中指示点无论是颜色和位置在控件显示之后都不需要改变,在这里可以当作背景,而选中指示点则需要随着ViewPager的onPageScrolled而移动。
/** * 绘制背景指示器 * * @param canvas */ private void drawBackground(Canvas canvas) { paint.setColor(colorNormal); for (int i = 0; i < num; i++) { canvas.drawCircle( padding + radius + i * (2 * radius + padding), padding + radius, radius, paint ); } }根据ViewPager的onPageScrolled显示选中点的位置
/** * 设置页数和偏移 * * @param pager * @param offset */ public void setPagerAndOffset(int pager, float offset) { this.pager = pager; this.offset = offset; //调用会使View测量、布局、重绘 requestLayout(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); //设置选中点的位置 selectView.layout( (int) (padding + (padding + 2 * radius) * (pager + offset)), padding, (int) (padding + (padding + 2 * radius) * (pager + 1 + offset)), padding + radius * 2 ); }
完整实现
public class ViewPagerIndicator extends LinearLayout { public ViewPagerIndicator(Context context) { this(context, null); } public ViewPagerIndicator(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } //指示器半径 private int radius = 10; //画笔 private Paint paint; //普通指示器颜色 private int colorNormal = Color.GRAY; //选中指示器颜色 private int colorSelected = Color.RED; //间距 private int padding = 20; //个数 private int num = 3; //选中的指示器 private SelectView selectView; //当前选中页 private int pager; //偏移 private float offset; /** * 初始化 * * @param attrs */ private void init(AttributeSet attrs) { //初始化属性 initAttrs(attrs); //初始化工具 initTools(); //不调用自身onDraw setWillNotDraw(false); } /** * 初始化属性 * * @param attrs */ private void initAttrs(AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator); radius = typedArray.getInt(R.styleable.ViewPagerIndicator_radius, 5); colorNormal = typedArray.getColor(R.styleable.ViewPagerIndicator_colorNormal, Color.GRAY); colorSelected = typedArray.getColor(R.styleable.ViewPagerIndicator_colorSelected, Color.RED); padding = typedArray.getInt(R.styleable.ViewPagerIndicator_padding, 10); num = typedArray.getInt(R.styleable.ViewPagerIndicator_num, 3); typedArray.recycle(); } /** * 初始化工具 */ private void initTools() { //初始化画笔 paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(colorNormal); //初始化选中点 selectView = new SelectView(getContext()); addView(selectView); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //计算设置控件的宽高 setMeasuredDimension(padding + (padding + 2 * radius) * num, (padding + radius) * 2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBackground(canvas); } /** * 绘制背景指示器 * * @param canvas */ private void drawBackground(Canvas canvas) { paint.setColor(colorNormal); for (int i = 0; i < num; i++) { //绘制每个点的位置 canvas.drawCircle( padding + radius + i * (2 * radius + padding), padding + radius, radius, paint ); } } public void setNum(int num) { this.num = num; } /** * 设置页数和偏移 * * @param pager * @param offset */ public void setPagerAndOffset(int pager, float offset) { this.pager = pager; this.offset = offset; //调用会使View测量、布局、重绘 requestLayout(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); //设置选中点的位置 selectView.layout( (int) (padding + (padding + 2 * radius) * (pager + offset)), padding, (int) (padding + (padding + 2 * radius) * (pager + 1 + offset)), padding + radius * 2 ); } /** * 选中的指示器 */ class SelectView extends View { private Paint mPaint; public SelectView(Context context) { super(context); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(colorSelected); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(radius * 2, radius * 2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(colorSelected); canvas.drawCircle(radius, radius, radius, mPaint); } }}
0 0
- 【笔记】自定义控件——ViewPager指示器
- Android——自定义ViewPager指示器
- Android 自定义控件ViewPager 指示器 ViewPagerIndicator
- Android自定义view之ViewPager指示器——1
- Android自定义view之ViewPager指示器——2
- 自定义ViewPager指示器
- 自定义viewpager指示器
- Android_自定义ViewPager指示器
- 自定义ViewPager指示器
- Android自定义ViewPager指示器
- Android-自定义ViewPager指示器
- 自定义ViewPager指示器
- Android自定义ViewPager指示器
- 自定义ViewPager指示器
- 安卓基础:自定义控件实现ViewPager指示器
- 自定义控件——视图树绘制指示器
- 自定义控件——万能的圆形指示器Indictor
- 自定义view实现ViewPager指示器
- CSS——Fonts(字体)
- 待整理的linux
- Flume-ng源码解析之Channel组件
- 分布式TensorFlow
- 33个必须了解的iOS开源库
- 【笔记】自定义控件——ViewPager指示器
- 【九度OJ】题目1196:成绩排序 解题报告
- 5-4 输出全排列 (20分)——DFS
- 华为OJ训练之0016-170102-记负均正
- linux问题经验
- 设计模式之单例模式
- ConcurrentHashMap 和 HashTable 的区别
- 最小二乘法及其C++实现
- leetcode142. Linked List Cycle II