Android 自定义控件 loding小球

2024-08-30 16:32

本文主要是介绍Android 自定义控件 loding小球,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以下为参照博客    http://blog.csdn.net/guimianhao9833/article/details/74858472 


首先看下效果图:

步骤:
1.继承view,并需要三个构造函数。
public MyView(Context context) {//注意不要默认实现,记得修改。
    this(context, null);
}public MyView(Context context, AttributeSet attrs) {//注意不要默认实现,记得修改。
    this(context, attrs, 0);
}public MyView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
    //初始化工作
    init(context, attrs);
}
初始化工作init:
1)在attrs.xml中定义控件需要的属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView">
        <attr name="color" format="color"/>
        <attr name="text" format="string"/>
    </declare-styleable>
</resources>
2)自定义控件一般都需要定义相关的属性,我们获取它并对它进行相关的设置;
由效果图可知,这个自定义控件需要定义一个画笔用来画图形路径;
需要定义一个画笔用来画文字;
需要Path用来定义闭合波浪路径;
为了实现控件无线循环的动画效果,需要对其进行相关的监听动作并实时刷新。
private void init(Context context, AttributeSet attrs) {//1.定义需要的属性
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
    //颜色和文字
    color = a.getColor(R.styleable.MyView_color, Color.rgb(238,121,66));
    text = a.getString(R.styleable.MyView_text);
    //记得调用这个方法回收
    a.recycle();
    //2.1定义图形及路径填充画笔的相关值(抗锯齿、填充、防抖动)
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setColor(color);
    mPaint.setDither(true);
    //2.2定义文字画笔的相关值(抗锯齿、白色、粗体)
    textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    textPaint.setColor(Color.WHITE);
    textPaint.setTypeface(Typeface.DEFAULT_BOLD);
    //2.3定义闭合波浪路径
    path = new Path();
    //3.实现无线循环的动画效果
    //ValueAnimator定时器,属性动画ObjectAnimator就是它的一个子类
    ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    //让动画无限重复,每次从头开始,一个周期1000毫秒
    animator.setDuration(1000);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.setRepeatMode(ValueAnimator.RESTART);
    //补上一个线性插值器,使得动画流畅
    animator.setInterpolator(new LinearInterpolator());
    //监听获得过程值,实时进行刷新
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Override
        public void onAnimationUpdate(ValueAnimator animation) {currentPercent = animation.getAnimatedFraction();
            //刷新
            invalidate();
        }});
    //动画开始
    animator.start();
}
 2.onDraw方法,重中之重!
绘制流程:

1)绘制底部蓝色的文字
2)绘制闭合的波浪路径,颜色为蓝色
3)绘制白色的文字
4)根据已有的波浪路径去裁剪文字,使得文字上半部门为蓝色,文字下半部门为白色
(因为先绘制在下部,后绘制的在上部)
5)在已有的画布canvas上画一个圆,也就是裁剪成圆形
@Override
protected void onDraw(Canvas canvas) {//super.onDraw(canvas);
    //1.画底部蓝色的字
    textPaint.setColor(color);
    drawCenterText(canvas, textPaint, "");
    //2.画上层白色的字
    textPaint.setColor(Color.WHITE);
    //3.生成闭合波浪路径
    path = getActionPath(currentPercent);
    //4.剪裁文字
    canvas.clipPath(path);
    //5.剪裁成圆形(SRC 源像素)
    canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mPaint);
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    //6.画波浪(DST 目标像素)
    canvas.drawPath(path, mPaint);
    mPaint.setXfermode(null);
    drawCenterText(canvas, textPaint, "");
}
生成闭合的波浪路径的方法getActionPath:
这个波浪可以由 二阶贝塞尔曲线。如下的例子,起点为(100,100),然后移动相对于起点的两个位置变化为(150,0),(200,100)。
Path path=new Path();
path.moveTo(100,100);
path.rQuadTo(50,-100,100,0);
               图解:

1)画两个周期的波浪
2)画右侧的直线
3)画下边的直线
private Path getActionPath(float percent) {Path path = new Path();
    int x = -mWidth;
    //1.当前x点坐标(根据动画进度水平推移,一个动画周期推移的距离为一个mWidth    x += percent * mWidth;
    //2.波形的起点
    path.moveTo(x, mHeight / 2);
    //控制点的相对宽度
    int kongzhiWidth = mWidth / 4;
    //控制点的相对高度=mHeight的二十分之3
    int kongzhiHeight = mHeight / 20 * 3;
    //3.画第一个周期,一个周期为一上一下
    path.rQuadTo(kongzhiWidth, kongzhiHeight, kongzhiWidth * 2, 0);
    path.rQuadTo(kongzhiWidth, -kongzhiHeight, kongzhiWidth * 2, 0);
    //画第二个周期,如此循环下去
    path.rQuadTo(kongzhiWidth, kongzhiHeight, kongzhiWidth * 2, 0);
    path.rQuadTo(kongzhiWidth, -kongzhiHeight, kongzhiWidth * 2, 0);
    //4.画右侧的直线
    path.lineTo(x + mWidth * 2, mHeight);
    //5.画下边的直线
    path.lineTo(x, mHeight);
    //自动闭合补出左边的直线
    path.close();
    return path;
}
   画中间的文字drawCenterText:
private void drawCenterText(Canvas canvas, Paint textPaint, String text) {//画一个规定位置的矩形
    Rect rect = new Rect(0, 0, mWidth, mHeight);
    //由于默认是位于左边的,所以这样设置到中间来。
    textPaint.setTextAlign(Paint.Align.CENTER);
    Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
    float top = fontMetrics.top;
    float bottom = fontMetrics.bottom;

    int centerY = (int) (rect.centerY() - top / 2 - bottom / 2);
    canvas.drawText(text, rect.centerX(), centerY, textPaint);
}
3.onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    if (widthMode == MeasureSpec.EXACTLY) {mWidth = widthSize;
    }if (heightMode == MeasureSpec.EXACTLY) {mHeight = heightSize;
    }setMeasuredDimension(mWidth, mHeight);
    textSize = mWidth / 2;
    textPaint.setTextSize(textSize);
}
自定义控件,要好好学哦。

这篇关于Android 自定义控件 loding小球的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1121338

相关文章

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

如何自定义Nginx JSON日志格式配置

《如何自定义NginxJSON日志格式配置》Nginx作为最流行的Web服务器之一,其灵活的日志配置能力允许我们根据需求定制日志格式,本文将详细介绍如何配置Nginx以JSON格式记录访问日志,这种... 目录前言为什么选择jsON格式日志?配置步骤详解1. 安装Nginx服务2. 自定义JSON日志格式各

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式