如何在 kotlin 的滚动视图中实现人类签名视图?

Posted

技术标签:

【中文标题】如何在 kotlin 的滚动视图中实现人类签名视图?【英文标题】:How to implement human signature view inside a scroll view in kotlin? 【发布时间】:2021-05-27 19:09:19 【问题描述】:

我需要在滚动视图中实现一个自定义签名视图。我的xml文件的结构是这样的

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
>
    <ScrollView>
        <androidx.constraintlayout.widget.ConstraintLayout>
          //bunch of linear layouts and textviews
            <LinearLayout
                android:id="@+id/linearLayoutSignature"
                android:layout_
                android:layout_
                android:layout_marginTop="10dp"
                android:orientation="vertical"
                app:layout_constraintTop_toBottomOf="@+id/imageView3"
                tools:ignore="MissingConstraints">
            </LinearLayout>
         //some buttons and textfields
 </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

现在,当我在签名视图画布内左右移动时,一切都很好。但是当我向上或向下移动时,滚动会移动,我无法绘制。有没有办法在不将我的签名视图移到滚动视图之外的情况下实现这一点?有没有办法在签名布局处于活动状态时冻结它,所以在我绘制签名时它不会向上或向下滚动?

CaptureSignature.java

package com.example.app_ptt.services;

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;

import java.io.ByteArrayOutputStream;

public class CaptureSignature extends View 

    private Bitmap _Bitmap;
    private Canvas _Canvas;
    private Path _Path;
    private Paint _BitmapPaint;
    private Paint _paint;
    private float _mX;
    private float _mY;
    private float TouchTolerance = 4;
    private float LineThickness = 4;

    public CaptureSignature(Context context, AttributeSet attr) 
        super(context, attr);
        _Path = new Path();
        _BitmapPaint = new Paint(Paint.DITHER_FLAG);
        _paint = new Paint();
        _paint.setAntiAlias(true);
        _paint.setDither(true);
        _paint.setColor(Color.argb(255, 0, 0, 0));
        _paint.setStyle(Paint.Style.STROKE);
        _paint.setStrokeJoin(Paint.Join.ROUND);
        _paint.setStrokeCap(Paint.Cap.ROUND);
        _paint.setStrokeWidth(LineThickness);
    

    public CaptureSignature(Context context) 
        super(context);
    

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) 
        super.onSizeChanged(w, h, oldw, oldh);
        _Bitmap = Bitmap.createBitmap(w, (h > 0 ? h : ((View) this.getParent()).getHeight()), Bitmap.Config.ARGB_8888);
        _Canvas = new Canvas(_Bitmap);
    

    @Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        canvas.drawBitmap(_Bitmap, 0, 0, _BitmapPaint);
        canvas.drawPath(_Path, _paint);
    

    private void TouchStart(float x, float y) 
        _Path.reset();
        _Path.moveTo(x, y);
        _mX = x;
        _mY = y;
    

    private void TouchMove(float x, float y) 
        float dx = Math.abs(x - _mX);
        float dy = Math.abs(y - _mY);

        if (dx >= TouchTolerance || dy >= TouchTolerance) 
            _Path.quadTo(_mX, _mY, (x + _mX) / 2, (y + _mY) / 2);
            _mX = x;
            _mY = y;
        
    

    private void TouchUp() 
        if (!_Path.isEmpty()) 
            _Path.lineTo(_mX, _mY);
            _Canvas.drawPath(_Path, _paint);
         else 
            _Canvas.drawPoint(_mX, _mY, _paint);
        

        _Path.reset();
    

    @Override
    public boolean onTouchEvent(MotionEvent e) 
        super.onTouchEvent(e);
        float x = e.getX();
        float y = e.getY();

        switch (e.getAction()) 
            case MotionEvent.ACTION_DOWN:
                TouchStart(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                TouchMove(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                TouchUp();
                invalidate();
                break;
        

        return true;
    

    public void ClearCanvas() 
        _Canvas.drawColor(Color.WHITE);
        invalidate();
    

    public byte[] getBytes() 
        Bitmap b = getBitmap();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        b.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    

    public Bitmap getBitmap() 
        View v = (View) this.getParent();
        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(b);
        v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
        v.draw(c);

        return b;
    


【问题讨论】:

查看此链接希望对您有所帮助***.com/questions/30525066/… 或提供您的自定义签名类代码听到 我添加了签名类,请看一下。 【参考方案1】:

在您的 CaptureSignature 类中尝试此 Override 方法副本并检查

@Override
    public boolean onTouchEvent(final MotionEvent event) 
        switch (event.getAction()) 
            case MotionEvent.ACTION_DOWN:

                getParent().getParent().requestDisallowInterceptTouchEvent(true);

                break;
            case MotionEvent.ACTION_UP:

                getParent().getParent().requestDisallowInterceptTouchEvent(false);


                break;
            default:
                break;
        

        return super.onTouchEvent(event);
    

【讨论】:

以上是关于如何在 kotlin 的滚动视图中实现人类签名视图?的主要内容,如果未能解决你的问题,请参考以下文章

当用户滚动时如何显示或隐藏日期文本视图就像whatsapp聊天android Kotlin

如何使用自动滚动制作水平滚动文本视图?

如何使用 kotlin 实现分页

如何在 Kotlin 的卡片视图中设置属性

自定义视图在滚动视图内滚动

如何实现在动态布局中添加更多视图在android中实现滚动视图