1. 程式人生 > >Android 繪圖進階:仿360水紋進度球(可動正餘弦曲線+xfermode)

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);

}
}