美文网首页
Android:实现签名功能

Android:实现签名功能

作者: 栩檬 | 来源:发表于2022-11-30 20:35 被阅读0次

    问题

    在 Android 应用中,如何实现签名功能?


    示例.jpg

    回答

    可以借助 signature-pad 库提供的 SignaturePad 控件来实现。

    效果

    效果.png

    简介

    Android Signature Pad is an Android library for drawing smooth signatures. It uses variable width Bézier curve interpolation based on Smoother Signatures post by Square.

    译:Android Signature Pad 是一个用于绘制签名的 Android 库。它基于 Square 发布的 Smoother Signatures 使用可变宽度的贝塞尔插值。

    Features

    • Bézier implementation for a smoother line
    • Variable point size based on velocity
    • Customizable pen color and size
    • Bitmap and SVG support
    • Data Binding

    译:

    特性

    • 贝塞尔插值绘制出更光滑的线条
    • 根据速率变化的线条粗细
    • 自定义画笔颜色和大小
    • 支持 Bitmap 和 SVG
    • 数据绑定 API

    注:下文代码是参考库的开发者的示例代码而写出的。如需进一步了解,请移步 SignaturePad-Example

    步骤

    1. 添加 signature-pad 库的依赖。
    dependencies {
        ...
        implementation 'com.github.gcacace:signature-pad:1.3.1'
        ...
    }
    
    1. 在 layout 文件中使用 SignaturePad 控件,另外添加“清空”和“保存”两个按钮。
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
            <variable
                name="listener"
                type="pers.xumeng.androidstudy.signature.SignatureActivity" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorActivityBackground">
    
            <TextView
                android:id="@+id/signature_tv_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="请在下方签名"
                android:textColor="@color/color_333333"
                android:textSize="@dimen/text_size3"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintVertical_bias="0.2" />
    
            <com.github.gcacace.signaturepad.views.SignaturePad
                android:id="@+id/signature_s_signature"
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:layout_margin="@dimen/common_margin"
                android:background="@drawable/rounded_rectangle_corner_10_color_white"
                android:padding="2dp"
                app:layout_constraintBottom_toTopOf="@id/signature_ll_button_bar"
                app:layout_constraintTop_toBottomOf="@id/signature_tv_message" />
    
            <LinearLayout
                android:id="@+id/signature_ll_button_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="@dimen/common_padding"
                app:layout_constraintBottom_toBottomOf="parent">
    
                <Button
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="@dimen/common_margin"
                    android:layout_weight="1"
                    android:background="@drawable/rounded_rectangle_corner_10_color_primary_border"
                    android:onClick="@{()->listener.clearSignature()}"
                    android:text="清空"
                    android:textColor="@color/colorPrimary"
                    android:textSize="@dimen/text_size3" />
    
                <Button
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="2"
                    android:background="@drawable/rounded_rectangle_corner_10_color_primary"
                    android:onClick="@{()->listener.attemptSaveSignature()}"
                    android:text="保存"
                    android:textColor="@android:color/white"
                    android:textSize="@dimen/text_size3" />
    
            </LinearLayout>
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    
    1. 实现清空 SignaturePad 控件内容的功能,在按钮的监听器中调用signaturepad.clear() 方法即可。
    public void clearSignature() {
        binding.signatureSSignature.clear();
    }
    
    1. 实现保存 SignaturePad 控件内容的功能:将控件上的内容保存为 .jpg 文件,并添加到相册。
    private void saveSignature() {
        Bitmap signatureBitmap = binding.signatureSSignature.getSignatureBitmap();
        if (addJpgSignatureToGallery(signatureBitmap)) {
          Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
          clearSignature();
        } else {
          Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show();
        }
    }
    

    4.1 检查外部存储权限,这一部分超出了本文的介绍范围。

    4.2 将 Bitmap 保存为 .jpg 图片,并添加到相册。

      private boolean addJpgSignatureToGallery(Bitmap signature) {
        boolean result = false;
        try {
          String fileName = String.format(Locale.CHINA, "Signature_%d.jpg", System.currentTimeMillis());
          File photo = new File(createAlbumStorageDirectory(), fileName);
          saveBitmapToJPG(signature, photo);
          scanMediaFile(photo);
          result = true;
        } catch (IOException e) {
          e.printStackTrace();
        }
        return result;
      }
    
    • 创建图片的保存目录
      private File createAlbumStorageDirectory() {
        // Get the directory for the user's public pictures directory.
        File parentDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        File directory = new File(parentDirectory, "Signature");
        boolean successful = directory.mkdirs();
        if (!successful) {
          LogUtil.e(TAG, "Directory not created");
        }
        return directory;
      }
    

    请注意,Environment.getExternalStoragePublicDirectory(String type) 在 API 29 被弃用了。如需了解详细信息,请参阅 getExternalStoragePublicDirectory

    • 将 Bitmap 保存为 .jpg 文件
      private void saveBitmapToJPG(Bitmap bitmap, File photo) throws IOException {
        Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(newBitmap);
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(bitmap, 0, 0, null);
        OutputStream stream = new FileOutputStream(photo);
        newBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
        stream.close();
      }
    
    • 通知扫描器将图片添加到媒体库
      private void scanMediaFile(File photo) {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        Uri contentUri = Uri.fromFile(photo);
        mediaScanIntent.setData(contentUri);
        sendBroadcast(mediaScanIntent);
      }
    

    需要注意的是, Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 在 API 29 被弃用了,替代方案是使用 MediaStore 。如需进一步了解,请参阅 ACTION_MEDIA_SCANNER_SCAN_FILE

    代码 XuMeng-0/android-study

    相关文章

      网友评论

          本文标题:Android:实现签名功能

          本文链接:https://www.haomeiwen.com/subject/tpdsfdtx.html