当前位置: 首页 > news >正文

做网站多少钱特惠西宁君博s国外优秀网站案例

做网站多少钱特惠西宁君博s,国外优秀网站案例,百度竞价推广的优势,wordpress上传不了效果图:网上垂直的水波纹进度条很多,但横向的很少,将垂直的水波纹改为水平的还遇到了些麻烦,现在完善后发布出来,希望遇到的人少躺点坑。思路分析整体效果可分为三个,绘制圆角背景和圆角矩形,绘…

效果图:

网上垂直的水波纹进度条很多,但横向的很少,将垂直的水波纹改为水平的还遇到了些麻烦,现在完善后发布出来,希望遇到的人少躺点坑。

思路分析

整体效果可分为三个,绘制圆角背景和圆角矩形,绘制第一条和第二条水波浪,根据自定义进度变化效果。

功能实现

1、绘制圆角背景和圆角矩形边框

圆角矩形边框:

private RectF rectBorder;
if (rectBorder == null) {rectBorder = new RectF(0.5f * dp1, 0.5f * dp1, waveActualSizeWidth - 0.5f * dp1, waveActualSizeHeight - 0.5f * dp1);
}
canvas.drawRoundRect(rectBorder, dp27, dp27, borderPaint);

我们创建一个新的画布,然后在画布里画上圆角矩形背景和第一条和第二条水波浪:

//这里用到了缓存 根据参数创建新位图
if (circleBitmap == null) {circleBitmap = Bitmap.createBitmap(waveActualSizeWidth, waveActualSizeHeight, Bitmap.Config.ARGB_8888);
}
//以该bitmap为底创建一块画布
if (bitmapCanvas == null) {bitmapCanvas = new Canvas(circleBitmap);
}
// 圆角矩形背景,为了能让波浪填充完整个圆形背景
if (rectBg == null) {rectBg = new RectF(0, 0, waveActualSizeWidth, waveActualSizeHeight);
}
bitmapCanvas.drawRoundRect(rectBg, dp27, dp27, backgroundPaint);
//裁剪图片
canvas.drawBitmap(circleBitmap, 0, 0, null);

2、通过贝塞尔曲线实现双水波

1)实现第一条水波

/*** 绘制波浪线*/
private Path canvasWavePath() {//要先清掉路线wavePath.reset();//起始点移至(0,0) p0 -p1 的高度随着进度的变化而变化wavePath.moveTo((currentPercent) * waveActualSizeWidth, -moveDistance);//最多能绘制多少个波浪//其实也可以用 i < getWidth() ;i+=waveLength来判断 这个没那么完美//绘制p0 - p1 绘制波浪线 这里有一段是超出View的,在View右边距的右边 所以是* 2for (int i = 0; i < waveNumber * 2; i++) {wavePath.rQuadTo(waveHeight, waveLength / 2, 0, waveLength);wavePath.rQuadTo(-waveHeight, waveLength / 2, 0, waveLength);}//连接p1 - p2wavePath.lineTo(0, waveActualSizeHeight);//连接p2 - p0wavePath.lineTo(0, 0);//封闭起来填充wavePath.close();return wavePath;
}

moveDistance为水波垂直方向移动的距离。

waveLength为水波长度,一个上弧加一个下弧为一个波长。

path的起始点为(0,0)可根据进度动态改变,然后循环画曲线,长度是有几个波浪就是多长,然后连接到view高度的位置,最后到(0,0),形成一个封闭的区域,这样就实现了一个填充的水波效果。

2)绘制第二条水波,第二条水波和第一条类似,只是起始点变了:

/*** 绘制第二层波浪*/
private Path canvasSecondPath() {secondWavePath.reset();//初始点移动到下方secondWavePath.moveTo((currentPercent) * waveActualSizeWidth, waveActualSizeHeight + moveDistance);for (int i = 0; i < waveNumber * 2; i++) {secondWavePath.rQuadTo(waveHeight, -waveLength / 2, 0, -waveLength);secondWavePath.rQuadTo(-waveHeight, -waveLength / 2, 0, -waveLength);}secondWavePath.lineTo(0, 0);secondWavePath.lineTo(0, waveActualSizeHeight);secondWavePath.close();return secondWavePath;
}

