热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android如何自定义圆点指示器

这篇文章主要讲解了“Android如何自定义圆点指示器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“

这篇文章主要讲解了“Android如何自定义圆点指示器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android如何自定义圆点指示器”吧!

先上效果图

Android如何自定义圆点指示器

大概思路就是自定义View 从左至右绘制圆点 然后在ViewPager的OnPageChangeListener中设置当前页面的圆点

下面是代码

先定义属性


    
    
    
        
        
    

接下来是自定义的View

public class Indicator extends View{
 
    private static final int DEFAULT_TOTAL_INDEX = 5;
    private static final int DEFAULT_CURRENT_INDEX = 0;
    private static final int DEFAULT_CIRCLE_DISTANCE = 40;
    private static final int DEFAULT_CIRCLE_RADIUS = 8;
    private static final int DEFAULT_CIRCLE_SELECTED_RADIUS = 11;
 
    private int selectedColor;
    private int unselectedColor;
    private int currentIndex;
    private int totalIndex;
    private Paint paint;
    private int startX;
    private int startSelectedY;
    private int startY;
    private int centreX;
 
    public Indicator(Context context) {
        this(context,null);
    }
 
    public Indicator(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
 
    public Indicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.Indicator,defStyleAttr,0);
        selectedColor = typedArray.getColor(R.styleable.Indicator_selectedColor, Color.LTGRAY);
        unselectedColor = typedArray.getColor(R.styleable.Indicator_unselectedColor,Color.WHITE);
        typedArray.recycle();
        totalIndex = DEFAULT_TOTAL_INDEX;
        currentIndex = DEFAULT_CURRENT_INDEX;
        paint = new Paint();
    }

从TypedArray中获取自定义的属性,totalIndex是总的圆点个数,currentIndex是当前页面的圆点
接下来是重写的OnDraw()方法

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        centreX = getWidth() / 2;
        startSelectedY = getHeight() / 2 - DEFAULT_CIRCLE_SELECTED_RADIUS;
        startY = getHeight() / 2 - DEFAULT_CIRCLE_RADIUS;
        if (totalIndex % 2 == 0){
            startX = centreX - (int)(1.0 * (totalIndex - 1)/2 * DEFAULT_CIRCLE_DISTANCE);
        }else{
            startX = centreX - totalIndex / 2 * DEFAULT_CIRCLE_DISTANCE;
        }
        paint.setAntiAlias(true);
        paint.setColor(unselectedColor);
        int tempX = startX;
        for(int i = 0 ; i < totalIndex ; i++ ){
            RectF rectF = new RectF(tempX - DEFAULT_CIRCLE_RADIUS,startY,
                    tempX + DEFAULT_CIRCLE_RADIUS,startY + 2 * DEFAULT_CIRCLE_RADIUS);
            if (i == currentIndex) {
                paint.setColor(selectedColor);
                rectF = new RectF(tempX - DEFAULT_CIRCLE_SELECTED_RADIUS,startSelectedY,
                        tempX + DEFAULT_CIRCLE_SELECTED_RADIUS,startSelectedY + 2 * DEFAULT_CIRCLE_SELECTED_RADIUS);
            }
            canvas.drawOval(rectF,paint);
            if (paint.getColor() == selectedColor)
                paint.setColor(unselectedColor);
            tempX += DEFAULT_CIRCLE_DISTANCE;
        }
    }

因为当前页面的圆点和未选中页面的圆点要设置不同的大小 所以分别设置每个圆点的坐标 然后用for循环绘制圆点
这里有一点要注意 new RectF() 的四个参数分别是圆点外面的矩形的左上角的X,Y和右下角的X,Y

接下来是设置当前页面的圆点的方法

public void setCurrentIndex(int currentIndex){
        //if (currentIndex < 0)
        //    currentIndex += totalIndex ;
        //if (currentIndex > totalIndex - 1)
        //    currentIndex %= totalIndex;
        this.currentIndex = currentIndex;
        invalidate();
    }

注释里的代码是当页面可以循环的时候设置的
接下来是设置总的圆点个数的方法

public void setTotalIndex(int totalIndex){
        int oldTotalIndex = this.totalIndex;
        if (totalIndex < 1)
            return;
        if (totalIndex < oldTotalIndex){
            if (currentIndex == totalIndex )
                currentIndex = totalIndex - 1;
        }
        this.totalIndex = totalIndex;
        invalidate();
    }

