Android 绘图进阶:仿360水纹进度球(可动正余弦曲线+xfermode)

这里写图片描述
  在 Android 绘图基础:Path(绘制三角形、贝塞尔曲线、正余弦) 这篇博客中我们已经实现了可动的正余弦曲线,在学习了PorterDuff的Xfermode设置画笔风格后我们只需要在可动正余弦曲线的基础上进行修改即可。

思路

  要在上次可动正余弦曲线的基础上实现仿360的水纹进度球,最不太好做的是将我们的正余弦曲线进行闭合。也就是下面这部分代码。

mpath.reset();
        //f要放置在前面
        //如果写成currentprogress/100*300f的话  前半部分都是int值计算后已经是0再*300就没用了
        //可以先将450-(currentprogress/100f*300)
        //修改为固定高度比如200进行查看水纹样式
        mpath.moveTo(500,450-(currentprogress/100f*300));
        mpath.lineTo(500,450);
        //450-currentprogress/maxprogress*300f
        mpath.lineTo(count,450);
        mpath.lineTo(count,450-(currentprogress/100f*300));
        for(int i=0;i<10;i++){
            //rQuadTo
            mpath.rQuadTo(20, size, 40, 0);
            mpath.rQuadTo(20, -size, 40, 0);    
        }       

        mcanvas_bitmap.drawPath(mpath, Paintpath);

  根据代码的坐标点,可以先将450-(currentprogress/100f*300)//修改为固定高度比如200进行查看水纹样式,,之后尝试划线进行路径的闭合。
备注:count是为了值水纹可动的,实际上就是将正余弦曲线向右进行拖拽。
2、设置画笔风格Xfermode为SRC_IN就可以了。

Paintpath.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

调用

mcanvas_bitmap.drawPath(mpath, Paintpath);

3、最后在MainActivity中控制currentprogress就OK了。
在MyPathView 中给出currentprogress的set/get方法,通过Mainactivity中的Hamdler进行改变:就可以了

mypathview.setCurrentprogress(progress);

代码展示

MyPathView (实现水纹闭合+画笔样式SRC_IN)

public class MyPathView extends View{
    private static final int A9DBF6 = 0;
    private int width;
    private int height;

    private Paint Paintpath;
    private Path mpath;
    private Paint PaintText;
    private Paint Paintpoint;
    private int count;
    private int size;
    private Bitmap mbitmap;
    private Canvas mcanvas_bitmap;
    private Paint paintnew;
    private int maxprogress=100;
    private int currentprogress;
    private Handler mhanHandler=new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case 0x23:
                count++;
            if(count>=80){
                count=0;
            }
            size++;
            if(size>10){
                size=5;
            }
            mhanHandler.sendEmptyMessageDelayed(0x23, 200);
                invalidate();
                break;

            default:
                break;
            }

        };
    };


    public int getCurrentprogress() {

        return currentprogress;
    }
    public void setCurrentprogress(int currentprogress) {
        this.currentprogress = currentprogress;
        invalidate();
    }
    public MyPathView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Paintpath=new Paint();
        Paintpath.setColor(Color.BLUE);
        Paintpath.setAntiAlias(true);
    //  Paintpath.setStrokeWidth(5);
        Paintpath.setStyle(Style.FILL);
        Paintpath.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));


        PaintText=new Paint();
        PaintText.setColor(Color.YELLOW);
        PaintText.setAntiAlias(true);       
        PaintText.setTextSize(30);
        PaintText.setTextAlign(Align.CENTER);

        mpath=new Path();
        Paintpoint=new Paint();
        Paintpoint.setColor(Color.RED);
    //  Paintpoint.setStrokeWidth(20);
        Paintpoint.setStyle(Style.FILL);
        paintnew=new Paint();
        paintnew.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mhanHandler.sendEmptyMessage(0x23);


    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.LTGRAY);
        mpath.reset();
        mcanvas_bitmap.drawCircle(300, 300, 150, Paintpoint);

        mpath.reset();
        //f要放置在前面
        //如果写成currentprogress/100*300f的话  前半部分都是int值计算后已经是0再*300就没用了
        mpath.moveTo(500,450-(currentprogress/100f*300));
        mpath.lineTo(500,450);
        //450-currentprogress/maxprogress*300f
        mpath.lineTo(count,450);
        mpath.lineTo(count,450-(currentprogress/100f*300));
        for(int i=0;i<10;i++){
            //rQuadTo
            mpath.rQuadTo(20, size, 40, 0);
            mpath.rQuadTo(20, -size, 40, 0);    
        }       

        mcanvas_bitmap.drawPath(mpath, Paintpath);

    //  mcanvas_bitmap.drawCircle(300, 300, 150,paintnew );

        canvas.drawBitmap(mbitmap, 0, 0, null);
        canvas.drawText((float)currentprogress/maxprogress*100f+"",300,300, PaintText);


    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        mbitmap=Bitmap.createBitmap(width, height, Config.ARGB_8888);
        mcanvas_bitmap=new Canvas(mbitmap);
    }
}

MainActivity(通过Handler修改currentprogress)

注:在布局中给出MyPathView 的id,通过id获得对象,修改currentprogress值

public class MainActivity_path extends Activity implements OnClickListener{
    private Button mbtn_pathview;
    private MyPathView mypathview;
     private int progress;
        private Handler mhanHandler=new Handler(){
            public void handleMessage(android.os.Message msg) {
                switch (msg.what) {
                case 0x24:
                    progress++;
                    if(progress<=100){
                        mypathview.setCurrentprogress(progress);
                        mhanHandler.sendEmptyMessageDelayed(0x24, 200);
                    }
                    break;

                default:
                    break;
                }

            };
        };
  @Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.path_view);
    mbtn_pathview=(Button) findViewById(R.id.btn_pathview);
    mypathview=(MyPathView) findViewById(R.id.mypathview);
    mbtn_pathview.setOnClickListener(this);
}
@Override
public void onClick(View v) {
    mhanHandler.sendEmptyMessageDelayed(0x24, 1000);

}
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值