自定义View,又一种进度条的呈现,CircleProgressView使用解析

简介:

转载请注明出处王亟亟的大牛之路

话不多说,先上效果图
这里写图片描述这里写图片描述

循环旋转的状态
这里写图片描述这里写图片描述

项目结构

这里写图片描述
一个Sample包,一个Lib包。Lib包里面其实只有一个累,很多内容都在素材文件里,比较建议把内容复制出来,贴到自己的项目中

主类:

public class MainActivity extends ActionBarActivity {


    CircleProgressView mCircleView;
    Switch mSwitchSpin;
    Switch mSwitchShowUnit;
    SeekBar mSeekBar;
    SeekBar mSeekBarSpinnerLength;

    @Override
    protected void onCreate(Bundle savedInstanceState) {


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WebView.setWebContentsDebuggingEnabled(true);
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mCircleView = (CircleProgressView) findViewById(R.id.circleView);
        mCircleView.setMaxValue(100);
        mCircleView.setUnit("%");
        mCircleView.setValue(0);

        //Setup Switch
        mSwitchSpin = (Switch) findViewById(R.id.switch1);
        mSwitchSpin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mCircleView.spin();
                } else {
                    mCircleView.stopSpinning();
                }
            }
        });

        mSwitchShowUnit = (Switch) findViewById(R.id.switch2);
        mSwitchShowUnit.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    mCircleView.setShowUnit(isChecked);
            }
        });

        //Setup SeekBar
        mSeekBar = (SeekBar) findViewById(R.id.seekBar);
        mSeekBar.setMax(100);
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mCircleView.setValueAnimated(seekBar.getProgress(),1500);
                mSwitchSpin.setChecked(false);
            }
        });

        mSeekBarSpinnerLength = (SeekBar) findViewById(R.id.seekBar2);
        mSeekBarSpinnerLength.setMax(360);
        mSeekBarSpinnerLength.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                mCircleView.setSpinningBarLength(seekBar.getProgress());
            }
        });


    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
//        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
//        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
//        if (id == R.id.action_settings) {
//            return true;
//        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mCircleView.setValue(0);
        mCircleView.setValueAnimated(0);
    }
}

分析:
一个CircleProgressView自定义控件,2个SeekBar来控制进度条的百分比,以及长度,2个Switch用于切换显示内容,和一堆显示的TextView

可以在OnStart()调用setValue()方法,来给进度条赋值。而内部实现也是Handle传参的一系列操作

    /**
     * Set the value of the circle view without an animation.
     * Stops any currently active animations.
     */
    public void setValue(float _value) {
        Message msg = new Message();
        msg.what = AnimationMsg.SET_VALUE.ordinal();
        msg.obj = new float[]{_value, _value};
        mAnimationHandler.sendMessage(msg);
    }

在HandleMessage方法里又调用setValue(msg, circleView);
最终实现的是setValue(Message msg, CircleProgressView _circleView)方法

   private void setValue(Message msg, CircleProgressView _circleView) {
            _circleView.mValueFrom = _circleView.mValueTo;
            _circleView.mCurrentValue = _circleView.mValueTo = ((float[]) msg.obj)[0];
            _circleView.mAnimationState = AnimationState.IDLE;
            _circleView.invalidate();
        }

所以,你在代码操作的过程中,可以肆意调用SetValue()方法,不用在意会对其他部分的内容产生影响。

Sample代码里的 mSeekBarSpinnerLength.setMax(360);就等于mCircleView.setSpinningBarLength(seekBar.getProgress());给环状的SpinningBar传一个int的值让他呈现出一个角度为seekBar.getProgress()/360的图形。当然你传入的数值<360时,SeekBar拉到底了也不会成为整圆 那么>360的话只要到达360圆就已经呈现出来了,多余的值将没有效果。
效果如图:
这里写图片描述

然后我们来看下核心类CircleProgressView

public class CircleProgressView extends View 继承于View

然后洋洋洒洒1300+行的代码,我就不一一分析了,一些是画的一些是用的,亟亟就不做过多解释了,自己可以看源码,为了用那我们来看下一些配置

    //尺寸参数
    private int mLayoutHeight = 0;
    private int mLayoutWidth = 0;
    private int mFullRadius = 100;
    private int mCircleRadius = 80;
    private int mBarWidth = 40;
    private int mRimWidth = 40;
    private int mTextSize = 20;
    private float mContourSize = 1;
    private float mTextScale = 1;
    private float mUnitScale = 1;

对图形的整个大小啊,半径啊,字体的大小啊等进行设置。

    //颜色
    private final int mBarColorStandard =  0xff009688; //stylish blue
    private int mContourColor = 0xAA000000;
    private int mSpinnerColor = mBarColorStandard; //stylish blue
    private int mFillColor = 0x00000000;  //transparent
    private int mRimColor = 0xAA83d0c9;
    private int mTextColor = 0xFF000000;
    private int mUnitColor = 0xFF000000;
    private int[] mBarColors = new int[]{
            mBarColorStandard, //stylish blue
            mBarColorStandard, //stylish blue
    };

