2013-12-13 5 views
1

Canvas에서 패스를 그리는 데 다음 코드를 사용하고 있습니다. 지금까지 모든 것이 잘 작동하며이 코드를 사용하여 쉽게 패스를 그릴 수 있습니다.캔버스에서 가변 너비로 패스를 그리는 방법

하지만 이제 우리의 요구 사항은 가변 너비로 경로를 그리는 것입니다. 즉, 사용자가 적용한 압력을 기반으로 사용자가 그리는 경로를 의미합니다. 사용자가 가벼운 압력을 가하면 경로가 얇아지며 사용자가 높은 압력을 가하면 통로가 두꺼워 질 것입니다. 지금까지 나는 가변 너비로 도출 경로를 도출했지만 그려진 선은 매끄럽지 않습니다. 왜 그런 일이 벌어지는가? 내 코드에서 놓칠만한 것이있다.

도와주게 도와주세요. 나는 폭

public class FingerPaint extends GraphicsActivity 
{ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(new MyView(this)); 
    } 

    public void colorChanged(int color) 
    { 

    } 

    public class MyView extends View 
    { 
     private static final float STROKE_WIDTH = 5f;  

     private Paint paint = new Paint(); 

     private Path mPath = new Path(); 
     ArrayList<Path> mPaths = new ArrayList<Path>(); 

     ArrayList<Integer> mStrokes = new ArrayList<Integer>(); 

     private float lastTouchX; 
     private float lastTouchY; 
     private final RectF dirtyRect = new RectF(); 

     private int lastStroke = -1; 
     int variableWidthDelta = 0; 

     private float   mX, mY; 

     private static final float  TOUCH_TOLERANCE = 4; 

     public MyView(Context context) 
     { 
      super(context); 

      paint.setAntiAlias(true); 
      paint.setDither(true); 
      paint.setStyle(Paint.Style.STROKE); 
      paint.setStrokeJoin(Paint.Join.ROUND); 
      paint.setStrokeCap(Paint.Cap.ROUND);  
      paint.setStrokeWidth(STROKE_WIDTH); 
     } 

     public void clear() 
     { 
      mPath.reset(); 
      // Repaints the entire view. 
      invalidate(); 
     } 

     @Override 
     protected void onDraw(Canvas canvas) 
     { 
      for(int i=0; i<mPaths.size();i++) 
      { 
       paint.setStrokeWidth(mStrokes.get(i)); 
       canvas.drawPath(mPaths.get(i), paint); 
      } 
     } 

     @Override 
     public boolean onTouchEvent(MotionEvent event) 
     { 
      float eventX = event.getX(); 
      float eventY = event.getY(); 
      int historySize = event.getHistorySize(); 

      switch (event.getAction()) 
      { 
       case MotionEvent.ACTION_DOWN: 
       { 
        resetDirtyRect(eventX, eventY); 
        mPath.reset(); 
        mPath.moveTo(eventX, eventY); 
        mX = eventX; 
        mY = eventY; 
        break;     
       } 
       case MotionEvent.ACTION_MOVE: 
       {     
        if (event.getPressure()>=0.00 && event.getPressure()<0.05) 
        { 
         variableWidthDelta = -2; 
        } 
        else if (event.getPressure()>=0.05 && event.getPressure()<0.10) 
        { 
         variableWidthDelta = -2; 
        } 
        else if (event.getPressure()>=0.10 && event.getPressure()<0.15) 
        { 
         variableWidthDelta = -2; 
        } 
        else if (event.getPressure()>=0.15 && event.getPressure()<0.20) 
        { 
         variableWidthDelta = -2; 
        } 
        else if (event.getPressure()>=0.20 && event.getPressure()<0.25) 
        { 
         variableWidthDelta = -2; 
        } 
        else if (event.getPressure() >= 0.25 && event.getPressure()<0.30) 
        { 
         variableWidthDelta = 1; 
        } 
        else if (event.getPressure() >= 0.30 && event.getPressure()<0.35) 
        { 
         variableWidthDelta = 2; 
        } 
        else if (event.getPressure() >= 0.35 && event.getPressure()<0.40) 
        { 
         variableWidthDelta = 3; 
        } 
        else if (event.getPressure() >= 0.40 && event.getPressure()<0.45) 
        { 
         variableWidthDelta = 4; 
        } 
        else if (event.getPressure() >= 0.45 && event.getPressure()<0.60) 
        { 
         variableWidthDelta = 5; 
        } 

        float dx = Math.abs(eventX - mX); 
        float dy = Math.abs(eventY - mY); 

        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) 
        { 
         if(lastStroke != variableWidthDelta) 
         { 
          mPath.lineTo(mX, mY); 

          mPath = new Path(); 
          mPath.moveTo(mX,mY); 
          mPaths.add(mPath); 
          mStrokes.add(variableWidthDelta); 
         } 

         mPath.quadTo(mX, mY, (eventX + mX)/2, (eventY + mY)/2); 
         mX = eventX; 
         mY = eventY; 
        } 

        for (int i = 0; i < historySize; i++) 
        { 
         float historicalX = event.getHistoricalX(i); 
         float historicalY = event.getHistoricalY(i); 
         expandDirtyRect(historicalX, historicalY); 
        } 

        break; 
       } 
       case MotionEvent.ACTION_UP: 
       { 
        for (int i = 0; i < historySize; i++) 
        { 
         float historicalX = event.getHistoricalX(i); 
         float historicalY = event.getHistoricalY(i); 
         expandDirtyRect(historicalX, historicalY); 
        } 

        mPath.lineTo(mX, mY);     
        break; 
       } 
      } 

      // Include half the stroke width to avoid clipping. 
      invalidate(); 

      lastTouchX = eventX; 
      lastTouchY = eventY; 
      lastStroke = variableWidthDelta; 

      return true; 
     } 

     private void expandDirtyRect(float historicalX, float historicalY) 
     { 
      if (historicalX < dirtyRect.left) 
      { 
       dirtyRect.left = historicalX; 
      } 
      else if (historicalX > dirtyRect.right) 
      { 
       dirtyRect.right = historicalX; 
      } 
      if (historicalY < dirtyRect.top) 
      { 
       dirtyRect.top = historicalY; 
      } 
      else if (historicalY > dirtyRect.bottom) 
      { 
       dirtyRect.bottom = historicalY; 
      } 
     } 

     /** 
     * Resets the dirty region when the motion event occurs. 
     */ 
     private void resetDirtyRect(float eventX, float eventY) 
     { 
      // The lastTouchX and lastTouchY were set when the ACTION_DOWN 
      // motion event occurred. 
      dirtyRect.left = Math.min(lastTouchX, eventX); 
      dirtyRect.right = Math.max(lastTouchX, eventX); 
      dirtyRect.top = Math.min(lastTouchY, eventY); 
      dirtyRect.bottom = Math.max(lastTouchY, eventY); 
     } 
    } 
} 

