Android SwipeRefreshLayout实现工作原理.

2024-05-11 12:58

本文主要是介绍Android SwipeRefreshLayout实现工作原理.,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先这个工具类是由V4包提供的,翻看里面的源码发现,原来这个工具视图[主要探讨视图]是通过自己创建了一个圆形VIew,并在圆形View里面添加了一个旋转的进度Drawable,当然旋转的并不是一个控件,仅仅是一个资源.并通过圆形View去设置了该Drawable,并将圆形图片添加到了SwieRefresh控件上.具体源码如下,通过该源码你可以找到MaterialProgressDrawable,自己手动实现一些进度,大致看了一下算法,还不错,如果你想依赖原生的,你就可以自己创建一个控件去设置这个背景.

mCircleView = new CircleImageView(getContext(), CIRCLE_BG_LIGHT, CIRCLE_DIAMETER/2);mProgress = new MaterialProgressDrawable(getContext(), this);mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);mCircleView.setImageDrawable(mProgress);//设置圆形进度资源mCircleView.setVisibility(View.GONE);addView(mCircleView);
然后 MaterialProgressDrawable提供一些方便的api,
<pre name="code" class="java">setAlpha(float); // 设置渐变
showArrow(boolean);// 设置箭头
setStartEndTrim(float,float); // 开始和结束的长度这里默认是0.8f,参考源码:mProgress.setStartEndTrim(0f, Math.min(MAX_PROGRESS_ANGLE, strokeStart));
setArrowScale(float); //缩放箭头

/*关键的旋转代码*/
 
<pre name="code" class="java">float rotation = (-0.25f + .4f * adjustedPercent + tensionPercent * 2) * .5f; // ACTION_MOVE的时候计算的一个旋转值,然后给该设置,当然你也可以自己定义.
mProgress.setProgressRotation(rotation);// 设置旋转值.
mProgress.start();//开始旋转
mProgress.stop(); // 结束旋转.

 

下面是MaterialProcessDrawable部分算法源码:

// The minProgressArc is calculated from 0 to create an// angle that// matches the stroke width.final float minProgressArc = (float) Math.toRadians(ring.getStrokeWidth() / (2 * Math.PI * ring.getCenterRadius()));final float startingEndTrim = ring.getStartingEndTrim();final float startingTrim = ring.getStartingStartTrim();final float startingRotation = ring.getStartingRotation();// Offset the minProgressArc to where the endTrim is// located.final float minArc = MAX_PROGRESS_ARC - minProgressArc;final float endTrim = startingEndTrim + (minArc* START_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));ring.setEndTrim(endTrim);final float startTrim = startingTrim + (MAX_PROGRESS_ARC* END_CURVE_INTERPOLATOR.getInterpolation(interpolatedTime));ring.setStartTrim(startTrim);final float rotation = startingRotation + (0.25f * interpolatedTime);ring.setRotation(rotation);float groupRotation = ((720.0f / NUM_POINTS) * interpolatedTime)+ (720.0f * (mRotationCount / NUM_POINTS));setRotation(groupRotation);//设置旋转值
/***画箭头**/
private void drawTriangle(Canvas c, float startAngle, float sweepAngle, Rect bounds) {if (mShowArrow) {if (mArrow == null) {mArrow = new android.graphics.Path();mArrow.setFillType(android.graphics.Path.FillType.EVEN_ODD);} else {mArrow.reset();}// Adjust the position of the triangle so that it is inset as// much as the arc, but also centered on the arc.float inset = (int) mStrokeInset / 2 * mArrowScale;float x = (float) (mRingCenterRadius * Math.cos(0) + bounds.exactCenterX());float y = (float) (mRingCenterRadius * Math.sin(0) + bounds.exactCenterY());// Update the path each time. This works around an issue in SKIA// where concatenating a rotation matrix to a scale matrix// ignored a starting negative rotation. This appears to have// been fixed as of API 21.mArrow.moveTo(0, 0);mArrow.lineTo(mArrowWidth * mArrowScale, 0);mArrow.lineTo((mArrowWidth * mArrowScale / 2), (mArrowHeight* mArrowScale));mArrow.offset(x - inset, y);mArrow.close();// draw a trianglemArrowPaint.setColor(mColors[mColorIndex]);c.rotate(startAngle + sweepAngle - ARROW_OFFSET_ANGLE, bounds.exactCenterX(),bounds.exactCenterY());c.drawPath(mArrow, mArrowPaint);}}

这儿主要是画进度:

/*** Draw the progress spinner*/public void draw(Canvas c, Rect bounds) {final RectF arcBounds = mTempBounds;arcBounds.set(bounds);arcBounds.inset(mStrokeInset, mStrokeInset);final float startAngle = (mStartTrim + mRotation) * 360;final float endAngle = (mEndTrim + mRotation) * 360;float sweepAngle = endAngle - startAngle;mPaint.setColor(mColors[mColorIndex]);c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);drawTriangle(c, startAngle, sweepAngle, bounds);if (mAlpha < 255) {mCirclePaint.setColor(mBackgroundColor);mCirclePaint.setAlpha(255 - mAlpha);c.drawCircle(bounds.exactCenterX(), bounds.exactCenterY(), bounds.width() / 2,mCirclePaint);}}


 下面是我自己定义的CircleView,算法如下.:

mRefreshStart += mIsStart ? 3 : 10;//计算距离mRefreshStop += mIsStart ? 10 : 3;mRefreshStart = mRefreshStart % 360;//还原位置mRefreshStop = mRefreshStop % 360;int swipe = mRefreshStop - mRefreshStart;swipe = swipe < 0 ? swipe + 360 : swipe; //计算扫过的角度.canvas.drawArc(rectF,mRefreshStart, swipe, false, mOutPaint);//画圆弧.if (swipe >= 330) {//恢复加速mIsStart = false;} else if (swipe <= 10) {//开始加速mIsStart = true;}

GitHub地址:https://github.com/q422013/CircleView


这篇关于Android SwipeRefreshLayout实现工作原理.的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Android中Dialog的使用详解

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

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

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

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