編輯:關於Android編程
最近項目中有個新的需求,用戶在完交易需要進行輸入支付密碼付款的時候,要讓用戶簽下自己的簽名,提起到數字簽名這個東西,感覺有點高大上,後來想想數字簽名的原理也不是太復雜,主要實現原理就是利用了View的繪圖原理,把用戶在屏幕上的手指移動軌跡顯示在屏幕上,接著把在屏幕上顯示的軌跡View轉換成一張圖片,最後把圖片保存到本地或者上傳到服務器...
還是老規矩,首先看一下工程目錄吧:
public class DrawView extends View { /** * 簽名畫筆 */ private Paint paint; /** * 簽名畫布 */ private Canvas cacheCanvas; /** * 畫筆路徑 */ private Path path; /** * 緩存圖片 */ private Bitmap cacheBitmap; /** * 圖片寬度 */ private int width; /** * 圖片高度 */ private int height; /** * 手指觸摸屏幕時的X,Y坐標 */ private float xDown, yDown; /** * 是否正在繪制 */ private boolean isDrawing = false; /** * 默認畫筆顏色 */ private int paintColor = Color.CYAN; /** * 默認畫板背景色 */ private int canvasColor = Color.parseColor("#bbccaa"); public DrawView(Context context, int width, int height) { super(context); this.width = width; this.height = height; initWedgits(); } /** * 初始化組件 */ private void initWedgits() { try { paint = new Paint(Paint.DITHER_FLAG); // 設置抗鋸齒 paint.setAntiAlias(true); // 設置畫筆寬度 paint.setStrokeWidth(3); paint.setDither(true); // 設置樣式 paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); // 畫筆顏色 paint.setColor(paintColor); // 繪制路徑 path = new Path(); // 創建空緩存圖片 cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); // 把畫布內容畫到空緩存圖片上 cacheCanvas = new Canvas(cacheBitmap); } catch (Exception e) { e.printStackTrace(); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(canvasColor); canvas.drawBitmap(cacheBitmap, 0, 0, paint); canvas.drawPath(path, paint); } @Override public boolean onTouchEvent(MotionEvent event) { // 記錄手指摁下屏幕時的X坐標 final float x = event.getX(); // 記錄手指摁下屏幕時的Y坐標 final float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 手指摁下時清空之前的設置 path.reset(); // 設置路徑起始點 path.moveTo(x, y); xDown = x; yDown = y; isDrawing = true; break; case MotionEvent.ACTION_MOVE: // 移動下一點 path.quadTo(xDown, yDown, x, y); // 重新設置起點 xDown = x; yDown = y; isDrawing = true; break; case MotionEvent.ACTION_UP: path.lineTo(xDown, yDown); // 手指抬起時繪制路徑 cacheCanvas.drawPath(path, paint); // 路徑重置 path.reset(); isDrawing = false; break; default: break; } // 刷新界面 invalidate(); return true; } /** * 設置畫筆顏色 * * @param color * 畫筆顏色 */ public void setPaintColor(int color) { paintColor = color; } /** * 設置畫板顏色 * * @param color * 畫板顏色 */ public void setCanvasColor(int color) { canvasColor = color; } /** * 返回繪畫狀態 * * @return【true:正在繪制】【false:繪制完成】 */ public boolean getDrawState() { return isDrawing; } /** * 返回Bitmap * * @return 返回繪制的圖片 */ public Bitmap getBitmap() { return cacheBitmap; } }
DrawView的代碼注釋都很清晰,我還是大致說下DrawView的執行邏輯吧,DrawView繼承了View也就是說具有了View的所有功能,要實現圖片繪制就要實現onDraw()方法,要實現對手指在屏幕上的軌跡繪制就需要獲取軌跡坐標,所以需要重寫onTouchEvent()放法,重點在onTouchEvent()方法中。當手指摁下時我們繪制起點,但是在繪制起點前需要先調用path.reset()方法,防止path進行二次重繪,path的moveTo方法就是來繪制當前觸摸事件的起點,摁下完成之後調用inValidate()方法進行界面刷新。當手指移動時調用path.quadTo()方法,這個方法就是追加的意思,把新坐標點追加到path中,手指移動之後再調用inValidate()方法進行界面刷新,最後當手指抬起時,把在當前事件周期內的軌跡繪制到畫板cacheCanvas上,最後再調用inValidate()方法進行界面刷新,因此一次的手指移動軌跡就繪制完成,當要進行下一次的繪制,就是重復以上操作了...
接下來我們看看DrawView的使用吧,首先看一下布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffff"> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="請繪制簽名" android:textSize="18sp" android:layout_margin="5dip" android:gravity="center" android:textColor="#000000" /> <FrameLayout android:id="@+id/contents" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" android:layout_gravity="center" android:background="#aabbcc"> </FrameLayout> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="save" android:text="保存簽名" /> </LinearLayout>
乍一看布局文件中並沒有使用我們自定義的DrawView,不過不用著急我是使用了通過在FrameLayout中動態添加的方法把DrawView添加進來的,好了,那緊接著看看MainActivity中的代碼實現吧:
public class MainActivity extends Activity { private FrameLayout frameLayout; private DrawView drawView; private TextView title; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initWedgits(); } /** * 初始化組件 */ private void initWedgits() { try { frameLayout = (FrameLayout) findViewById(R.id.contents); title = (TextView) findViewById(R.id.title); title.setText(Html.fromHtml("<b>China中國<tt>中國</tt></b>China真偉大!")); } catch (Exception e) { e.printStackTrace(); } } @Override public void onWindowFocusChanged(boolean hasFocus) { drawView = new DrawView(MainActivity.this, frameLayout.getWidth(), frameLayout.getHeight()); frameLayout.addView(drawView); } /** * 保存圖片 * * @param view */ public void save(View view) { try { File file = new File(Environment.getExternalStorageDirectory() .getAbsolutePath() + "/handle.png"); if (file.exists()) { file.delete(); } file.createNewFile(); if (drawView.getBitmap().compress(CompressFormat.PNG, 100, new FileOutputStream(file))) { Toast.makeText(getApplicationContext(), "圖片保存成功", 1000).show(); } } catch (Exception e) { e.printStackTrace(); } } }
在MainActivity中的代碼沒什麼好解釋的,相信你一看就懂,最主要的是在save方法中使用了Bitmap的compress()方法,就是把圖片存儲在文件中,當我們簽名結束之後點擊保存簽名按鈕,簽名圖片就保存在了本地文件中了,當然了如果你想上傳到後台服務器也不難,就是使用個異步操作進行圖片上傳就行了...
說明:當你運行程序的時候,會看見China中國中國真偉大!的字樣,其中China和中國是加粗的效果,因為項目中有個需求讓把漢字也加粗,上網上找了些方法,但是都是對英文和數字有效果對中文暫時沒效果,我也是無意看源碼中的注釋,其中注釋裡邊有加粗的文字說明,我就點擊進去了,結果發現注釋裡的標簽是<tt></tt>,當時腦子一轉就想估計<tt>標簽可以實現對漢字的加粗效果,呵呵,功夫不付有心人,把<tt>標簽放到<b>裡邊已測試,果然有效果,呵呵,當時高興壞了,現在再高興一下,(*^__^*) 嘻嘻...
好了,現在我們運行程序來看一下效果圖吧:
繪制簽名:
當點擊了保存按鈕後,進入圖庫看看吧:
好了,數字簽名的講解到這裡了,謝謝大家的閱讀。
源碼下載: Android UI實現數字簽名效果
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
這一章很多,但是很有趣,也是這書的最後一章知識點了,我現在還在考慮要不要寫這個拼圖和2048的案例,在此之前,我們先來玩玩Android5.X的新特性吧!Android
小米電視2s定價在2999很大程度上是小米電視2s功能的刪減,其中大家最為關注的是砍掉了3D功能,3d功能可能不是每個人都需要,但是有總比沒有要好嗎?你說對
最近做了個自定義鍵盤,但面對不同分辨率的機型其中數字鍵盤不能根據界面大小自已鋪滿,但又不能每種機型都做一套吧,所以要做成自適應,那這裡主講思路。這裡最上面的titleba
https://github.com/hongyangAndroid/MagicViewPager實現效果:Rotate Y Rotate Dow