하나의 경로를 그리기 위해 사용

코드 enter image description here

답변

0

업데이트 : Raghunandan 및 M-WaJeEh에 감사합니다.

내가 틀렸어. 이 SO 질문을 참조 할 수 있습니다.

android find pressure on screen

그리고 코멘트 섹션에서 다른 링크.

http://developer.android.com/reference/android/view/MotionEvent.html#getPressure(int)

+0

어때 이것에 대해 http://stackoverflow.com/questions/9312518/android-find-pressure-on-screen – Raghunandan

+0

그게 사실이 아닙니다. 쿠마. 'getPressure()'메서드를 사용할 수 있습니다. http://developer.android.com/reference/android/view/MotionEvent.html#getPressure(int) –

+0

네, 틀 렸습니다. 이 API가 존재한다는 것을 결코 알지 못했습니다. 내 대답을 편집 할 것입니다. –

1

당신은 getPressure() 방법을 사용하고 작동하도록이 답변 https://stackoverflow.com/a/15533607/1112882와 결합 할 수 있습니다. 아이디어는 폭을 저장하고 사용하는 것입니다.

+0

이전에이 코드를 살펴 보았지만 코드에서이 코드를 처리 할 수 ​​없었습니다. 기본 단계로 나를 도와 줄 수 있습니까? – AndroidDev

