2011-09-13 107 views
10

我是新來的Android圖形類。我想使用觸摸事件繪製圖像(實際上是一種簽名類型),並希望在保存時將其保存在SDcard中。我已經通過網絡掃描任何這樣的教程,但我還沒有找到任何。任何人都可以告訴我如何使用觸摸事件在畫布上繪製並保存它。在畫布上繪圖並保存圖像

任何教程或示例代碼都會有很大的幫助。

回答

20

我看到Android開發者真正的好代碼,但我找不到它了......它的輸出是貝塞爾曲線,所以它會非常平滑。這裏是我編輯的代碼:你想在你使用它只是寫這樣的事情

public class MyDrawView extends View { 

private Bitmap mBitmap; 
private Canvas mCanvas; 
private Path mPath; 
private Paint mBitmapPaint; 
private Paint mPaint; 

public MyDrawView(Context c) { 
    super(c); 

    mPath = new Path(); 
    mBitmapPaint = new Paint(Paint.DITHER_FLAG); 

    mPaint = new Paint(); 
    mPaint.setAntiAlias(true); 
    mPaint.setDither(true); 
    mPaint.setColor(0xFF000000); 
    mPaint.setStyle(Paint.Style.STROKE); 
    mPaint.setStrokeJoin(Paint.Join.ROUND); 
    mPaint.setStrokeCap(Paint.Cap.ROUND); 
    mPaint.setStrokeWidth(3); 
} 

@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
    mCanvas = new Canvas(mBitmap); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); 

    canvas.drawPath(mPath, mPaint); 
} 

private float mX, mY; 
private static final float TOUCH_TOLERANCE = 4; 

private void touch_start(float x, float y) { 
    mPath.reset(); 
    mPath.moveTo(x, y); 
    mX = x; 
    mY = y; 
} 
private void touch_move(float x, float y) { 
    float dx = Math.abs(x - mX); 
    float dy = Math.abs(y - mY); 
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 
     mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); 
     mX = x; 
     mY = y; 
    } 
} 
private void touch_up() { 
    mPath.lineTo(mX, mY); 
    // commit the path to our offscreen 
    mCanvas.drawPath(mPath, mPaint); 
    // kill this so we don't double draw 
    mPath.reset(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    float x = event.getX(); 
    float y = event.getY(); 

    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      touch_start(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      touch_move(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_UP: 
      touch_up(); 
      invalidate(); 
      break; 
    } 
    return true; 
} 

public void clear(){ 
    mBitmap.eraseColor(Color.TRANSPARENT); 
    invalidate(); 
    System.gc(); 
}} 

然後在活動的onCreate:

RelativeLayout parent = (RelativeLayout) findViewById(R.id.signImageParent); 
myDrawView = new MyDrawView(this); 
parent.addView(myDrawView); 

這種觀點是透明的,採用黑色漆繪製你的手指。所以如果你想看看你畫的是什麼,只需在這個視圖的背景上畫一個白色或灰色的位圖(你只需在onDraw的beginnig中添加一行),或者你可以使用父級的背景。

然後,當你想創建你吸引你的圖像只是調用

parent.setDrawingCacheEnabled(true); 
Bitmap b = parent.getDrawingCache(); 

FileOutputStream fos = null; 
try { 
fos = new FileOutputStream(getFileName()); 
} catch (FileNotFoundException e) { 
e.printStackTrace(); 
} 

b.compress(CompressFormat.PNG, 95, fos); 

這取決於你想有作爲輸出什麼,你可以使用此代碼或代替你可以使用myDrawView來做到這一點,你只需獲取沒有背景繪製的圖像(因爲我們的myDrawView背景是透明的)。

希望這會有所幫助。隨時留下反饋。

+0

真棒代碼... !!! – Manjunath

+0

謝謝,這是我需要的。 – lucasjmatias

+1

如果我有一個TextView,我想將它製作成繪圖板以允許自由繪製,該怎麼辦? –

19

繪圖事情

Scribbler.java:

package org.yourpackage.scribble; 

import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 

public class Scribbler extends Activity { 
    DrawView drawView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     drawView = new DrawView(this); 
     drawView.setBackgroundColor(Color.WHITE); 
     setContentView(drawView); 
     drawView.requestFocus(); 

    } 
} 

DrawView.java:

package org.yourpackage.scribble; 

import java.util.ArrayList; 
import java.util.List; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 

public class DrawView extends View implements OnTouchListener { 
    List<Point> points = new ArrayList<Point>(); 
    Paint paint = new Paint(); 

    public DrawView(Context context) { 
     super(context); 
     setFocusable(true); 
     setFocusableInTouchMode(true); 
     this.setOnTouchListener(this); 
     paint.setColor(Color.BLACK); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 
     for (Point point : points) { 
      canvas.drawCircle(point.x, point.y, 2, paint); 
     } 
    } 

    public boolean onTouch(View view, MotionEvent event) { 
     Point point = new Point(); 
     point.x = event.getX(); 
     point.y = event.getY(); 
     points.add(point); 
     invalidate(); 
     return true; 
    } 
} 

class Point { 
    float x, y; 
} 

的AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="org.yourpackage.scribble" 
     android:versionCode="1" 
     android:versionName="1.0"> 
    <application> 
     <activity android:name=".Scribbler"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 
    <uses-sdk android:minSdkVersion="3" /> 
</manifest> 

..will給你這樣的事情:

alt text

您可能要畫線,而不是像素

節能的事情

落實節能可以傳遞一個Bitmap成構造函數Canvas,然後使用compress 方法Bitmap創建一個OutputStream,它可以寫入SD卡

編輯回答您的評論:
當然您也可以使用XML來定義你的佈局,因爲DrawView擴展視圖,您可以在您的佈局xml文件中使用它。 爲main.xml佈局文件

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:id="@+id/linearLayout" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="@drawable/gradient" 
    > 

    <Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> 
    <org.yourpackage.scribble.DrawView android:id="@+id/drawView1" android:layout_width="wrap_content" android:layout_height="wrap_content">  </at.gru.android.drawdemo.DrawView> 
</LinearLayout> 

,讓你像這樣的例子:
enter image description here
你只需要一個額外的contstructor public DrawView(Context context, AttributeSet attrSet)

+0

如果我想插入任何UI組件,是否需要從代碼創建按鈕和標籤?我可以爲UI組件使用XML佈局文件嗎?使用上面的例子,繪圖不是連續的。應該做什麼來實現連續繪製而不會破損? –

+0

我剛剛編輯答案,以解決您的意見 – DonGru

+0

感謝編輯馬丁。最後一件事。如何在沒有破損的情況下實現平滑的繪製? –