颜色的设置,圆的颜色,字的颜色等

  private float mSpinSpeed = 2.8f; 动画的滚动速度

总体来说,使用起来还是很方便的,附上源码大家自己看吧
http://yunpan.cn/cdLfFUxTaNydr 访问密码 6c65

目录
相关文章
|
12月前
|
并行计算 Java 数据处理
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析
764 0
|
12月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
786 2
|
7月前
|
Web App开发 移动开发 前端开发
React音频播放器样式自定义全解析:从入门到避坑指南
在React中使用HTML5原生&lt;audio&gt;标签时,开发者常面临视觉一致性缺失、样式定制局限和交互体验割裂等问题。通过隐藏原生控件并构建自定义UI层,可以实现完全可控的播放器视觉风格,避免状态不同步等典型问题。结合事件监听、进度条拖拽、浏览器兼容性处理及性能优化技巧,可构建高性能、可维护的音频组件,满足跨平台需求。建议优先使用成熟音频库(如react-player),仅在深度定制需求时采用原生方案。
226 12
|
10月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
12月前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
197 0
|
开发者 监控 开发工具
如何将JSF应用送上云端?揭秘在Google Cloud Platform上部署JSF应用的神秘步骤
【8月更文挑战第31天】本文详细介绍如何在Google Cloud Platform (GCP) 上部署JavaServer Faces (JSF) 应用。首先,确保已准备好JSF应用并通过Maven构建WAR包。接着,使用Google Cloud SDK登录并配置GCP环境。然后,创建`app.yaml`文件以配置Google App Engine,并使用`gcloud app deploy`命令完成部署。最后,通过`gcloud app browse`访问应用,并利用GCP的监控和日志服务进行管理和故障排查。整个过程简单高效,帮助开发者轻松部署和管理JSF应用。
141 0
|
开发者 容器 Java
Azure云之旅:JSF应用的神秘部署指南,揭开云原生的新篇章!
【8月更文挑战第31天】本文探讨了如何在Azure上部署JavaServer Faces (JSF) 应用,充分发挥其界面构建能力和云平台优势,实现高效安全的Web应用。Azure提供的多种服务如App Service、Kubernetes Service (AKS) 和DevOps简化了部署流程,并支持应用全生命周期管理。文章详细介绍了使用Azure Spring Cloud和App Service部署JSF应用的具体步骤,帮助开发者更好地利用Azure的强大功能。无论是在微服务架构下还是传统环境中,Azure都能为JSF应用提供全面支持,助力开发者拓展技术视野与实践机会。
63 0
|
前端开发 开发者
Vaadin Grid的秘密武器:打造超凡脱俗的数据展示体验!
【8月更文挑战第31天】赵萌是一位热爱UI设计的前端开发工程师。在公司内部项目中,她面临大量用户数据展示的挑战,并选择了功能强大的Vaadin Grid来解决。她在技术博客上分享了这一过程,介绍了Vaadin Grid的基本概念及其丰富的内置功能。通过自定义列和模板,赵萌展示了如何实现复杂的数据展示。
138 0
|
SQL 开发框架 .NET
深入解析Entity Framework Core中的自定义SQL查询与Raw SQL技巧:从基础到高级应用的全面指南,附带示例代码与最佳实践建议
【8月更文挑战第31天】本文详细介绍了如何在 Entity Framework Core (EF Core) 中使用自定义 SQL 查询与 Raw SQL。首先,通过创建基于 EF Core 的项目并配置数据库上下文,定义领域模型。然后,使用 `FromSqlRaw` 和 `FromSqlInterpolated` 方法执行自定义 SQL 查询。此外,还展示了如何使用 Raw SQL 进行数据更新和删除操作。最后,通过结合 LINQ 和 Raw SQL 构建动态 SQL 语句,处理复杂查询场景。本文提供了具体代码示例,帮助读者理解和应用这些技术,提升数据访问层的效率和灵活性。
696 0
|
开发框架 API 开发者
Flutter表单控件深度解析:从基本构建到高级自定义,全方位打造既美观又实用的移动端数据输入体验,让应用交互更上一层楼
【8月更文挑战第31天】在构建美观且功能强大的移动应用时,表单是不可或缺的部分。Flutter 作为热门的跨平台开发框架,提供了丰富的表单控件和 API,使开发者能轻松创建高质量表单。本文通过问题解答形式,深入解读 Flutter 表单控件,并通过具体示例代码展示如何构建优秀的移动应用表单。涵盖创建基本表单、处理表单提交、自定义控件样式、焦点管理和异步验证等内容,适合各水平开发者学习和参考。
325 0

热门文章

最新文章

推荐镜像

更多
  • DNS