3、设置动画使进度和水波纹变化

/*** 设置进度** @param currentProgress 进度* @param duration        达到进度需要的时间*/
public void setProgress(int currentProgress, long duration, AnimatorListenerAdapter listenerAdapter) {float percent = currentProgress * 1f / maxProgress;this.currentProgress = currentProgress;//从0开始变化currentPercent = 0;moveDistance = 0;mProgressAnimator = ValueAnimator.ofFloat(0, percent);//设置动画时间mProgressAnimator.setDuration(duration);//让动画匀速播放,避免出现波浪平移停顿的现象mProgressAnimator.setInterpolator(new LinearInterpolator());mProgressAnimator.addUpdateListener(listener);mProgressAnimator.addListener(listenerAdapter);mProgressAnimator.start();// 波浪线startWaveAnimal();
}/*** 波浪动画*/
private void startWaveAnimal() {//动画实例化if (waveProgressAnimator == null) {waveProgressAnimator = new WaveProgressAnimal();//设置动画时间waveProgressAnimator.setDuration(2000);//设置循环播放waveProgressAnimator.setRepeatCount(Animation.INFINITE);//让动画匀速播放,避免出现波浪平移停顿的现象waveProgressAnimator.setInterpolator(new LinearInterpolator());//当前视图开启动画this.startAnimation(waveProgressAnimator);}
}

其中波浪动画是通过改变moveDistance的值改变纵坐标达到,进度主要是通过改变百分比currentPercent改变波浪的横坐标达到。

完整源码:

