zoukankan      html  css  js  c++  java
  • 自定义控件之手势签名

    Android中,我们常用的控件,例如按钮(Button)、文本框(TextView,可编辑文本框(EditText,列表框(ListView,复选框(CheckBox,单选框(RadioButton,滚动条(Gallery,微调器(Spinner, 等等,还有一些比较先进的有着特殊用途的View组件,例如AutoCompleteTextView, ImageSwitcher TextSwitcher。除此之外,种类繁多的像 线性布局(LinearLayout, 框架布局(FrameLayout, 这样的布局组件(Layout)也被认为是View组件,他们是从View类派生过来的。本文呢,我们就先创建一个网络签名的控件SignatureView,具体的理论,本文就先不介绍这么多了,有点饿了,赶紧写完去吃饭,下次再详细研究下里面的理论知识。好,开始我们的实验。

     

    第一步:创建自定义控件SignatureView.java

     

     

     

    package com.figo.helloworld;

     

    import android.content.Context;

    import android.graphics.Bitmap;

    import android.graphics.Canvas;

    import android.graphics.Color;

    import android.graphics.Paint;

    import android.graphics.Path;

    import android.util.AttributeSet;

    import android.view.MotionEvent;

    import android.view.View;

     

    /**

     * 自定义签名控件

     *

     * @author zhuzhifei

     * 版权所有 20120912

     */

    public class SignatureView extends View {

             private Bitmap mBitmap;// 绘成的图片

             private Canvas mCanvas;// 画布

             private Path mPath;// 绘图路径

             private Paint mBitmapPaint;// 绘制图片的画笔

             private Paint mPathPaint;// 绘制路径的画笔

             private float mX, mY;// 坐标

             private static final float TOUCH_TOLERANCE = 4;// 公差4dp

     

             // 构造函数

             public SignatureView(Context context) {

                       super(context);

                       init();

             }

     

             // 构造函数

             public SignatureView(Context context, AttributeSet attrs) {

                       super(context, attrs);

                       init();

             }

     

             // 构造函数

             public SignatureView(Context context, AttributeSet attrs, int defStyle) {

                       super(context, attrs, defStyle);

                       init();

             }

     

             // 新建绘图路径,画笔,和画布

             private void init() {

                       mPath = new Path();// 绘图路径

                       mBitmapPaint = new Paint(Paint.DITHER_FLAG);// 绘制图片的画笔

                       mPathPaint = new Paint();// 绘制路径的画笔

                       mPathPaint.setAntiAlias(true);

                       mPathPaint.setDither(true);

                       mPathPaint.setColor(0xFF000000);// 颜色

                       mPathPaint.setStyle(Paint.Style.STROKE);// 样式 线条

                       mPathPaint.setStrokeJoin(Paint.Join.ROUND);

                       mPathPaint.setStrokeCap(Paint.Cap.ROUND);

                       mPathPaint.setStrokeWidth(7);// 笔画宽度

             }

     

             // 测量手机屏幕宽度和高度

             protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

                       super.onMeasure(widthMeasureSpec, heightMeasureSpec);

                       this.createBitmap();

             }

     

             // 生成签名图片

             protected void createBitmap() {

                       if (mBitmap != null) {

                                return;

                       }

                       mBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),

                                         Bitmap.Config.ARGB_8888);

                       mBitmap.eraseColor(Color.TRANSPARENT);

                       mCanvas = new Canvas(mBitmap);

             }

     

             @Override

             protected void onSizeChanged(int w, int h, int oldw, int oldh) {

                       super.onSizeChanged(w, h, oldw, oldh);

             }

     

             // 绘制视图

             @Override

             protected void onDraw(Canvas canvas) {

                       canvas.drawColor(Color.TRANSPARENT);

     

                       canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

     

                       canvas.drawPath(mPath, mPathPaint);

             }

     

             // 开始绘制

             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);// 路径到达终点坐标

                       mCanvas.drawPath(mPath, mPathPaint);// 通过路径,在画布上画图

                       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();// 绘制结束更新视图,触发ondraw事件

                                break;

                       case MotionEvent.ACTION_MOVE:// 手指移动

                                touch_move(x, y);

                                invalidate();

                                break;

                       case MotionEvent.ACTION_UP:// 手指释放

                                touch_up();

                                invalidate();

                                break;

                       }

                       return true;

             }

     

             // 清除之前画的图像

             public void clearSignature() {

                       mBitmap.eraseColor(Color.TRANSPARENT);

                       invalidate();

             }

     

             // 获取画好的图像

             public Bitmap getSignatureBitmap() {

                       return mBitmap;

             }

    }

    第二步:设计Activity对应的布局页面signature.xml

    <?xml version="1.0" encoding="utf-8"?>

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent" >

     

        <com.figo.helloworld.SignatureView

            android:id="@+id/signatureView1"

            android:layout_width="fill_parent"

            android:layout_height="180dp"

            android:layout_alignParentLeft="true"

            android:background="@drawable/sign_tip" />

     

        <Button

            android:id="@+id/btnSave"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_alignParentRight="true"

            android:layout_below="@+id/signatureView1"

            android:layout_marginRight="104dp"

            android:layout_marginTop="55dp"

             android:onClick="onSaveClick"

            android:text="     " />

     

        <Button

            android:id="@+id/btnReset"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_alignBaseline="@+id/btnSave"

            android:layout_alignBottom="@+id/btnSave"

            android:layout_marginRight="34dp"

            android:layout_toLeftOf="@+id/btnSave"

            android:onClick="onResetClick"

            android:text="     " />

     

        <ImageView

            android:id="@+id/imgShow"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_alignParentLeft="true"

            android:layout_below="@+id/btnReset"

            android:layout_marginTop="18dp"

            android:background="@drawable/sign_tip"/>

     

    </RelativeLayout>

     

    第三步:创建Acitivity  SignatureActivity.java 这个activity里面我们将引用上面创建的控件

     

    package com.figo.helloworld;

     

    import java.io.File;

    import java.io.FileOutputStream;

    import java.io.IOException;

    import java.text.SimpleDateFormat;

    import java.util.Date;

     

    import android.app.Activity;

    import android.graphics.Bitmap;

    import android.graphics.Matrix;

    import android.net.Uri;

    import android.os.Bundle;

    import android.os.Environment;

    import android.view.View;

    import android.widget.ImageView;

     

    /**

     * 使用自定义绘图控件 签名、保存签名图片、显示签名

     *

     * @author zhuzhifei 版权所有 20120912

     */

    public class SignatureActivity extends Activity {

             SignatureView sigView = null;

             private Bitmap newSigBmp = null;

             private ImageView image;

     

             public void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.signature);

                       initView();

     

             }

     

             private void initView() {

                       sigView = (SignatureView) findViewById(R.id.signatureView1);

                       image = (ImageView) findViewById(R.id.imgShow);

     

             }

     

             public void onResetClick(View view) {

                       sigView.clearSignature();

             }

     

             public void onSaveClick(View view) throws IOException {

                       // 判断是否有签名后再操作...

                       Bitmap bitMap = sigView.getSignatureBitmap();

                       // 方法一:直接显示

                       // image.setImageBitmap(bitMap);

                       // 方法二:保存后再显示

                       newSigBmp = scaleToNewBitmap(bitMap, 0.3f);

                       SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

                       String fn = df.format(new Date());

                       String path = saveBitmapToPngFile(newSigBmp, fn);

                       image.setImageURI(Uri.parse(path));

     

             }

     

             // 更换图片尺寸

             private Bitmap scaleToNewBitmap(Bitmap origin, float scaleRate) {

                       Matrix matrix = new Matrix();

                       matrix.postScale(scaleRate, scaleRate);

                       Bitmap newBitmap = Bitmap.createBitmap(origin, 0, 0, origin.getWidth(),

                                         origin.getHeight(), matrix, true);

                       return newBitmap;

             }

     

             // bmp格式图片转换成png格式,同时保存到sdcard/Sign这个文件夹里面

             private String saveBitmapToPngFile(Bitmap b, String name) {

                       String currentPath = Environment.getExternalStorageDirectory()

                                         .getAbsolutePath() + "/Sign";

                       FileOutputStream fos = null;

                       try {

                                File sddir = new File(currentPath);

                                if (!sddir.exists()) {

                                         sddir.mkdirs();

                                }

                                File file = new File(currentPath + "/" + name + ".png");

                                if (file.exists()) {

                                         file.delete();

                                }

                                file.createNewFile();

                                fos = new FileOutputStream(file);

                                if (fos != null) {

                                         b.compress(Bitmap.CompressFormat.PNG, 50, fos);

                                         fos.close();

                                }

                                return currentPath + "/" + name + ".png";

                       } catch (Exception e) {

                                e.printStackTrace();

                       }

                       return currentPath;

     

             }

    }

     

    第四步:AndroidManifest.xml 注册Acitivity和设置写sdcard的权限

     

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

        <application

            android:icon="@drawable/ic_launcher"

            android:label="@string/app_name" >

            <activity

                android:name=".SignatureActivity"

                android:label="@string/app_name" >

                <intent-filter>

                    <action android:name="android.intent.action.MAIN" />

     

                    <category android:name="android.intent.category.LAUNCHER" />

                </intent-filter>

            </activity>

    </application>

     

    第五步:运行效果

    点击保存后,签名图片写入sdcard,同时将图片显示在下面的一个imageView里面

  • 相关阅读:
    友元程序集
    反射与dynamic
    GetHashCode作用
    论immutable不可变性
    GetCursorPos函数的使用方法、应用实例(转)
    WIN32 创建线程CreateThread
    动态链接库两种定义方式
    WIN32硬盘文件映射到内存CreateFileMapping
    CreateFileMapping和MapViewOfFile
    WIN32 卷 目录 文件 操作
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3060112.html
Copyright © 2011-2022 走看看