+0

안녕하세요, 제 코드에서 몇 가지 사항을 변경했습니다. 그것의 작동하지만 그려진 선은 부드럽 지 않다.; – AndroidDev

+0

여기에 몇 가지 제안 사항이 있습니다. 1)'mStrokes'를'Float''ArrayList'로 만듭니다. 2) else else를 모두 제거 할 수 있으며, 이처럼 'variableWidthDelta = 5 * event.getPressure();'와 같이 할당하면보다 부드러운 전환을 수행 한 다음 'mStrokes'에 추가 할 수 있습니다. –

0

경로가 가변 너비 그리기를 지원하지 않습니다.

MotionEvent.getPressure()VelocityTracker.computeCurrentVelocity() 방법을 사용하여 터치 압력과 속도를 얻을 수 있습니다.

다음으로 특정 속도 나 압력을 특정 너비로 ​​매핑하는 함수를 만들어야합니다.

이러한 준비가되어 있다고 가정하면 가변 너비 패스를 그리는 한 가지 방법은 경로를 다른 너비의 여러 패스로 나누는 것입니다. 예를 들어, 단일 경로를 따라 너비가 10에서 50으로 진행되어야한다면 너비는 5,10,15,20 ... 대신 10 개의 경로를 가질 수 있습니다. 많은 수의 Path 객체를 생성하면 메모리 소비가 발생하므로 많은 최적화 작업을 수행해야합니다.

또 다른 방법은 quad-curves 또는 bezier curves을 사용하는 것입니다.

+0

내 코드에서 쿼드 커브 프로젝트를 어떻게 사용할 수 있습니까? – AndroidDev

+0

내 것이 아닙니다. 그것은 iOS 용 Cocos2D를 기반으로합니다. 알고리즘과 방법론을 연구하는 데 사용할 수 있습니다. 동일한 코드를 직접 사용할 수 없습니다. –

