公司的项目里有一个功能是,用户有个涂鸦签字的功能,需要再白色面板上涂鸦,然后上传到又拍云,把又拍云返回的图片url通过post请求上传到服务器。摸索了一段时间,完成了这个功能,并且实现的不错。下面贴出截图跟部分demo:
上传到又拍云的那部分demo就不贴了,涉及到很多图片url定义规则还有项目隐私的东西,只贴到 保存图片到本地的,后面上传图片就是很简单啦!
1.自定义的ImageTextView.class
<span style="font-size:14px;">public class ImageEditTextView extends EditText {
private Paint mPaint;
private Rect mRect;
private Context mContext;
public ImageEditTextView(Context context) {
super(context);
mContext = context;
}
public ImageEditTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mContext = context;
}
public ImageEditTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
mContext = context;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
System.out.println("left:"+left+".top:"+top+".right:"+right+".bottom:"+bottom);
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
int windowWidth = wm.getDefaultDisplay().getWidth();
int windowHeight = wm.getDefaultDisplay().getHeight();
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLACK);
paint.setColor(Color.WHITE);
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int scrollY = getScrollY(); //
int scrollX = getScrollX()+windowWidth;
int innerHeight = scrollY + getHeight() - paddingTop - paddingBottom;
int lineHeight = getLineHeight();
int baseLine = scrollY + (lineHeight - (scrollY % lineHeight));
int x = 8;
while (baseLine < innerHeight) {
//canvas.drawBitmap(line, x, baseLine + paddingTop, paint);
canvas.drawLine(x, baseLine + paddingTop,scrollX, baseLine + paddingTop, paint);
baseLine += lineHeight;
}
}
}</span>
2.自定义
HandTouchView.class
public class HandTouchView extends View {
public Handler mbitmaphHandler;
public Handler getMbitmaphHandler() {
return mbitmaphHandler;
}
public void setMbitmaphHandler(Handler mbitmaphHandler) {
this.mbitmaphHandler = mbitmaphHandler;
}
private DisplayMetrics dm;
private Bitmap bitmap=null;
private Bitmap mBitmap=null;
private Bitmap myBitmap ;
private Paint mPaint=null;
private Canvas mCanvas=null;
private Paint mBitmapPaint=null;
private Timer timer=null;
private savePath sPath;
private List<savePath> lists =null;
private FingerMatrix fingerMatrix=null;
private float Xi,Yi;
private Path path=null;
public HandTouchView(Context context) {
super(context);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);
}
public HandTouchView(Context context, AttributeSet attrs) {
super(context, attrs);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);
}
public HandTouchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
inter(dm.widthPixels, dm.heightPixels);
}
/**
* 初始化
* @param w
* @param h
*/
public void inter(int w,int h){
mBitmap =Bitmap.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(FingerMatrix.colorValue);
lists = new ArrayList<HandTouchView.savePath>();
fingerMatrix = new FingerMatrix();
timer = new Timer(true); //定时器来截取字
}
public void minter(int w,int h){
mBitmap =Bitmap.createBitmap(w, h, Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(FingerMatrix.colorValue);
lists = new ArrayList<HandTouchView.savePath>();
fingerMatrix = new FingerMatrix();
timer = new Timer(true);
}
public void RefreshPaint(){
path = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
mPaint.setStrokeCap(Paint.Cap.SQUARE);// 形 状
mPaint.setStrokeWidth(15);// 画笔宽度
mPaint.setColor(Color.BLACK);
}
protected void onDraw(Canvas canvas) {
// 设置canvas画布背景为白色
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (path!=null) {
canvas.drawPath(path, mPaint);
}
super.onDraw(canvas);
}
/**
* 手指 移动事件
*/
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: //按下屏幕时
mPaint.setColor(FingerMatrix.colorValue);
float x = event.getX();
float y = event.getY();
if (task!=null) { //如果等于空
task.cancel(); //关闭定时器将原任务从队列中移除
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message); //发给handler
}
};
}
//Log.i("线程", "触屏时的坐标"+x+"y坐标"+y);
if (fingerMatrix==null) {
fingerMatrix = new FingerMatrix();
//Log.i("线程", "<staRT>fingerMatrix等于空");
fingerMatrix.init(x, y);
}else {
fingerMatrix.getx(x);
//Log.i("线程", "<等于空>fingerMatrix等于空");
fingerMatrix.getY(y);
}
path = new Path();
sPath =new savePath();
sPath.paint = mPaint; //保存路径
sPath.path = path;
path.moveTo(x, y); //开始划线
Xi = x;
Yi = y;
invalidate(); //刷新
break;
case MotionEvent.ACTION_MOVE: //移动中
float X1 = event.getX();
float Y1 = event.getY();
if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what=1;
handler.sendMessage(message);
}
};
}
if (fingerMatrix!=null) {
fingerMatrix.getx(X1);
fingerMatrix.getY(Y1);
//Log.i("线程", "fingerMatrix不等于空");
}
float j = Math.abs(X1-Xi);
float i = Math.abs(Yi-Y1);
if (j>=5||i>=5) {
path.quadTo(Xi, Yi, X1, Y1);
Xi = X1;
Yi = Y1;
}
invalidate();
break;
case MotionEvent.ACTION_UP: //手指松下离开屏幕时
//一旦有在屏幕按下抬起操作时,就给SettleAccountActivity发送消息,告知已签字
Message message = new Message();
message.what=2;
message.arg1=1;
if (mbitmaphHandler!=null){
mbitmaphHandler.sendMessage(message);
}
float My = event.getX(); //手指离开屏幕时的坐标
float Mx = event.getY();
if (fingerMatrix!=null) {
fingerMatrix.getx(Mx);
//Log.i("线程", "离开"+Mx);
fingerMatrix.getY(My);
}
mCanvas.drawPath(path, mPaint);
lists.add(sPath);
invalidate();
if (timer!=null) {
if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
timer.schedule(task, 2200, 2200); //2200秒后发送消息给handler更新Activity
}
}else {
timer = new Timer(true);
timer.schedule(task, 2200, 2200); //2200秒后发送消息给handler更新Activity
}
break;
default:
if (task!=null) {
task.cancel();
task = new TimerTask() {
public void run() {
handler.sendEmptyMessage(0);
}
};
}
break;
}
return true;
}
/**
* 处理屏幕显示
*/
Handler handler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) { //handler告诉Activity处理数据
case 1: //CUT_BITMAP_SEND_TO_ACTIVITY//切割图片发送给Activity处理
//Log.i("线程", "handler收到");
myBitmap = mBitmap; //获取写好的图片
if (fingerMatrix!=null) { //获取绘制的区域坐标
myBitmap = cutBitmap(myBitmap); //切割Bitmap图片方法
}
fingerMatrix=null;
if (mbitmaphHandler!=null){
Matrix matrix = new Matrix();
matrix.postRotate(90); /*翻转90度*/
int width = myBitmap.getWidth();
int height =myBitmap.getHeight();
myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, width, height, matrix, true);
saveBiamtImate(myBitmap);
}
Message message = new Message();
message.what=1;
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap",myBitmap);
message.setData(bundle);
if (mbitmaphHandler!=null){
mbitmaphHandler.sendMessage(message);
}
//RefreshCanvas();
break;
}
super.handleMessage(msg);
}
};
/**
* 发送消息给handler更新ACTIVITY
*/
TimerTask task = new TimerTask() {
public void run() {
Message message = new Message();
message.what=1;
//Log.i("线程", "来了");
handler.sendMessage(message);
}
};
/**
* 保存路径类
* @author Administrator
*/
class savePath{
Paint paint;
Path path;
}
/**
* 切割图片方法和更新Activity
* @param bnBitmap
*/
public Bitmap cutBitmap(Bitmap bnBitmap){
//最小
float minx = fingerMatrix.getMinX(); //最小的x坐标
float miny = fingerMatrix.getMinY(); //最小的y坐标
//最大
float maxy = fingerMatrix.getMaxY(); //最大的Y坐标
float maxX = fingerMatrix.getMaxX(); //最大的x坐标
//Log.i("","矩阵的坐标信息为:-======最大X:"+maxX+"----====最大Y:"+maxy+"----====最小X:"+minx+"----====最小Y:"+miny);
int cutMinX = (int)(minx-15); //切割的最小值
int cutMinY = (int)(miny-15); //切割的最小值
int cutMaxX = (int)(maxX+15);
int cutMaxY = (int)(maxy+15);
if (cutMinX<=0) {
cutMinX=0;
}
if (cutMinY<=0) {
cutMinY=0;
}
if (cutMaxX>mBitmap.getWidth()) { //如果X坐标大于图片的宽度
cutMaxX = mBitmap.getWidth()-1; //那就把图片的宽度付给X坐标 的最大值
}
if (cutMaxY>mBitmap.getHeight()) { //如果Y坐标大于图片的宽度
cutMaxY = mBitmap.getHeight()-1; //那就把图片的宽度付给Y坐标 的最大值
}
int width =(int)(cutMaxX - cutMinX); //最大的x坐标减去最小的x坐标
int height =(int)(cutMaxY-cutMinY); //最大的Y坐标减去最小的y坐标
Bitmap wBitmap =Bitmap.createBitmap(bnBitmap, cutMinX, cutMinY, width, height); //这个步骤意思是在什么坐标位置创建一张图片
if (myBitmap!=null ) {
//myBitmap.recycle();
myBitmap= null;
}
//Log.i("线程", "剪切图片成功");
return wBitmap;
}
/**
* 保存图片
* @param bitmap1
*/
public boolean saveBiamtImate(Bitmap bitmap1){
Date localDate=new Date();
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AthenaImage";
File file=new File(path);
if (!file.exists()){
file.mkdirs();
}
//String fileUrl = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"AthenaImage"+ "/save.jpg";
String fileUrl ="save.png";
try {
FileOutputStream fos = new FileOutputStream(new File(file,fileUrl));
bitmap1.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
Log.i("TAG", "2成功!" + fileUrl);
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 刷新画布
*/
public void RefreshCanvas(){
//Log.i("线程", "初始化数据并且 刷新画布");
if (lists!=null&&lists.size()>0) {
lists.remove(lists);
if (mBitmap!=null) {
mBitmap=null;
}
path=null;
// inter(dm.widthPixels,dm.heightPixels);
inter(dm.widthPixels,dm.heightPixels);
//Log.i("线程", "初始化数据成功");
invalidate();
}
if (task!=null) {
task.cancel();
}
}
}
3.布局文件引用:
4.Activity:<FrameLayout android:layout_below="@+id/tv2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/finger_layout" android:background="@drawable/tv_border_thin" android:layout_margin="@dimen/common_sw320dp_of_10" > <com.canvas.ImageEditTextView android:id="@+id/main_image_edit" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/transparent" android:focusable="true" android:focusableInTouchMode="true" android:gravity="top|left" android:paddingBottom="3dip" android:paddingTop="3dip" android:textSize="50dip" > </com.canvas.ImageEditTextView> <com.canvas.HandTouchView android:id="@+id/hand_touch" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/transparent"> </com.canvas.HandTouchView> </FrameLayout>
private void initView() { Display display = this.getWindowManager().getDefaultDisplay(); mWidth = display.getWidth(); mHeight = display.getHeight(); touchView=(HandTouchView) include2.findViewById(R.id.hand_touch); imageEditTextView = (ImageEditTextView)include2.findViewById(R.id.main_image_edit); }
public int mWidth,mHeight; public HandTouchView touchView; private Bitmap tempBitmap;
/** * 图片处理方法 */ Handler handler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case 1: Bundle bundle = new Bundle(); bundle = msg.getData(); tempBitmap = bundle.getParcelable("bitmap"); //获取图片 if (null!=tempBitmap) { isGetBitmap=1;//0:未签字;1:已签字 Log.i("线程", "前台取到VIEW的值"); int w = tempBitmap.getWidth(); //获取图片的宽度如果大就缩小如果小就不变 int h = tempBitmap.getHeight(); //取到当前的行高和行宽 int lineHeight = (int) (mHeight/6f); int lineWidth = (int) (mWidth/4f); if(mHeight == 1280 && mWidth == 800){ lineHeight = (int) (mHeight/5.4f); lineWidth = (int) (mWidth/4f); } tempBitmap =BitmapAmplification(tempBitmap); editInsertBitmap(tempBitmap); //显示在EditText上 try { EditTextSaveImage(); tv_submit_c.setEnabled(true); Log.i("TAG","①图片已保存本地"); /*if (tv_submit_c.getText().toString().equals("保存")){ tv_submit_c.setEnabled(true); Log.i("TAG","①图片已保存本地"); }*/ } catch (IOException e) { e.printStackTrace(); } }else { if (dialog.isShowing()){ dialog.dismiss(); } Toast.makeText(SettleAccountActivity.this,"提交前请先签字",Toast.LENGTH_SHORT).show(); } break; default: isGetBitmap= msg.arg1;//0:未签字;1:已签字 break; } super.handleMessage(msg); } }; /** * 将bitmap添加到自定义edittext中 * @param bitmap */ public void editInsertBitmap(Bitmap bitmap) { SpannableString ss = new SpannableString("1"); ImageSpan span = new ImageSpan(bitmap, ImageSpan.ALIGN_BOTTOM); ss.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); imageEditTextView.append(ss); imageEditTextView.setPadding(0, 0, 0, 10); } /** * 删除方法 */ public void editImageDelete(){ Editable editable = imageEditTextView.getText(); int end = imageEditTextView.getSelectionEnd(); //删除最后的一个 if (end==1) { imageEditTextView.setText(""); return; } if (end<=0) { imageEditTextView.setText(""); return; } CharSequence sequence = editable.subSequence(0, end-1); imageEditTextView.setText(sequence); imageEditTextView.setSelection(end - 1); } Bitmap bp; public Bitmap BitmapAmplification(Bitmap path) { if (path!=null) { if(bp!=null){ bp=null; } int w = path.getWidth(); //得到图片的宽度 int h = path.getHeight();//得到图片的高度 Log.v("nnn", "宽"+w+"高"+h); float ww = ((float) 62) / w; float hh = ((float) 45) / h; Matrix matrix = new Matrix(); matrix.postScale(ww, hh); Log.v("nnn", "可以www"); bp = Bitmap.createBitmap(path, 0, 0, w, h, matrix, true); if (tempBitmap!=null ) { tempBitmap=null; } return bp; } return null; } //private Bitmap savebitmap; public void EditTextSaveImage() throws IOException { //取本地图片 String fileUrl = Environment.getExternalStorageDirectory().getAbsoluteFile()+File.separator+"AthenaImage"+File.separator+"save.png"; //String fileUrl=Environment.getExternalStorageDirectory().getAbsoluteFile()+File.separator+"iv.jpg"; Log.i("TAG", "②取到本地图片地址:fileUrl:" + fileUrl); if (!StringUtils.isEmpty(fileUrl)&&!hasSaved) { saveUPYun(fileUrl); } }
好了,写到这里,其实你的本地就已经存好了图片,剩下来的步骤就很简单啦</pre><pre name="code" class="java">
注意保存的图片格式是PNG,千万一定要用PNG,不要用JPG啊,因为JPG保存的图片背景是黑色的,有好长一段时间我都掉进了这个坑!具体什么原因,我也不清楚,欢迎交流学习。