android - 如何在 kotlin 的滚动视图中实现人工签名视图?
问题描述
我需要在滚动视图中实现自定义签名视图。我的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_width="match_parent"
android:layout_height="200dp"
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;
}
}
解决方案
在您的 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);
}
推荐阅读
- python - 将 MNIST 数据从 numpy 数组转换为原始 ubyte 数据
- api - 带有翻译器消息的 Api 平台自定义异常
- html - 如何制作包含合并单元格的 HTML 表格
- typescript - 找不到名称“文档”。您需要更改目标库吗?尝试更改 `lib` 编译器选项以包含 'dom'.ts(2584)
- ios - 如何在 Apple Silicon ('M1') 上构建 Google Analytics SDK,使其在 Xcode Simulator 中运行?
- javascript - 如何使用传单从地图上删除标记?
- reactjs - 我试图通过在我的 React 应用程序中将它们设置为状态来显示 graphql 错误
- node.js - 使用 --experimental-modules 后出现“ESM 模块加载器是实验性的”的 NodeJs 错误
- android - Lateinit 字段在 Realm 中变为可选(对象中没有任何更改)
- google-colaboratory - 需要帮助在 Google Colab 上提取 Google 卡通数据集