/*** 横向双水波浪进度条** @author jingbin**/
public class HorizontalWaveProgressView extends View {//绘制波浪画笔private Paint wavePaint;//绘制波浪Pathprivate Path wavePath;//波浪的宽度private final float waveLength;//波浪的高度private final float waveHeight;//波浪组的数量 一个波浪是一低一高private int waveNumber;//自定义View的波浪宽高private int waveDefaultWidth;private int waveDefaultHeight;//测量后的View实际宽高private int waveActualSizeWidth;private int waveActualSizeHeight;//当前进度值占总进度值的占比private float currentPercent;//当前进度值private int currentProgress;//进度的最大值private int maxProgress;//动画对象private WaveProgressAnimal waveProgressAnimator;private ValueAnimator mProgressAnimator;private ValueAnimator mEndAnimator;//波浪平移距离private float moveDistance = 0;//圆形背景画笔private Paint backgroundPaint;// 边框private Paint borderPaint;//bitmapprivate Bitmap circleBitmap;//bitmap画布private Canvas bitmapCanvas;//波浪颜色private final int wave_color;//圆形背景进度框颜色private final int backgroundColor;//进度条显示值监听接口private UpdateTextListener updateTextListener;//是否绘制双波浪线private boolean isShowSecondWave;//第二层波浪的颜色private final int secondWaveColor;//边框色private final int borderColor;//第二层波浪的画笔private Paint secondWavePaint;private Path secondWavePath;private int dp1;// 圆角角度private int dp27;public HorizontalWaveProgressView(Context context) {this(context, null);}public HorizontalWaveProgressView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public HorizontalWaveProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//获取attrs文件下配置属性TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorizontalWaveProgressView);//获取波浪宽度 第二个参数,如果xml设置这个属性,则会取设置的默认值 也就是说xml没有指定wave_length这个属性,就会取Density.dip2px(context,25)waveLength = typedArray.getDimension(R.styleable.HorizontalWaveProgressView_wave_length, DensityUtil.dip2px(context, 25));//获取波浪高度waveHeight = typedArray.getDimension(R.styleable.HorizontalWaveProgressView_wave_height, DensityUtil.dip2px(context, 5));//获取波浪颜色wave_color = typedArray.getColor(R.styleable.HorizontalWaveProgressView_wave_color, Color.parseColor("#B76EFF"));//圆形背景颜色backgroundColor = typedArray.getColor(R.styleable.HorizontalWaveProgressView_wave_background_color, Color.WHITE);//当前进度currentProgress = typedArray.getInteger(R.styleable.HorizontalWaveProgressView_currentProgress, 0);//最大进度maxProgress = typedArray.getInteger(R.styleable.HorizontalWaveProgressView_maxProgress, 100);//是否显示第二层波浪isShowSecondWave = typedArray.getBoolean(R.styleable.HorizontalWaveProgressView_second_show, false);//第二层波浪的颜色secondWaveColor = typedArray.getColor(R.styleable.HorizontalWaveProgressView_second_color, Color.parseColor("#DEBCFF"));//边框色borderColor = typedArray.getColor(R.styleable.HorizontalWaveProgressView_border_color, Color.parseColor("#DEBCFF"));//记得把TypedArray回收//程序在运行时维护了一个 TypedArray的池,程序调用时,会向该池中请求一个实例,用完之后,调用 recycle() 方法来释放该实例,从而使其可被其他模块复用。//那为什么要使用这种模式呢?答案也很简单,TypedArray的使用场景之一,就是上述的自定义View,会随着 Activity的每一次Create而Create,//因此,需要系统频繁的创建array,对内存和性能是一个不小的开销,如果不使用池模式,每次都让GC来回收,很可能就会造成OutOfMemory。//这就是使用池+单例模式的原因,这也就是为什么官方文档一再的强调:使用完之后一定 recycle,recycle,recycletypedArray.recycle();init(context);}/*** 初始化一些画笔路径配置*/private void init(Context context) {//设置自定义View的宽高waveDefaultWidth = DensityUtil.dip2px(context, 152);waveDefaultHeight = DensityUtil.dip2px(context, 40);dp1 = DensityUtil.dip2px(getContext(), 1);dp27 = DensityUtil.dip2px(getContext(), 27);wavePath = new Path();wavePaint = new Paint();//设置画笔为取交集模式wavePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//设置波浪颜色wavePaint.setColor(wave_color);//设置抗锯齿wavePaint.setAntiAlias(true);//矩形背景backgroundPaint = new Paint();backgroundPaint.setColor(backgroundColor);backgroundPaint.setAntiAlias(true);//边框borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);borderPaint.setColor(borderColor);borderPaint.setAntiAlias(true);borderPaint.setStrokeWidth(dp1);borderPaint.setStyle(Paint.Style.STROKE);if (isShowSecondWave) {//是否绘制双波浪线secondWavePath = new Path();//初始化第二层波浪画笔secondWavePaint = new Paint();secondWavePaint.setColor(secondWaveColor);secondWavePaint.setAntiAlias(true);//因为要覆盖在第一层波浪上,且要让半透明生效,所以选SRC_ATOP模式secondWavePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));}//占比一开始设置为0currentPercent = currentProgress * 1f / maxProgress;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//这里用到了缓存 根据参数创建新位图circleBitmap = Bitmap.createBitmap(waveActualSizeWidth, waveActualSizeHeight, Bitmap.Config.ARGB_8888);//以该bitmap为底创建一块画布bitmapCanvas = new Canvas(circleBitmap);// 绘制背景,为了能让波浪填充完整个圆形背景RectF rectBg = new RectF(0, 0, waveActualSizeWidth, waveActualSizeHeight);bitmapCanvas.drawRoundRect(rectBg, dp27, dp27, backgroundPaint);if (isShowSecondWave) {//绘制第二层波浪bitmapCanvas.drawPath(canvasSecondPath(), secondWavePaint);}
//绘制波浪形bitmapCanvas.drawPath(canvasWavePath(), wavePaint);//裁剪图片canvas.drawBitmap(circleBitmap, 0, 0, null);// 绘制边框RectF rectBorder = new RectF(0.5f * dp1, 0.5f * dp1, waveActualSizeWidth - 0.5f * dp1, waveActualSizeHeight - 0.5f * dp1);canvas.drawRoundRect(rectBorder, dp27, dp27, borderPaint);}/*** 绘制波浪线*/private Path canvasWavePath() {//要先清掉路线wavePath.reset();//起始点移至(0,0) p0 -p1 的高度随着进度的变化而变化wavePath.moveTo((currentPercent) * waveActualSizeWidth, -moveDistance);
//        wavePath.moveTo(-moveDistance,(1-currentPercent) * waveActualSize);//最多能绘制多少个波浪//其实也可以用 i < getWidth() ;i+=waveLength来判断 这个没那么完美//绘制p0 - p1 绘制波浪线 这里有一段是超出View的,在View右边距的右边 所以是* 2for (int i = 0; i < waveNumber * 2; i++) {wavePath.rQuadTo(waveHeight, waveLength / 2, 0, waveLength);wavePath.rQuadTo(-waveHeight, waveLength / 2, 0, waveLength);}//连接p1 - p2wavePath.lineTo(waveActualSizeWidth, waveActualSizeHeight);//连接p2 - p3wavePath.lineTo(0, waveActualSizeHeight);//连接p3 - p0 p3-p0d的高度随着进度变化而变化wavePath.lineTo(0, 0);//封闭起来填充wavePath.close();return wavePath;}/*** 绘制第二层波浪方法*/private Path canvasSecondPath() {float secondWaveHeight = waveHeight;secondWavePath.reset();//移动到右上方,也就是p1点secondWavePath.moveTo((currentPercent) * waveActualSizeWidth, waveActualSizeHeight + moveDistance);//p1 - p0for (int i = 0; i < waveNumber * 2; i++) {secondWavePath.rQuadTo(secondWaveHeight, -waveLength / 2, 0, -waveLength);secondWavePath.rQuadTo(-secondWaveHeight, -waveLength / 2, 0, -waveLength);}//p3-p0的高度随着进度变化而变化secondWavePath.lineTo(0, 0);//连接p3 - p2secondWavePath.lineTo(0, waveActualSizeHeight);secondWavePath.lineTo(waveActualSizeHeight, waveActualSizeWidth);//连接p2 - p1secondWavePath.lineTo(waveActualSizeWidth, waveActualSizeHeight + moveDistance);//封闭起来填充secondWavePath.close();return secondWavePath;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = measureSize(waveDefaultWidth, widthMeasureSpec);int height = measureSize(waveDefaultHeight, heightMeasureSpec);//把View改为正方形setMeasuredDimension(width, height);//waveActualSize是实际的宽高waveActualSizeWidth = width;waveActualSizeHeight = height;//Math.ceil(a)返回求不小于a的最小整数// 举个例子:// Math.ceil(125.9)=126.0// Math.ceil(0.4873)=1.0// Math.ceil(-0.65)=-0.0//这里是调整波浪数量 就是View中能容下几个波浪 用到ceil就是一定让View完全能被波浪占满 为循环绘制做准备 分母越小就约精准waveNumber = (int) Math.ceil(Double.parseDouble(String.valueOf(waveActualSizeHeight / waveLength / 2)));}/*** 返回指定的值** @param defaultSize 默认的值* @param measureSpec 模式*/private int measureSize(int defaultSize, int measureSpec) {int result = defaultSize;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);//View.MeasureSpec.EXACTLY:如果是match_parent 或者设置定值就//View.MeasureSpec.AT_MOST:wrap_contentif (specMode == MeasureSpec.EXACTLY) {result = specSize;} else if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}return result;}//新建一个动画类public class WaveProgressAnimal extends Animation {//在绘制动画的过程中会反复的调用applyTransformation函数,// 每次调用参数interpolatedTime值都会变化,该参数从0渐 变为1,当该参数为1时表明动画结束@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {super.applyTransformation(interpolatedTime, t);//左边的距离moveDistance = interpolatedTime * waveNumber * waveLength * 2;//重新绘制invalidate();}}/*** 直接结束** @param duration 结束时间*/public void setProgressEnd(long duration, AnimatorListenerAdapter listenerAdapter) {// 如果是100会不满,因为在波动if (currentProgress == maxProgress) {// 到底了就从头开始currentPercent = 0;}mEndAnimator = ValueAnimator.ofFloat(currentPercent, 1.1f);mEndAnimator.setInterpolator(new DecelerateInterpolator());mEndAnimator.setDuration(duration);mEndAnimator.addUpdateListener(listener);mEndAnimator.addListener(listenerAdapter);mEndAnimator.start();// 波浪线startWaveAnimal();}/*** 设置进度** @param currentProgress 进度* @param duration        达到进度需要的时间*/public void setProgress(int currentProgress, long duration, AnimatorListenerAdapter listenerAdapter) {float percent = currentProgress * 1f / maxProgress;this.currentProgress = currentProgress;//从0开始变化currentPercent = 0;moveDistance = 0;mProgressAnimator = ValueAnimator.ofFloat(0, percent);//设置动画时间mProgressAnimator.setDuration(duration);//让动画匀速播放,避免出现波浪平移停顿的现象mProgressAnimator.setInterpolator(new LinearInterpolator());mProgressAnimator.addUpdateListener(listener);mProgressAnimator.addListener(listenerAdapter);mProgressAnimator.start();// 波浪线startWaveAnimal();}/*** 波浪动画*/private void startWaveAnimal() {//动画实例化if (waveProgressAnimator == null) {waveProgressAnimator = new WaveProgressAnimal();//设置动画时间waveProgressAnimator.setDuration(2000);//设置循环播放waveProgressAnimator.setRepeatCount(Animation.INFINITE);//让动画匀速播放,避免出现波浪平移停顿的现象waveProgressAnimator.setInterpolator(new LinearInterpolator());//当前视图开启动画this.startAnimation(waveProgressAnimator);}}/*** 进度的监听*/ValueAnimator.AnimatorUpdateListener listener = new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {// 当前进度百分比,[0,1]currentPercent = (float) animation.getAnimatedValue();//这里直接根据进度值显示if (updateTextListener != null) {updateTextListener.updateText(currentPercent, maxProgress);}}};public interface UpdateTextListener {/*** 提供接口 给外部修改数值样式 等** @param currentPercent 当前进度百分比* @param maxProgress    进度条的最大数值*/void updateText(float currentPercent, float maxProgress);}/*** 设置监听*/public void setUpdateTextListener(UpdateTextListener updateTextListener) {this.updateTextListener = updateTextListener;}/*** 停止动画,销毁对象*/public void stopAnimal() {if (waveProgressAnimator != null) {waveProgressAnimator.cancel();}if (mProgressAnimator != null && mProgressAnimator.isStarted()) {mProgressAnimator.removeAllListeners();mProgressAnimator.cancel();}if (mEndAnimator != null && mEndAnimator.isStarted()) {mEndAnimator.removeAllListeners();mEndAnimator.cancel();}}
}
http://www.yayakq.cn/news/259932/

