关闭。这个问题需要更加突出重点。它目前不接受答案。
**想改进这个问题吗?**通过编辑这篇文章更新这个问题,使它只关注一个问题。
8天前关门了。
改进这个问题
如何在平板电脑设备上通过自由手写在pdf上绘制线条、文本?
我想保存编辑的pdf版本历史记录。因此,如果用户想查看历史,那么用户可以检查它。
我在这里面临着pdf质量问题:当我从版面生成pdf时,pdf质量太低。
我正在使用androidpdfviewer库打开pdf,并在pdfview上创建canvasdrawingview来绘制和删除。
活动\u drawing.xml:
<com.exmple.pdfdrawing.ZoomLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:id="@+id/zoomLayout"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvTime"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout"
>
<com.github.barteksc.pdfviewer.PDFView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/pdfView"
android:clickable="false"
/>
<com.example.pdfdrawing.CanvasDrawingView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:id="@+id/drawingView"
/>
</FrameLayout>
</ com.exmple.pdfdrawing.ZoomLayout>
zoom layout用于缩放pdfview和canvasdrawingview,这样我们就可以准确地在所需的位置写入/绘制。
zoomlayout.java文件:
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {
private enum Mode {
NONE,
DRAG,
ZOOM
}
private static final String TAG = "ZoomLayout";
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 5.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
// Where the finger first touches the screen
private float startX = 0f;
private float startY = 0f;
// How much to translate the canvas
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
public ZoomLayout(Context context) {
super(context);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "DOWN");
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = motionEvent.getX() - prevDx;
startY = motionEvent.getY() - prevDy;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == Mode.DRAG) {
dx = motionEvent.getX() - startX;
dy = motionEvent.getY() - startY;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = Mode.ZOOM;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = Mode.DRAG;
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "UP");
mode = Mode.NONE;
prevDx = dx;
prevDy = dy;
break;
}
scaleDetector.onTouchEvent(motionEvent);
if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale))/ 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
+ ", max " + maxDx);
applyScaleAndTranslation();
}
return true;
}
});
}
// ScaleGestureDetector
@Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleBegin");
return true;
}
@Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
Log.i(TAG, "onScale" + scaleFactor);
if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
scale *= scaleFactor;
scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
lastScaleFactor = scaleFactor;
} else {
lastScaleFactor = 0;
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleEnd");
}
private void applyScaleAndTranslation() {
child().setScaleX(scale);
child().setScaleY(scale);
child().setTranslationX(dx);
child().setTranslationY(dy);
}
public void resetLayout(){
Log.d(TAG,"reset layout called");
scale=1.0f;
dx=0f;
dy=0f;
applyScaleAndTranslation();
}
private View child() {
return getChildAt(0);
}
}
canvasdrawingview.java:
public class CanvasDrawingView extends View {
private Context context;
private static final float STROKE_WIDTH = 2f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Path m_path = new Path();
private float m_lastTouchX;
private float m_lastTouchY;
private final RectF m_dirtyRect = new RectF();
private Paint m_paint = new Paint();
private int currentColor;
private boolean eraserMode=false;
private boolean brushMode=false;
private boolean penMode=true;
private boolean editMode=false;
LinkedHashMap<Path, Paint> pathMap = new LinkedHashMap<>();
public CanvasDrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
setLayerType(LAYER_TYPE_HARDWARE, null);
currentColor=Color.RED;
m_paint.setAntiAlias(true);
m_paint.setColor(currentColor);
m_paint.setStyle(Paint.Style.STROKE);
m_paint.setStrokeJoin(Paint.Join.ROUND);
m_paint.setStrokeWidth(STROKE_WIDTH);
m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
m_paint.setAntiAlias(true);
m_paint.setDither(true);
}
@Override
protected void onDraw(Canvas canvas) {
getParent().requestDisallowInterceptTouchEvent(true);
if(pathMap!=null){
for(Path p: pathMap.keySet()){
canvas.drawPath(p,pathMap.get(p));
}
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(editMode){
float m_eventX = event.getX();
float m_eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
m_path=new Path();
Paint newPaint;
if(eraserMode){
newPaint= getEraserPaint();
} else if(brushMode){
newPaint= getBrushPaint();
}else{
newPaint = getPenPaint();
}
// m_paint.setColor(currentColor);
pathMap.put(m_path,newPaint);
m_path.moveTo(m_eventX, m_eventY);
m_lastTouchX = m_eventX;
m_lastTouchY = m_eventY;
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
resetDirtyRect(m_eventX, m_eventY);
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++) {
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
m_path.lineTo(historicalX, historicalY);
}
m_path.lineTo(m_eventX, m_eventY);
// m_path= new Path();
break;
default:
return false;
}
invalidate((int) (m_dirtyRect.left - HALF_STROKE_WIDTH),
(int) (m_dirtyRect.top - HALF_STROKE_WIDTH),
(int) (m_dirtyRect.right + HALF_STROKE_WIDTH),
(int) (m_dirtyRect.bottom + HALF_STROKE_WIDTH));
m_lastTouchX = m_eventX;
m_lastTouchY = m_eventY;
return true;
} else{
return false;
}
}
public void setEditMode(boolean editMode) {
this.editMode = editMode;
}
private Paint getEraserPaint() {
Paint erasePaint = new Paint();
erasePaint.setAntiAlias(true);
// erasePaint.setColor(getResources().getColor(android.R.color.transparent));
erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
erasePaint.setColor(Color.WHITE);
erasePaint.setStyle(Paint.Style.STROKE);
erasePaint.setStrokeJoin(Paint.Join.ROUND);
erasePaint.setStrokeWidth(6f);
erasePaint.setAntiAlias(true);
erasePaint.setDither(true);
return erasePaint;
}
private Paint getPenPaint() {
Paint penPaint = new Paint();
penPaint.setAntiAlias(true);
penPaint.setColor(currentColor);
penPaint.setStyle(Paint.Style.STROKE);
penPaint.setStrokeJoin(Paint.Join.ROUND);
penPaint.setStrokeWidth(STROKE_WIDTH);
penPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
penPaint.setAntiAlias(true);
penPaint.setDither(true);
return penPaint;
}
private Paint getBrushPaint() {
Paint brushPaint = new Paint();
brushPaint.setAntiAlias(true);
brushPaint.setColor(currentColor);
brushPaint.setStyle(Paint.Style.STROKE);
brushPaint.setStrokeJoin(Paint.Join.ROUND);
brushPaint.setStrokeWidth(15f);
brushPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
brushPaint.setAntiAlias(true);
brushPaint.setDither(true);
return brushPaint;
}
private void expandDirtyRect(float historicalX, float historicalY) {
if (historicalX < m_dirtyRect.left) {
m_dirtyRect.left = historicalX;
} else if (historicalX > m_dirtyRect.right) {
m_dirtyRect.right = historicalX;
}
if (historicalY < m_dirtyRect.top) {
m_dirtyRect.top = historicalY;
} else if (historicalY > m_dirtyRect.bottom) {
m_dirtyRect.bottom = historicalY;
}
}
private void resetDirtyRect(float eventX, float eventY) {
m_dirtyRect.left = Math.min(m_lastTouchX, eventX);
m_dirtyRect.right = Math.max(m_lastTouchX, eventX);
m_dirtyRect.top = Math.min(m_lastTouchY, eventY);
m_dirtyRect.bottom = Math.max(m_lastTouchY, eventY);
}
public void setPaintColor(String color){
m_paint=null;
m_paint=new Paint();
m_paint.setStyle(Paint.Style.STROKE);
m_paint.setStrokeJoin(Paint.Join.ROUND);
m_paint.setStrokeWidth(STROKE_WIDTH);
m_paint.setColor(Color.parseColor(color));
}
public void setCurrentColor(int color){
currentColor=color;
}
public void setEraserMode(boolean eraserMode){
this.eraserMode=eraserMode;
}
public void setBrushMode(boolean brushMode){
this.brushMode=brushMode;
}
public void setPenMode(boolean penMode){
this.penMode=penMode;
}
}
现在,当我使用以下代码从framelayout生成pdf时,pdf质量太低(可能取决于设备分辨率):
drawingactivity.java文件:
public void saveToPDF(){
FrameLayout contentView=(FrameLayout) findViewById(R.id.frameLayout);
float orginalPDFHeight= contentView.getHeight();
float orginalPDFWidth= contentView.getWidth();
PdfDocument pdfDocument = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder((int)orginalPDFWidth,(int) orginalPDFHeight,0).create();
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
Canvas pageCanvas = page.getCanvas();
pageCanvas.scale(1f,1f);
contentView.draw(pageCanvas);
pdfDocument.finishPage(page);
File applicationPath = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
String targetPdf = applicationPath+"/test.pdf";
File filePath = new File(targetPdf);
try {
pdfDocument.writeTo(new FileOutputStream(filePath));
Toast.makeText(this, "Done", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(this, "Something wrong: " + e.toString(), Toast.LENGTH_LONG).show();
}
pdfDocument.close();
}
这里有什么解决办法?另外,指导我,如果有任何其他方式做,非常感谢它。提前谢谢。
pdf质量:
原始pdf:https://drive.google.com/file/d/1dnfgq1qjdbslnzo_j_ds8ugloeuu2jwl/view?usp=sharing
版本1 pdf:https://drive.google.com/file/d/19doz4ywygit1r488elvffdgassu5lrot/view?usp=sharing
暂无答案!
目前还没有任何答案,快来回答吧!