不多说,直接上代码看效果:
package com.loaderman.signaturedemo; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class SignatureView extends View { private Path mPath = new Path(); private Paint mPaint; private float mPreX,mPreY; public SignatureView(Context context) { super(context); init(); } public SignatureView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public SignatureView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mPaint = new Paint(); mPaint.setColor(Color.BLACK); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(10); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN:{ mPath.moveTo(event.getX(),event.getY()); mPreX = event.getX(); mPreY = event.getY(); return true; } case MotionEvent.ACTION_MOVE:{ float endX = (mPreX+event.getX())/2; float endY = (mPreY+event.getY())/2; mPath.quadTo(mPreX,mPreY,endX,endY);//实现手势平滑过渡 mPreX = event.getX(); mPreY =event.getY(); invalidate(); } break; default: break; } return super.onTouchEvent(event); } Canvas canvas; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); this.canvas=canvas; canvas.drawColor(Color.WHITE); canvas.drawPath(mPath,mPaint); } public void clearDraw(){ if (mPath!=null){ mPath.reset(); invalidate(); } } }
package com.loaderman.signaturedemo; import android.os.Environment; import java.io.File; public class FileUtil { public static File getFile() { File appDir = new File(Environment.getExternalStorageDirectory(), "Signature"); if (!appDir.exists()) { appDir.mkdirs(); } return appDir; } }
package com.loaderman.signaturedemo; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ImageView; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; public class MainActivity extends AppCompatActivity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.tv_start).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(MainActivity.this, SignatureActivity.class)); } }); iv = findViewById(R.id.iv); } @Override protected void onResume() { super.onResume(); Bitmap loacalBitmap = getLoacalBitmap(new File(FileUtil.getFile(), "signature.png")); if (loacalBitmap != null) { iv.setImageBitmap(loacalBitmap); } } /** * 加载本地图片 * * @param file * @return */ public static Bitmap getLoacalBitmap(File file) { try { FileInputStream fis = new FileInputStream(file); return BitmapFactory.decodeStream(fis); ///把流转化为Bitmap图片 } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } }
package com.loaderman.signaturedemo; import android.graphics.Bitmap; import android.graphics.Canvas; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class SignatureActivity extends AppCompatActivity { private SignatureView sv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_signature); sv = findViewById(R.id.sv); findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Bitmap bitmap = Bitmap.createBitmap(sv.getWidth(), sv.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); //把view中的内容绘制在画布上 sv.draw(canvas); boolean b = saveBitmap(bitmap); if (b){ finish(); }else { Toast.makeText(SignatureActivity.this,"保存失败",Toast.LENGTH_SHORT).show(); } } }); findViewById(R.id.btn_clear).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sv.clearDraw(); } }); } /** 保存方法 */ public boolean saveBitmap(Bitmap bm) { File f=new File(FileUtil.getFile(),"signature.png"); if (f.exists()) { f.delete(); } try { FileOutputStream out = new FileOutputStream(f); bm.compress(Bitmap.CompressFormat.PNG, 90, out); out.flush(); out.close(); return true; } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } } }
main布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.loaderman.signaturedemo.MainActivity"> <TextView android:id="@+id/tv_start" android:layout_width="match_parent" android:text="线上签名" android:gravity="center" android:textColor="@color/colorPrimary" android:textSize="18sp" android:textStyle="bold" android:background="#ddd" android:layout_height="40dp" /> <ImageView android:id="@+id/iv" android:background="#666" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
activity_signature.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.loaderman.signaturedemo.SignatureActivity"> <com.loaderman.signaturedemo.SignatureView android:id="@+id/sv" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@color/colorPrimary" android:gravity="center"> <Button android:id="@+id/btn_ok" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_margin="5dp" android:textColor="#fff" android:textStyle="bold" android:textSize="18sp" android:background="@color/colorAccent" android:text="确定" /> <Button android:id="@+id/btn_clear" android:layout_width="wrap_content" android:layout_height="40dp" android:textColor="#fff" android:textStyle="bold" android:textSize="18sp" android:background="@color/colorAccent" android:text="重签" /> </LinearLayout> </LinearLayout>
添加储存权限,配置签名时手机横屏显示
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.loaderman.signaturedemo"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SignatureActivity" android:screenOrientation="landscape" ></activity> </application> </manifest>
效果图:
源代码:https://github.com/loaderman/signaturedemo 喜欢请star哦