मुझे यह कोड उन प्रश्नों में से एक में मिला है जो एंड्रॉइड में आकर्षित करने के लिए कह रहे थे, लेकिन फिर इसका उपयोग करते समय और मेरे ऐप में इसका परीक्षण करते समय, मुझे पता चला कि यह कुशल नहीं है बड़ी चीजें या कई पथ ड्राइंग। समस्या onDraw
के अंदर कोड से आती है क्योंकि प्रत्येक बार invalidate()
को onDraw
कहा जाता है, जिसमें एक लूप होता है जो paths
को canvas
पर फिर से खींचता है, और इसमें अधिक पथ जोड़कर, यह बहुत धीमा हो जाता है।एंड्रॉइड ड्रॉइंग व्यू बहुत धीमा है
यहाँ क्लास है:
public class DrawingView extends View implements OnTouchListener {
private Canvas m_Canvas;
private Path m_Path;
private Paint m_Paint;
ArrayList<Pair<Path, Paint>> paths = new ArrayList<Pair<Path, Paint>>();
ArrayList<Pair<Path, Paint>> undonePaths = new ArrayList<Pair<Path, Paint>>();
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
public static boolean isEraserActive = false;
private int color = Color.BLACK;
private int stroke = 6;
public DrawingView(Context context, AttributeSet attr) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
setBackgroundColor(Color.WHITE);
this.setOnTouchListener(this);
onCanvasInitialization();
}
public void onCanvasInitialization() {
m_Paint = new Paint();
m_Paint.setAntiAlias(true);
m_Paint.setDither(true);
m_Paint.setColor(Color.parseColor("#000000"));
m_Paint.setStyle(Paint.Style.STROKE);
m_Paint.setStrokeJoin(Paint.Join.ROUND);
m_Paint.setStrokeCap(Paint.Cap.ROUND);
m_Paint.setStrokeWidth(2);
m_Canvas = new Canvas();
m_Path = new Path();
Paint newPaint = new Paint(m_Paint);
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
@Override
public void setBackground(Drawable background) {
mBackground = background;
super.setBackground(background);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
public boolean onTouch(View arg0, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
for (Pair<Path, Paint> p : paths) {
canvas.drawPath(p.first, p.second);
}
}
private void touch_start(float x, float y) {
if (isEraserActive) {
m_Paint.setColor(Color.WHITE);
m_Paint.setStrokeWidth(50);
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
} else {
m_Paint.setColor(color);
m_Paint.setStrokeWidth(stroke);
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
m_Path.reset();
m_Path.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
m_Path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
m_Path.lineTo(mX, mY);
// commit the path to our offscreen
m_Canvas.drawPath(m_Path, m_Paint);
// kill this so we don't double draw
m_Path = new Path();
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
public void onClickUndo() {
if (!paths.isEmpty()) {//paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
undo = true;
invalidate();
}
}
public void onClickRedo() {
if (!undonePaths.isEmpty()){//undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
undo = true;
invalidate();
}
}}
लेकिन मैं इंटरनेट पर खोज की फिर से बैठक के लिए एक बेहतर तरीका खोजने के लिए, तो मैं निम्नलिखित पाया:
1 निर्माता के लिए निम्न जोड़ें:
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
m_Canvas = new Canvas(mBitmap);
}
01:
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
2 अवहेलना निम्न कोड के साथ onSizeChanged
3 OnDraw में डाल इस:
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (!paths.isEmpty())
canvas.drawPath(paths.get(paths.size() - 1).first, paths.get(paths.size() - 1).second);
}
यह दृष्टिकोण काम करता है और यह दृश्य को धीमा नहीं करता है, लेकिन इस दृष्टिकोण के साथ समस्या यह है कि मैं पूर्ववत नहीं हो सकता है और कार्यक्षमताओं फिर से करना है।
मैंने दूसरे दृष्टिकोण के साथ पूर्ववत करने और फिर से करने के लिए कई चीजों की कोशिश की, लेकिन मैं इसे नहीं कर सका। तो मैं यहां जो कुछ पूछ रहा हूं वह तीन चीजों में से एक है: 1. दूसरे दृष्टिकोण के साथ पूर्ववत करने और फिर से करने का एक तरीका 2. एक अन्य दृष्टिकोण जो पूर्ववत करना और को फिर से करना संभव बनाता है 3. एक पूरी नई कक्षा जिसमें सब कुछ पहले से ही किया गया है, एक ओपन सोर्स लाइब्रेरी या कुछ की तरह।
यदि आप कर सकते हैं तो कृपया मदद करें। धन्यवाद
संपादित करें 1
ठीक है, तो मैं इसे इस तक ही सीमित नीचे और फिर मैं कुछ भी अधिक, मैं अब 8 घंटे से अधिक के लिए कोशिश कर रहे हैं नहीं कर सका। यह पूर्ववत होने तक काम करता है (आप जितना चाहें उतने पथ को पूर्ववत कर सकते हैं), फिर फिर से ड्राइंग करते समय सभी शेष पथ गायब हो जाते हैं, मुझे नहीं पता कि यह क्या करता है।
@Override
protected void onDraw(Canvas canvas) {
if (mBitmap != null)
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
if (!paths.isEmpty() && !undo)
canvas.drawPath(paths.get(paths.size() - 1).first, paths.get(paths.size() - 1).second);
if (undo) {
setBackground(mBackground);
for (Pair<Path, Paint> p : paths)
canvas.drawPath(p.first, p.second);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);
m_Canvas = new Canvas(mBitmap);
undo = false;
}
}
तो बुनियादी तौर पर मैं क्या किया पहली बार में पहली दृष्टिकोण का उपयोग (पहले पूर्ववत कहा जाता है), तो अगर पूर्ववत क्लिक किया जाता है, undo
true
पर सेट है और if (undo)
तहत कोड निष्पादित किया जाता है, जो वास्तव में पहले दृष्टिकोण है (फिर से सभी पथों की गणना), फिर मैं सभी पथों को फिर से mBitmap
में गणना करने का परिणाम खींचता हूं, इसलिए जब भी onDraw
को फिर से बुलाया जाता है, तो यह उस पर सबसे ऊपर खींचता है, लेकिन उस भाग को अभी भी काम करने की ज़रूरत है, मुझे उम्मीद है कि कोई उस भाग में मदद कर सकता है।
मुझे यह कहने में डर है कि यदि आप इतने सारे पथ खींचते हैं तो आपका विचार धीमा हो जाएगा। आपको एक ऐसी विधि खोजने का प्रयास करना चाहिए जिसमें एक बहुत लंबा रास्ता खींचना शामिल हो। – jcw
यदि आप हमेशा पुराने लोगों के शीर्ष पर नए पथ खींचते हैं तो आप बिटकमैप में अंतिम एन पथ को छोड़कर सभी विधियों को जोड़ सकते हैं और पिछले विधि के साथ अंतिम एन खींच सकते हैं। फिर आप इन अंतिम एन को कम से कम –