0
@Override 
    protected synchronized void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     this.canvas = canvas; 
     Log.d("tag", "Padding" + padding); 
     int newPadding = (int) padding; 

     // Set Min X 
     int xPadding = (int) padding; 
     Paint bottomLeftTextPaint = new Paint(); 
     Typeface tf = Typeface.create("Helvetica", Typeface.NORMAL); 
     bottomLeftTextPaint.setColor(context.getResources().getColor(
       R.color.common_color_rangeseekbar_bottomtext)); 
     bottomLeftTextPaint.setTextAlign(Align.LEFT); 
     bottomLeftTextPaint.setTypeface(tf); 
     bottomLeftTextPaint.setTextSize(20); 

     bottomLeftTextPaint.setColor(context.getResources().getColor(
       R.color.common_color_rangeseekbar_bottomtext)); 
     canvas.drawText(absoluteMinValue + "", newPadding - 5, 
       0.5f * (getHeight() + lineHeight) + 30, bottomLeftTextPaint); 
     // draw seek bar background line 
     final RectF rect = new RectF(newPadding - 5, 
       0.5f * (getHeight() - lineHeight), getWidth() - padding, 
       0.5f * (getHeight() + lineHeight)); 
     paint.setStyle(Style.FILL); 
     // paint.setColor(Color.parseColor("#ED797F")); 
     paint.setColor(Color.parseColor("#e2e2e2")); 
     paint.setAntiAlias(true); 
     canvas.drawRect(rect, paint); 
     RectF rectStartLine = new RectF(newPadding - 5, 
       0.5f * (getHeight() - lineHeight) - 5, padding, 
       0.5f * (getHeight() + lineHeight) + 5); 
     paint.setStyle(Style.FILL); 
     paint.setColor(Color.BLACK); 
     paint.setAntiAlias(true); 
     canvas.drawRect(rectStartLine, paint); 
     // End Line 
     // RectF rectEndLine = new RectF(getWidth() - padding, 
     // 0.5f * (getHeight() - lineHeight) - 5, 
     // getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5); 
     RectF rectEndLine = new RectF(getWidth() - padding, 
       0.5f * (getHeight() - lineHeight) - 5, 
       getWidth() - padding + 5, 0.5f * (getHeight() + lineHeight) + 5); 
     paint.setStyle(Style.FILL); 
     paint.setColor(Color.BLACK); 
     paint.setAntiAlias(true); 
     canvas.drawRect(rectEndLine, paint); 
     // End Text 
     // Set Min X 
     int xEndPadding = (int) padding; 

     paint.setColor(Color.parseColor(context.getResources().getString(
       R.color.common_color_rangeseekbar_bottomtext))); 
     paint.setTextSize(20); 
     int max = (Integer) absoluteMaxValue; 
     String MaxValue = String.valueOf(max); 
     paint.setColor(Color.parseColor(context.getResources().getString(
       R.color.common_color_rangeseekbar_bottomtext))); 
     Paint bottomTextPaint = new Paint(); 
     bottomTextPaint.setTypeface(tf); 
     bottomTextPaint.setColor(context.getResources().getColor(
       R.color.common_color_rangeseekbar_bottomtext)); 
     bottomTextPaint.setTextAlign(Align.RIGHT); 
     bottomTextPaint.setTypeface(tf); 
     bottomTextPaint.setTextSize(20); 
     // if (MaxValue.length() > 4) { 
     // 
     // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 23, 
     // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint); 
     // } else if (MaxValue.length() > 3) { 
     // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 18, 
     // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint); 
     // } else if (MaxValue.length() > 2) { 
     // canvas.drawText(absoluteMaxValue + "", getWidth() - padding - 13, 
     // 0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint); 
     // } else { 
     canvas.drawText(absoluteMaxValue + "", getWidth() - padding, 
       0.5f * (getHeight() + lineHeight) + 30, bottomTextPaint); 
     // } 
     // draw seek bar active range line 
     rect.left = normalizedToScreen(normalizedMinValue); 
     rect.right = normalizedToScreen(normalizedMaxValue); 

     // orange color 
     paint.setColor(DEFAULT_COLOR); 
     paint.setTypeface(tf); 

     canvas.drawRect(rect, paint); 
     Paint headerPaint = new Paint(); 
     // Set TextSize 
     headerPaint.setTextSize(20); 
     headerPaint.setTextAlign(Align.LEFT); 
     headerPaint.setTypeface(tf); 
     headerPaint.setColor(Color.parseColor(context.getResources().getString(
       R.color.common_color_rangeseekbar_toptext))); 
     headerPaint.setTextAlign(Align.LEFT); 
     // draw minimum thumb 
     drawThumb(normalizedToScreen(normalizedMinValue), 
       Thumb.MIN.equals(pressedThumb), canvas); 
     canvas.drawText("" + getSelectedMinValue(), 
       normalizedToScreen(normalizedMinValue)-5, 
       (float) ((0.5f * getHeight()) - thumbHalfHeight) - 8, 
       headerPaint); 
     // draw maximum thumb 
     drawThumb(normalizedToScreen(normalizedMaxValue), 
       Thumb.MAX.equals(pressedThumb), canvas); 
     // Right TrackText 
     Paint righText = new Paint(); 
     righText.setTextAlign(Align.RIGHT); 
     righText.setAntiAlias(true); 
     righText.setTextSize(20); 
     righText.setTypeface(tf); 
     canvas.drawText("" + getSelectedMaxValue(), 
       normalizedToScreen(normalizedMaxValue), 
       (float) ((0.5f * getHeight()) - thumbHalfHeight) , righText); 
    } 
0

아마도 this이 도움이 될 것입니다. 직접 구현해야합니다.

관련 문제