相关文章:

  • 绍兴网站建设公司电话开发公司项目管理部门获奖主持词
  • 德化住房和城乡建设网站乐云seo快速网站建设
  • 用html编写淘宝网站怎么做长沙品牌网站建设实力强
  • 海口模板建站哪家好wordpress英文主题 汉化
  • 广东工程承包网站聊城网站建设设计实力公司
  • 网站如何建数据库如何利用网站做产品推广
  • 网站软件下载大全最大的开源网站
  • 山东手机版建站系统哪家好模板建站常规流程
  • 岳阳做网站公司赫山区网站建设
  • 做网站哪个系统最好wordpress 纪念爱情
  • 网站欣赏网站建设基本流程教学视频教程
  • 可以做视频的网站网址你会感谢我的
  • 搭建网站seo集团网站设计公司
  • 可以做pos机的网站电气行业网站建设多少钱
  • 网站制作怎样做背景艺术字体在线生成器英文
  • 大气医院网站源码优化算法分类
  • 上海建站网络规划设计师书籍
  • 看公狍和女人做爰网站移动网站建设可信赖
  • 网站项目设计书自己怎么做百度网站
  • 新闻热点事件2020 最新网站seo入门基础教程书籍
  • 紧固件做网站有效果吗义乌网站制作
  • 网站改版的方式大致有wordpress d8主题 4.1
  • 怎么把源码做网站wordpress评论头像添加alt
  • 什么是网站规划计算机网络技术就业方向网站开发
  • 织梦网站栏目对应首页顺电网上商城app
  • 网站前面的logo标志网站推广途径和推广要点有哪些?
  • 哪个网站内链建设好石柱网站制作
  • 怎么用php做网站方案那些网站h5做的不错
  • 网站广告投放收费标准wordpress文章详情模版替换
  • 不同类型的网站我要自学网python