【问题标题】:Android custom view update specified part of viewAndroid自定义视图更新指定部分视图
【发布时间】:2017-07-20 15:12:44
【问题描述】:

我通过从AppCompatImageView扩展一个类来实现一个绘画应用程序,它工作得很好,但是当绘制很多路径时,它的速度会降低

是否可以在绘制任何新路径时,只绘制添加到视图中的新路径?

换句话说,只更新视图的特定部分,而不必每次都更新所有视图。

PaintView.java

import android.content.Context;
import android.graphics.*;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Stack;


public class PaintView extends AppCompatImageView implements View.OnTouchListener {

   private int defaultColor = 0xffff0000;
   private int defaultLineStrokeWidth = 4;
   private int defaultAlpha = 255;
   private int currentPathIndex = 0;
   private boolean isTouchDown = false;
   private boolean showBounds = false;
   private boolean isDeleteMode = false;

   private Paint linePaint;
   private Paint rectPaint;
   private Stack<PathHolder> paths;
   private Stack<PathHolder> memoryList;

   public GestureView(Context context) {
      super(context);
      init();
   }

   public GestureView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init();
   }

   public GestureView(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      init();
   }

   private void init() {
      setOnTouchListener(this);

      setBackgroundColor(Color.WHITE);

      linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      linePaint.setStrokeWidth(defaultLineStrokeWidth);
      linePaint.setDither(true);
      linePaint.setAntiAlias(true);
      linePaint.setColor(Color.BLACK);
      linePaint.setStyle(Paint.Style.STROKE);
      linePaint.setStrokeCap(Paint.Cap.ROUND);
      linePaint.setStrokeJoin(Paint.Join.ROUND);
      linePaint.setPathEffect(new CornerPathEffect(10));

      rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
      rectPaint.setStrokeWidth(0.5f);
      rectPaint.setAntiAlias(true);
      rectPaint.setColor(Color.RED);
      rectPaint.setStyle(Paint.Style.STROKE);

      paths = new Stack<>();
      memoryList = new Stack<>();
   }

   public void setPaintColor(@ColorInt int color) {
      defaultColor = color;
   }

   public void showBounds(boolean show) {
      showBounds = show;
      invalidate();
   }

   public void setDeleteMode(boolean deleteMode) {
      this.isDeleteMode = deleteMode;
      invalidate();
   }

   public void setLineStrokeWidth(int width) {
      if (width > 0) {
         defaultLineStrokeWidth = width;
      } else {
         Log.e("GestureView", "Stroke width can't be zero or less.");
      }
   }

   public void setLineAlpha(@IntRange(from = 0, to = 255) int alpha) {
      defaultAlpha = alpha;
   }

   public int getDefaultLineStrokeWidth() {
      return defaultLineStrokeWidth;
   }

   public void clearScreen() {
      currentPathIndex = 0;
      paths.clear();
      memoryList.clear();

      invalidate();
   }

   @Override
   protected void onDraw(Canvas canvas) {
      if (paths.size() > 0) {
         for (int i = 0; i < paths.size(); i++) {
            paths.get(i).setColor(paths.get(i).getColor() != 0 ? paths.get(i).getColor() : defaultColor);
            paths.get(i).setStrokeWidth(paths.get(i).getStrokeWidth() != 0 ? paths.get(i).getStrokeWidth() : defaultLineStrokeWidth);
            paths.get(i).setAlpha(paths.get(i).getAlpha() != 0 ? paths.get(i).getAlpha() : defaultAlpha);

            linePaint.setColor(paths.get(i).getColor());
            linePaint.setStrokeWidth(paths.get(i).getStrokeWidth());
            linePaint.setAlpha(paths.get(i).getAlpha());

            canvas.drawPath(paths.get(i).getPath(), linePaint);
            paths.get(i).getPath().computeBounds(paths.get(i).getRect(), true);

            if (showBounds && (!isTouchDown || currentPathIndex != i)) {
               canvas.drawRect(paths.get(i).getRect(), rectPaint);
            }
         }
      }
   }

   @Override
   public boolean onTouch(View view, MotionEvent motionEvent) {
      if (isDeleteMode) {
         for (int i = 0; i < paths.size(); i++) {
            if (RectF.intersects(paths.get(i).getRect(), new RectF(motionEvent.getX(), motionEvent.getY(), motionEvent.getX(), motionEvent.getY()))) {
               memoryList.push(paths.get(i));
               paths.remove(i);
               currentPathIndex--;
               invalidate();
               break;
            }
         }
      } else {
         switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:
               isTouchDown = true;

               Path path = new Path();
               path.moveTo(motionEvent.getX(), motionEvent.getY());

               RectF rectF = new RectF();
               path.computeBounds(rectF, true);

               PathHolder pathHolder = new PathHolder();
               pathHolder.setPath(path);
               pathHolder.setRect(rectF);

               paths.add(currentPathIndex, pathHolder);
               break;

            case MotionEvent.ACTION_UP:
               isTouchDown = false;
               paths.get(currentPathIndex).getPath().lineTo(motionEvent.getX(), motionEvent.getY());
               currentPathIndex++;
               invalidate();
               break;

            case MotionEvent.ACTION_MOVE:
               paths.get(currentPathIndex).getPath().lineTo(motionEvent.getX(), motionEvent.getY());
               invalidate();
               break;
         }
      }
      return true;
   }

   public void undo() {
      if (paths.isEmpty()) {
         return;
      }
      memoryList.push(paths.pop());
      currentPathIndex--;
      invalidate();
   }

   public void redo() {
      if (memoryList.isEmpty()) {
         return;
      }
      paths.push(memoryList.pop());
      currentPathIndex++;
      invalidate();
   }

   public Bitmap getCaptureBitmap() {
      setDrawingCacheEnabled(true);
      return getDrawingCache();
   }

   public void saveCaptureTo(String path, int quality) {
      Bitmap b = getCaptureBitmap();
      try {
         b.compress(Bitmap.CompressFormat.PNG, quality, new FileOutputStream(path));
      } catch (FileNotFoundException e) {
         Log.e(GestureView.class.getSimpleName(), e.getMessage());
      }
   }
}

【问题讨论】:

    标签: java android draw android-custom-view


    【解决方案1】:

    因此,当您在 Canvas 上绘图时,您必须再次绘制整个 Canvas。据我了解,每次调用 onDraw (60ps) 时,您基本上都是在一张新纸上绘图

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2023-03-19
      相关资源
      最近更新 更多