当删除圆点的时候 如果currentIndex是最后一个 让currentIndex向前移动
接下来是重写的OnMeasure()方法

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
    }
 
    private int measureHeight(int measureSpec){
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        int desired = DEFAULT_CIRCLE_SELECTED_RADIUS * 2 + getPaddingBottom() + getPaddingTop();
        if(specMode == MeasureSpec.EXACTLY) {
            result = Math.max(desired,specSize);
        }else{
            if(specMode == MeasureSpec.AT_MOST){
                result = Math.min(desired,specSize);
            }
            else result = desired;
        }
        return result;
    }
 
    private int measureWidth(int measureSpec){
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        int desired = (totalIndex - 1) * DEFAULT_CIRCLE_DISTANCE + DEFAULT_CIRCLE_SELECTED_RADIUS * 2 + getPaddingLeft() + getPaddingRight();
        if(specMode == MeasureSpec.EXACTLY) {
            result = Math.max(desired,specSize);
        }else{
            if(specMode == MeasureSpec.AT_MOST){
                result = Math.min(desired,specSize);
            }else result = desired;
        }
        return result;
    }

下面是MainActivity的布局代码,很简单


 
    
 
    
 

下面是MainActivity的代码

public class MainActivity extends AppCompatActivity {
 
    View layout1,layout2,layout3;
    ViewPager viewPager;
    Indicator indicator;
 
    List viewList;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        LayoutInflater inflater = getLayoutInflater();
        layout1 = inflater.inflate(R.layout.layout1,null);
        layout2 = inflater.inflate(R.layout.layout2,null);
        layout3 = inflater.inflate(R.layout.layout3,null);
 
        viewList = new ArrayList<>();
        viewList.add(layout1);
        viewList.add(layout2);
        viewList.add(layout3);
 
 
        indicator = (Indicator) findViewById(R.id.indicator);
        indicator.setTotalIndex(viewList.size());
        PagerAdapter pagerAdapter = new PagerAdapter() {
            @Override
            public int getCount() {
                return viewList.size();
            }
 
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView(viewList.get(position));
            }
 
            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                container.addView(viewList.get(position));
 
                return position;
            }
 
            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == viewList.get(Integer.parseInt(object.toString()));
            }
        };
 
        viewPager.setAdapter(pagerAdapter);
        viewPager.setOnPageChangeListener(new PageChangeListener());
 
    }
 
    public class PageChangeListener implements ViewPager.OnPageChangeListener{
 
 
        @Override
        public void onPageSelected(int position) {
 
            indicator.setCurrentIndex(position);
        }
 
        @Override
        public void onPageScrollStateChanged(int state) {
 
        }
 
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 
        }
    }

ViewPager里添加了三个空页面 然后设置指示器的圆点个数,最后在ViewPager的OnPageChangeListener中设置当前的 页面的圆点。

感谢各位的阅读,以上就是“Android如何自定义圆点指示器”的内容了,经过本文的学习后,相信大家对Android如何自定义圆点指示器这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程笔记,小编将为大家推送更多相关知识点的文章,欢迎关注!


推荐阅读
  • Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ... [详细]
  • 本文探讨了Android系统中支持的图像格式及其在不同版本中的兼容性问题,重点涵盖了存储、HTTP传输、相机功能以及SparseArray的应用。文章详细分析了从Android 10 (API 29) 到Android 11 的存储规范变化,并讨论了这些变化对图像处理的影响。此外,还介绍了如何通过系统升级和代码优化来解决版本兼容性问题,以确保应用程序在不同Android版本中稳定运行。 ... [详细]
  • java解析json转Map前段时间在做json报文处理的时候,写了一个针对不同格式json转map的处理工具方法,总结记录如下:1、单节点单层级、单节点多层级json转mapim ... [详细]
  • 一个建表一个执行crud操作建表代码importandroid.content.Context;importandroid.database.sqlite.SQLiteDat ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • 可参照github代码:https:github.comrabbitmqrabbitmq-tutorialsblobmasterjavaEmitLogTopic.ja ... [详细]
  • 本文介绍了如何在Spring框架中使用AspectJ实现AOP编程,重点讲解了通过注解配置切面的方法,包括方法执行前和方法执行后的增强处理。阅读本文前,请确保已安装并配置好AspectJ。 ... [详细]
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • Spring Data JdbcTemplate 入门指南
    本文将介绍如何使用 Spring JdbcTemplate 进行数据库操作,包括查询和插入数据。我们将通过一个学生表的示例来演示具体步骤。 ... [详细]
  • 机器学习算法:SVM(支持向量机)
    SVM算法(SupportVectorMachine,支持向量机)的核心思想有2点:1、如果数据线性可分,那么基于最大间隔的方式来确定超平面,以确保全局最优, ... [详细]
  • 本文介绍如何在 Android 中自定义加载对话框 CustomProgressDialog,包括自定义 View 类和 XML 布局文件的详细步骤。 ... [详细]
  • AIX编程挑战赛:AIX正方形问题的算法解析与Java代码实现
    在昨晚的阅读中,我注意到了CSDN博主西部阿呆-小草屋发表的一篇文章《AIX程序设计大赛——AIX正方形问题》。该文详细阐述了AIX正方形问题的背景,并提供了一种基于Java语言的解决方案。本文将深入解析这一算法的核心思想,并展示具体的Java代码实现,旨在为参赛者和编程爱好者提供有价值的参考。 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
author-avatar
沈智强619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有