visited 13 states (5.77%)
Create your own visited map of The World or Triposo world travel guide for Android

2014-10-01

Android應用程式以path元件畫圖,其中quadTo與lineTo的比較

當我們需要在銀幕上畫線,常常會用到Path元件,而Path元件的lineTo和quadTo這兩種方法所繪製出的線段形式是不一樣的,主要差別為,

Path->quadTo(float x1, float y1, float x2, float y2):      

example:
MainActivity:

package com.feixun.hu.pt;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.Window;  
import android.view.WindowManager;  
  
public class MainActivity extends Activity  
{  
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        //setContentView(new MySurfaceView(this));  
        //setContentView(new DrawingWithBezier(this));  
        setContentView(new DrawingWithoutBezier(this));        
    }  
}

QUADTO.java:

package com.feixun.hu.pt;  
  
import android.content.Context;  
import android.gesture.GestureStroke;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.Path;  
import android.graphics.Rect;  
import android.graphics.Paint.Style;  
import android.view.MotionEvent;  
import android.view.View;  
import android.widget.Toast;  
  
public class DrawingWithBezier extends View  
{  
    private float mX;  
    private float mY;  
  
    private final Paint mGesturePaint = new Paint();  
    private final Path mPath = new Path();  
      
    public DrawingWithBezier(Context context)  
    {  
        super(context);  
        mGesturePaint.setAntiAlias(true);  
        mGesturePaint.setStyle(Style.STROKE);  
        mGesturePaint.setStrokeWidth(5);  
        mGesturePaint.setColor(Color.WHITE);  
    }  
  
    @Override  
    public boolean onTouchEvent(MotionEvent event)  
    {  
        // TODO Auto-generated method stub  
        switch (event.getAction())  
        {  
            case MotionEvent.ACTION_DOWN:  
                touchDown(event);  
                 break;  
            case MotionEvent.ACTION_MOVE:  
                touchMove(event);  
        }  
        //重新繪圖
        invalidate();  
        return true;  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas)  
    {  
        // TODO Auto-generated method stub  
        super.onDraw(canvas);  
        //以畫布繪圖
        canvas.drawPath(mPath, mGesturePaint);  
    }  
  
    //點擊觸控銀幕時的反應
    private void touchDown(MotionEvent event)  
    {  
        
        //mPath.rewind();  
        //重新設定繪製的線段  
        mPath.reset();  
        float x = event.getX();  
        float y = event.getY();  
          
        mX = x;  
        mY = y;  
        //畫線起點 
        mPath.moveTo(x, y);  
    }  
      
    //手指在觸控銀幕上滑動時的動作  
    private void touchMove(MotionEvent event)  
    {  
        final float x = event.getX();  
        final float y = event.getY();  
  
        final float previousX = mX;  
        final float previousY = mY;  
  
        final float dx = Math.abs(x - previousX);  
        final float dy = Math.abs(y - previousY);  
          
        //兩點之間的距離大於等於3時,產生貝塞爾繪製曲線
        if (dx >= 3 || dy >= 3)  
        {  
            //設置貝塞爾曲線的操作點為起點和終點的一半  
            float cX = (x + previousX) / 2;  
            float cY = (y + previousY) / 2;  
  
            //二次貝塞爾,實現平滑曲線;previousX, previousY為操作點,cX, cY為終點
            mPath.quadTo(previousX, previousY, cX, cY);  
  
            //第二次執行時,第一次結束使用的座標值將作為第二次使用的初始座標
            mX = x;  
            mY = y;  
        }  
    }  
      
}



此方式不僅畫一條線甚至是畫弧線時會形成平滑的曲線,該曲線又稱為「貝塞爾曲線」(Bezier curve),其中,x1,y1為控制點的坐標值,x2,y2為終點的坐標值。貝塞爾曲線的形成,就比如我們把一條橡皮筋拉直,橡皮筋的頭尾部對應起點和終點,然後從拉直的橡皮筋中選擇任意一點(除頭尾對應的點外)扯動橡皮筋形成的彎曲形狀,而那個扯動橡皮筋的點就是控制點。

Path->lineTo(float x, float y) :

example:
MainActivity:

package com.feixun.hu.pt;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.Window;  
import android.view.WindowManager;  
  
public class MainActivity extends Activity  
{  
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        //setContentView(new MySurfaceView(this));  
        //setContentView(new DrawingWithBezier(this));  
        setContentView(new DrawingWithoutBezier(this));        
    }  
} 

LINETO.java

package com.feixun.hu.pt;  
  
import android.content.Context;  
import android.graphics.Bitmap;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.Path;  
import android.graphics.Bitmap.Config;  
import android.graphics.Paint.Style;  
import android.view.MotionEvent;  
import android.view.View;  
import android.widget.Toast;  
  
public class DrawingWithoutBezier extends View  
{  
    private float mX;  
    private float mY;  
  
    private final Paint mGesturePaint = new Paint();  
    private final Path mPath = new Path();  
      
    public DrawingWithoutBezier(Context context)  
    {  
        super(context);  
        mGesturePaint.setAntiAlias(true);  
        mGesturePaint.setStyle(Style.STROKE);  
        mGesturePaint.setStrokeWidth(5);  
        mGesturePaint.setColor(Color.WHITE);  
    }  
  
    @Override  
    public boolean onTouchEvent(MotionEvent event)  
    {  
        // TODO Auto-generated method stub  
        switch (event.getAction())  
        {  
            case MotionEvent.ACTION_DOWN:  
                touchDown(event);  
                 break;  
            case MotionEvent.ACTION_MOVE:  
                touchMove(event);  
        }  
        //重新繪圖  
        invalidate();  
        return true;  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas)  
    {  
        // TODO Auto-generated method stub  
        super.onDraw(canvas);  
        canvas.drawPath(mPath, mGesturePaint);  
    }  
  
    //點擊觸控銀幕時的反應  
    private void touchDown(MotionEvent event)  
    {  
        
        //mPath.rewind();  
        mPath.reset();  
        float x = event.getX();  
        float y = event.getY();  
          
        mX = x;  
        mY = y;  
          
        //畫線起點   
        mPath.moveTo(x, y);  
    }  
      
    //手指在觸控銀幕上滑動時的動作   
    private void touchMove(MotionEvent event)  
    {  
        final float x = event.getX();  
        final float y = event.getY();  
  
        final float previousX = mX;  
        final float previousY = mY;  
  
        final float dx = Math.abs(x - previousX);  
        final float dy = Math.abs(y - previousY);  
          
        //兩點之間的距離大於等於3時,產生貝塞爾繪製曲線 
        if (dx >= 3 || dy >= 3)  
        {  
            //兩點連成直線  
            mPath.lineTo(x, y);  
              
            //第二次執行時,第一次結束使用的座標值將作為第二次使用的初始座標 
            mX = x;  
            mY = y;  
        }  
    }  
      
}




此方法是將畫出兩點之間的線段,直接連成一線

對比前面quadTo方法繪製的S,lineTo繪製的S在彎曲部分很明顯的不能形成平滑的彎曲,會出現明顯的兩點形成一線的突起。可能圖片看的不是清楚,自行運行這個Demo,然後在銀幕上繪製彎曲曲線或者圓,對比他們的形狀區別就一目了然。

這些也是同標籤文章 :

沒有留言: