Android 实现签字,截屏,保存本地相册功能

本文详细介绍了如何在Android应用中实现签字功能,包括自定义View、横屏设置、截屏以及将截屏图片保存到本地相册。通过监听按钮事件,截取屏幕并保存为Bitmap,最后完成图片的本地存储。

写在前面:

                      公司需求(万恶的公司需求),需要在客户端实现 签字的功能,需求的延伸 就牵引出了 截图,保存本地相册 最后再图片上传(我们讨论的结果是要截图 保存本地去上传的 或者直接 截图 上传 也是可以的)不知道贵公司的需求是怎么样的哦.....

1.需要权限

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

2.实现客户端签字,要用到自定义View,上代码!   注: 已经实现,摇动屏幕,文字自动消失(抹去)的功能

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class SignatureView extends View { 

        private static final float STROKE_WIDTH = 5f;

        /** Need to track this so the dirty region can accommodate the stroke. **/
        private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;

        private Paint paint = new Paint();
        private Path path = new Path();

        /**
         * Optimizes painting by invalidating the smallest possible area.
         */
        private float lastTouchX;
        private float lastTouchY;
        private final RectF dirtyRect = new RectF();

        public SignatureView(Context context, AttributeSet attrs) {
            super(context, attrs);

            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeJoin(Paint.Join.ROUND);
            paint.setStrokeWidth(STROKE_WIDTH);
        }

        /**
         * Erases the signature.
         */
        public void clear() {
            path.reset();

            // Repaints the entire view.
            invalidate();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawPath(path, paint);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float eventX = event.getX();
            float eventY = event.getY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    path.moveTo(eventX, eventY);
                    lastTouchX = eventX;
                    lastTouchY = eventY;
                    // There is no end point yet, so don't waste cycles invalidating.
                    return true;

                case MotionEvent.ACTION_MOVE:
                case MotionEvent.ACTION_UP:
                    // Start tracking the dirty region.
                    resetDirtyRect(eventX, eventY);

                    // When the hardware tracks events faster than they are delivered, the
                    // event will contain a history of those skipped points.
                    int historySize = event.getHistorySize();
                    for (int i = 0; i < historySize; i++) {
                        float historicalX = event.getHistoricalX(i);
                        float historicalY = event.getHistoricalY(i);
                        expandDirtyRect(historicalX, historicalY);
                        path.lineTo(historicalX, historicalY);
                    }

                    // After replaying history, connect the line to the touch point.
                    path.lineTo(eventX, eventY);
                    break;

                default:

                    return false;
            }

            // Include half the stroke width to avoid clipping.
            invalidate(
                    (int) (dirtyRect.left - HALF_STROKE_WIDTH),
                    (int) (dirtyRect.top - HALF_STROKE_WIDTH),
                    (int) (dirtyRect.right + HALF_STROKE_WIDTH),
                    (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

            lastTouchX = eventX;
            lastTouchY = eventY;

            return true;
        }

        /**
         * Called when replaying history to ensure the dirty region includes all
         * points.
         */
        private void expandDirtyRect(float historicalX, float historicalY) {
            if (historicalX < dirtyRect.left) {
                dirtyRect.left = historicalX;
            } else if (historicalX > dirtyRect.right) {
                dirtyRect.right = historicalX;
            }
            if (historicalY < dirtyRect.top) {
                dirtyRect.top = historicalY;
            } else if (historicalY > dirtyRect.bottom) {
                dirtyRect.bottom = historicalY;
            }
        }

        /**
         * Resets the dirty region when the motion event occurs.
         */
        private void resetDirtyRect(float eventX, float eventY) {

            // The lastTouchX and lastTouchY were set when the ACTION_DOWN
            // motion event occurred.
            dirtyRect.left = Math.min(lastTouchX, eventX);
            dirtyRect.right = Math.max(lastTouchX, eventX);
            dirtyRect.top = Math.min(lastTouchY, eventY);
            dirtyRect.bottom = Math.max(lastTouchY, eventY);
        }
    }

3.在布局中引用

<包名.SignatureView
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    />

4.签名,我们总不能竖屏签名 所以要横屏 

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

SCREEN_ORIENTATION_LANDSCAPE 始终横屏的意思  

 

5.至此,我们就能在屏幕上写字啦, 下面开始,就要做截屏了

 

6.绑定findViewByid 给一个Button, 给一个单击监听 

此处略过一万字......咳咳

7.截取屏幕代码

/**
 * 调用系统截图功能获取屏幕截图
 *
 * @return
 */
private Bitmap getScreenShot(View view) {
    view = getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    return view.getDrawingCache();
}

返回一个BitMap路径,View参数直接给Button的View就可以

8.获取完,BitMap的路径以后要保存到本地相册中 上代码

public static void saveImageToGallery(Context context, Bitmap bmp) {
    // 首先保存图片路径
    File appDir = new File(Environment.getExternalStorageDirectory(),
            "xiaoheiqun");
    if (!appDir.exists()) {
        appDir.mkdir();
    }
    //当前时间来命名图片
    String fileName = System.currentTimeMillis() + ".jpg";
    File file = new File(appDir, fileName);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    // 其次把文件插入到系统图库
    try {
        MediaStore.Images.Media.insertImage(context.getContentResolver(),
                file.getAbsolutePath(), fileName, null);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    // 最后通知图库更新
    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    Uri uri = Uri.fromFile(file);
    intent.setData(uri);
    context.sendBroadcast(intent);

    Toast.makeText(context, "图片保存到本地成功"+uri.toString(), Toast.LENGTH_SHORT).show(); 

}

 

    到此,这个功能就全部实现了

                                                                                                                     2019年7月8号 沈阳 夏夜

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值