• 水波浪型的进度加载器


    话不多说,先上效果图



    下面说说原理,基本原理就是不停的绘制一条正弦曲线,曲线方程为y=A*Sin(w*x+fai)+k


    参数A是波浪振幅,A越大,波浪高度越大,基线K是就能直接表现进度,会随着进度的增大而减小

    w参数很重要,表示了图像的紧密程度,设置的小一点就会让图像较为平缓,初相fai,表示当X等于0时候的第一个位置

    在代码中不停的变化这个参数,就可以让这条曲线动起来。


    这个控件里面主要还是涉及三角函数的问题,不是很清楚的可以再研究研究

    这些清楚了,那么代码就好办了


    package customiew;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * 水波纹特效,使用正弦函数
     */
    public class SinWaterwaveView extends View {
    	
    	private float x,y;
    	//正弦函数的参数  y=A*Sin(w*x+fai)+k
    	private float w=(float) (Math.PI/128),fai=0,A=8,k=0;
    	//进度,单位是%
    	private float progress=0;
    	//view的宽高
    	private float width,height;
    	//路径
    	private Path mPath;
    	//波纹画笔和文字画笔
    	private Paint mPaint,textPaint;
    	
    
    	public SinWaterwaveView(Context context) {
    		super(context);
    		// TODO Auto-generated constructor stub
    		
    		init();
    	}
    	
    	
    	
    	public SinWaterwaveView(Context context, AttributeSet attrs,
    			int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    		// TODO Auto-generated constructor stub
    		init();
    	}
    
    
    
    	public SinWaterwaveView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		// TODO Auto-generated constructor stub
    		init();
    	}
    
    
    
    	private void init() {
    		mPaint=new Paint();
    		
    		textPaint=new Paint();
    		textPaint.setColor(0xffffffff);
    		
    		mPaint.setAntiAlias(true);
    		mPaint.setColor(0xaa000077);
    		mPaint.setStyle(Paint.Style.FILL);
    		mPaint.setStrokeWidth(5.0f);
    		mPaint.setTextSize(20);
    		mPath=new Path();
    	}
    	
    	
    	@Override
    	protected void onDraw(Canvas canvas) {
    		// TODO Auto-generated method stub
    		mPath.reset();
    		
    		mPath.moveTo(0, height/2);
    		
    		//根据progress计算k
    		k=height*(1-progress/100)-A;
    		//振幅A随着progress增大而减小
    		A=(float) (8*(1-0.5*progress/100));
    		//绘制完整的一条正弦曲线
    		for (int i = 0; i < width; i++) {
    			y=(float) (k+A*Math.sin(i*w+fai*w));
    			mPath.quadTo(i, y, i+1, y);
    		}
    		//把float型转换为字符串并且去掉小数						
    		String textString=String.valueOf(Math.round(progress*100)/100)+" %";
    		//测量文字宽度,宽度
    		float textwidth= mPaint.measureText(textString);
    		float textheight=mPaint.descent()-mPaint.ascent();
    		//绘制文字,使他在波浪下面并且居中
    		canvas.drawText(textString, (width-textwidth)/2, k+A+textheight, mPaint);
    		
    		mPath.lineTo(width, height);
    		mPath.lineTo(0, height);
    		mPath.close();
    		canvas.drawPath(mPath, mPaint);
    		//如果进度小于100,则不停的刷新页面,使他动起来
    		if (progress<100) {		
    			fai=fai+10;
    			postInvalidateDelayed(30);
    		}
    	}
    	
    	@Override
    	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    		// TODO Auto-generated method stub
    		super.onSizeChanged(w, h, oldw, oldh);
    		width=w;
    		height=h;		
    		k=height;	
    	}
    	/**
    	 * 设置progress进度,更新View,可在子线程中使用
    	 * @param progress
    	 */
    	public void setProgress(float progress) {
    		this.progress=progress;
    	}
    	public float getProgress() {
    		return progress;
    	}
    
    }
    

    代码量也很小,唯一不同的是,在代码里面随着进度增大也减小了A的大小,这样显得波浪越来越平缓,由于draw方法里面不断重绘,使得设置progress的方法在子线程中使用也是没有问题的。


    ok,抛砖引玉,如果大家有更好的实现方式,欢迎分享呀~   

    ^_^


  • 相关阅读:
    OpenGL(二十一) glPolygonOffset设置深度偏移解决z-fighting闪烁问题
    OpenGL(二十) glutSpecialFunc响应键盘方向控制键
    OpenGL(十九) gluOrtho2D、glViewport、glutInitWindowSize区别与关系
    matlab 三维图像的绘制
    matlab 三维图像的绘制
    UIKit和Core Graphics绘图(一)——字符串,线条,矩形,渐变
    jQuery实现密保互斥问题
    Lecture Halls
    POJ 3233 Matrix Power Series (矩阵+二分+二分)
    Wooden Sticks
  • 原文地址:https://www.cnblogs.com/xingyun1992/p/5021087.html
Copyright © 2020-2023  润新知