本例讲解了一个在图片上绘制路径的实例,绘制的路径可以选择普通、浮雕、喷涂三种效果。
效果如下:
下面是实现方法:
public class Main extends Activity implements OnColorChangedListener { private MyView myView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myView = new MyView(this); setContentView(myView); paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setColor(0xFFFF0000); paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeWidth(6); emboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f); blur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL); } private Paint paint; private MaskFilter emboss; private MaskFilter blur; public void colorChanged(int color) { paint.setColor(color); } public class MyView extends View { private Bitmap bitmap1; private Bitmap bitmap2; private Canvas canvas; private Path path; private Paint bitmapPaint; //创建一个可在图像上绘制图形的bitmap对象 public void loadBitmap() { try { //从drawable中装载图像资源,并生成bitmap对象 InputStream is = getResources().openRawResource( R.drawable.image); //使用createbitmap创建一个可绘制的bitmap对象,直接装载的不能直接绘制 bitmap2 = BitmapFactory.decodeStream(is); bitmap1 = Bitmap .createBitmap(320, 480, Bitmap.Config.ARGB_8888); //使用bitmap1对象创建一个画布 canvas = new Canvas(bitmap1); //在bitmap1上绘制2 canvas.drawBitmap(bitmap2, 0, 0, null); } catch (Exception e) { } } public MyView(Context c) { super(c); loadBitmap(); bitmapPaint = new Paint(Paint.DITHER_FLAG); path = new Path(); } public void clear() { loadBitmap(); invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap1, 0, 0, bitmapPaint); canvas.drawPath(path, paint); } private float mX, mY; private void touch_start(float x, float y) { path.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); path.quadTo(mX, mY, x, y); mX = x; mY = y; } private void touch_up() { canvas.drawPath(path, paint); path.reset(); try { FileOutputStream fos = new FileOutputStream("/sdcard/image.png"); bitmap1.compress(CompressFormat.PNG, 100, fos); fos.close(); } catch (Exception e) { } } //捕捉view的触摸事件 @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; } } private final int COLOR_MENU_ID = Menu.FIRST; private final int EMBOSS_MENU_ID = Menu.FIRST + 1; private final int BLUR_MENU_ID = Menu.FIRST + 2; private final int CLEAR_MENU_ID = Menu.FIRST + 3; @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, COLOR_MENU_ID, 0, "设置颜色"); menu.add(0, EMBOSS_MENU_ID, 0, "浮雕效果"); menu.add(0, BLUR_MENU_ID, 0, "喷涂效果"); menu.add(0, CLEAR_MENU_ID, 0, "清除图形"); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case COLOR_MENU_ID: new ColorPickerDialog(this, this, paint.getColor()).show(); return true; case EMBOSS_MENU_ID: if (paint.getMaskFilter() != emboss) { paint.setMaskFilter(emboss); } else { paint.setMaskFilter(null); } return true; case BLUR_MENU_ID: if (paint.getMaskFilter() != blur) { paint.setMaskFilter(blur); } else { paint.setMaskFilter(null); } return true; case CLEAR_MENU_ID: myView.clear(); return true; } return super.onOptionsItemSelected(item); } }本例使用的颜色选择器是APIDemo中的一个示例:
public class ColorPickerDialog extends Dialog { public interface OnColorChangedListener { void colorChanged(int color); } private OnColorChangedListener mListener; private int mInitialColor; private static class ColorPickerView extends View { private Paint mPaint; private Paint mCenterPaint; private final int[] mColors; private OnColorChangedListener mListener; ColorPickerView(Context c, OnColorChangedListener l, int color) { super(c); mListener = l; mColors = new int[] { 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 }; Shader s = new SweepGradient(0, 0, mColors, null); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setShader(s); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(32); mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCenterPaint.setColor(color); mCenterPaint.setStrokeWidth(5); } private boolean mTrackingCenter; private boolean mHighlightCenter; @Override protected void onDraw(Canvas canvas) { float r = CENTER_X - mPaint.getStrokeWidth()*0.5f; canvas.translate(CENTER_X, CENTER_X); canvas.drawOval(new RectF(-r, -r, r, r), mPaint); canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint); if (mTrackingCenter) { int c = mCenterPaint.getColor(); mCenterPaint.setStyle(Paint.Style.STROKE); if (mHighlightCenter) { mCenterPaint.setAlpha(0xFF); } else { mCenterPaint.setAlpha(0x80); } canvas.drawCircle(0, 0, CENTER_RADIUS + mCenterPaint.getStrokeWidth(), mCenterPaint); mCenterPaint.setStyle(Paint.Style.FILL); mCenterPaint.setColor(c); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(CENTER_X*2, CENTER_Y*2); } private static final int CENTER_X = 100; private static final int CENTER_Y = 100; private static final int CENTER_RADIUS = 32; private int floatToByte(float x) { int n = java.lang.Math.round(x); return n; } private int pinToByte(int n) { if (n < 0) { n = 0; } else if (n > 255) { n = 255; } return n; } private int ave(int s, int d, float p) { return s + java.lang.Math.round(p * (d - s)); } private int interpColor(int colors[], float unit) { if (unit <= 0) { return colors[0]; } if (unit >= 1) { return colors[colors.length - 1]; } float p = unit * (colors.length - 1); int i = (int)p; p -= i; // now p is just the fractional part [0...1) and i is the index int c0 = colors[i]; int c1 = colors[i+1]; int a = ave(Color.alpha(c0), Color.alpha(c1), p); int r = ave(Color.red(c0), Color.red(c1), p); int g = ave(Color.green(c0), Color.green(c1), p); int b = ave(Color.blue(c0), Color.blue(c1), p); return Color.argb(a, r, g, b); } private int rotateColor(int color, float rad) { float deg = rad * 180 / 3.1415927f; int r = Color.red(color); int g = Color.green(color); int b = Color.blue(color); ColorMatrix cm = new ColorMatrix(); ColorMatrix tmp = new ColorMatrix(); cm.setRGB2YUV(); tmp.setRotate(0, deg); cm.postConcat(tmp); tmp.setYUV2RGB(); cm.postConcat(tmp); final float[] a = cm.getArray(); int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b); int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b); int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b); return Color.argb(Color.alpha(color), pinToByte(ir), pinToByte(ig), pinToByte(ib)); } private static final float PI = 3.1415926f; @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX() - CENTER_X; float y = event.getY() - CENTER_Y; boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTrackingCenter = inCenter; if (inCenter) { mHighlightCenter = true; invalidate(); break; } case MotionEvent.ACTION_MOVE: if (mTrackingCenter) { if (mHighlightCenter != inCenter) { mHighlightCenter = inCenter; invalidate(); } } else { float angle = (float)java.lang.Math.atan2(y, x); // need to turn angle [-PI ... PI] into unit [0....1] float unit = angle/(2*PI); if (unit < 0) { unit += 1; } mCenterPaint.setColor(interpColor(mColors, unit)); invalidate(); } break; case MotionEvent.ACTION_UP: if (mTrackingCenter) { if (inCenter) { mListener.colorChanged(mCenterPaint.getColor()); } mTrackingCenter = false; // so we draw w/o halo invalidate(); } break; } return true; } } public ColorPickerDialog(Context context, OnColorChangedListener listener, int initialColor) { super(context); mListener = listener; mInitialColor = initialColor; } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); OnColorChangedListener l = new OnColorChangedListener() { public void colorChanged(int color) { mListener.colorChanged(color); dismiss(); } }; setContentView(new ColorPickerView(getContext(), l, mInitialColor)); setTitle("Pick a Color"); } }