Android, canvas: ฉันจะล้าง (ลบเนื้อหาของ) canvas (= bitmaps) โดยอาศัยอยู่ใน surfaceView ได้อย่างไร


96

ในการสร้างเกมง่ายๆฉันใช้เทมเพลตที่วาดผืนผ้าใบด้วยบิตแมปดังนี้:

private void doDraw(Canvas canvas) {
    for (int i=0;i<8;i++)
        for (int j=0;j<9;j++)
            for (int k=0;k<7;k++)   {
    canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }

(ผ้าใบถูกกำหนดไว้ใน "run ()" / SurfaceView อาศัยอยู่ใน GameThread)

คำถามแรกของฉันคือฉันจะล้าง (หรือวาดใหม่) ผืนผ้าใบทั้งหมดสำหรับเค้าโครงใหม่ได้อย่างไร
ประการที่สองฉันจะอัปเดตเฉพาะบางส่วนของหน้าจอได้อย่างไร?

// This is the routine that calls "doDraw":
public void run() {
    while (mRun) {
        Canvas c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) 
                    updateGame();
                doDraw(c);          }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);  }   }   }       }

คำตอบ:


78

ฉันจะล้าง (หรือวาดใหม่) ผืนผ้าใบทั้งหมดสำหรับเลย์เอาต์ใหม่ได้อย่างไร (= ลองที่เกม)

เพียงแค่โทรCanvas.drawColor(Color.BLACK)หรือสีอะไรก็ได้ที่คุณต้องการล้างของคุณCanvasด้วย

และ: ฉันจะอัปเดตเพียงบางส่วนของหน้าจอได้อย่างไร?

ไม่มีวิธีการดังกล่าวที่อัปเดต "ส่วนหนึ่งของหน้าจอ" เนื่องจากระบบปฏิบัติการ Android จะวาดใหม่ทุกพิกเซลเมื่ออัปเดตหน้าจอ แต่เมื่อคุณไม่ได้ล้างภาพวาดเก่า ๆ บนภาพวาดCanvasเก่า ๆ ก็ยังคงอยู่บนพื้นผิวและนั่นอาจเป็นวิธีหนึ่งในการ "อัปเดตเพียงบางส่วน" ของหน้าจอ

ดังนั้นหากคุณต้องการ "อัปเดตส่วนหนึ่งของหน้าจอ" ให้หลีกเลี่ยงCanvas.drawColor()วิธีการโทร


4
ไม่ถ้าคุณไม่วาดทุกพิกเซลในพื้นผิวคุณจะได้ผลลัพธ์ที่แปลกมาก (เนื่องจากการบัฟเฟอร์สองครั้งทำได้โดยการสลับพอยน์เตอร์ดังนั้นในส่วนที่คุณไม่ได้วาดคุณจะไม่เห็นสิ่งที่เคยมีมาก่อน) คุณต้องวาดใหม่ทุกพิกเซลของพื้นผิวในการวนซ้ำแต่ละครั้ง
Guillaume Brunerie

2
@Viktor Lanner: ถ้าคุณโทรmSurfaceHolder.unlockCanvasAndPost(c)แล้วc = mSurfaceHolder.lockCanvas(null)แล้วใหม่ไม่ได้มีสิ่งเดียวกับก่อนหน้านี้c cคุณไม่สามารถอัปเดตเพียงส่วนหนึ่งของ SurfaceView ซึ่งเป็นสิ่งที่ OP ขอให้ฉันเดา
Guillaume Brunerie

1
@Guillaume Brunerie: จริง แต่ไม่ใช่ทั้งหมด คุณไม่สามารถอัปเดตบางส่วนของหน้าจอได้ตามที่ฉันเขียนไว้ แต่คุณสามารถเก็บภาพวาดเก่าไว้บนหน้าจอได้ซึ่งจะมีผลเพียงแค่ "อัปเดตส่วนหนึ่งของหน้าจอ" ลองใช้ด้วยตัวคุณเองในแอปพลิเคชันตัวอย่าง Canvasเก็บภาพวาดเก่า ๆ
Wroclai

2
น่าอายจริงๆเรา !!! ฉันเริ่มต้นอาร์เรย์ของฉันเพียงครั้งเดียวเมื่อเริ่มเกมไม่ได้เริ่มต้นใหม่ติดต่อกันดังนั้นชิ้นส่วนเก่าทั้งหมดจึงยังคงอยู่ "บนหน้าจอ" - พวกมันเพิ่งถูกดึงขึ้นมาใหม่ !!! ฉันเสียใจมากสำหรับ "ความโง่" ของฉัน! ขอบคุณทั้งสองคน !!!
samClem

1
อาจเป็นเพราะวอลล์เปเปอร์สดไม่ทำงานในลักษณะเดียวกับ SurfaceView ทั่วไป อย่างไรก็ตาม @samClem: วาดทุกพิกเซลของ Canvas ในแต่ละเฟรมเสมอ (ตามที่ระบุไว้ในเอกสาร) มิฉะนั้นคุณจะมีการกะพริบแปลก ๆ
Guillaume Brunerie

280

วาดสีโปร่งใสด้วยโหมดเคลียร์ PorterDuff เป็นเคล็ดลับสำหรับสิ่งที่ฉันต้องการ

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

2
สิ่งนี้ควรใช้งานได้ แต่ดูเหมือนจะถูกบั๊กใน 4.4 (อย่างน้อยใน N7.2) ให้ใช้Bitmap#eraseColor(Color.TRANSPARENT)ดังในคำตอบของ HeMac ด้านล่าง
นาโนเมตร

4
ในความเป็นจริงColor.TRANSPARENTไม่จำเป็น PorterDuff.Mode.CLEARเพียงพอสำหรับARGB_8888บิตแมปซึ่งหมายถึงการตั้งค่าอัลฟาและสีเป็น [0, 0] อีกวิธีหนึ่งคือการใช้Color.TRANSPARENTกับPorterDuff.Mode.SRC.
jiasli

1
สิ่งนี้ใช้ไม่ได้สำหรับฉันโดยปล่อยให้พื้นผิวว่างเปล่าแทนที่จะเป็นแบบโปร่งใส
pallav bohara

31

พบสิ่งนี้ในกลุ่ม Google และสิ่งนี้ได้ผลสำหรับฉัน ..

Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint); 

สิ่งนี้จะลบรูปวาดสี่เหลี่ยม ฯลฯ ในขณะที่เก็บบิตแมปที่ตั้งไว้ ..


4
สิ่งนี้ทำให้ฉันมีพื้นที่สีดำไม่ใช่บิตแมปที่ฉันมีอยู่ข้างหลัง :(
slott

มันล้างได้ดี แต่บิตแมปก็ถูกลบออกไปเช่นกัน
Omar Rehman

ในstackoverflow.com/questions/9691985/…อธิบายถึงวิธีการวาดรูปสี่เหลี่ยมผืนผ้าของบิตแมปบนสี่เหลี่ยมผืนผ้าบางส่วนของผืนผ้าใบ เปลี่ยนรูปภาพในรูปสี่เหลี่ยมผืนผ้าจึงใช้งานได้: เรียนรู้เนื้อหาก่อนหน้าวาดภาพใหม่
มาร์ติน

18

ใช้วิธีการรีเซ็ตคลาส Path

Path.reset();

นี่เป็นคำตอบที่ดีที่สุดหากคุณใช้เส้นทาง คนอื่น ๆ สามารถปล่อยให้ผู้ใช้มีหน้าจอสีดำ ขอบคุณ.
j2emanue

18

ฉันลองคำตอบของ @mobistry:

canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);

แต่มันไม่ได้ผลสำหรับฉัน

วิธีแก้ปัญหาสำหรับฉันคือ:

canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);

อาจมีบางคนมีปัญหาเดียวกัน


4
การคูณด้วยความโปร่งใสคือคำตอบ มิฉะนั้นอาจกลายเป็นสีดำในอุปกรณ์บางอย่าง
Andreas Rudolph

12
mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

2
วิธีนี้ถูกต้องที่สุดอย่างไร ทำไมต้องใช้บิตแมปในเมื่อคุณสามารถวาดสีได้
RichieHH

แม้ว่าสิ่งนี้อาจใช้ไม่ได้กับโปสเตอร์ต้นฉบับ (ไม่จำเป็นต้องเข้าถึงบิตแมป) สิ่งนี้มีประโยชน์อย่างแน่นอนสำหรับการล้างเนื้อหาของบิตแมปเมื่อพร้อมใช้งาน ในกรณีดังกล่าวจำเป็นต้องใช้บรรทัดแรกเท่านั้น เทคนิคที่เป็นประโยชน์ +1
เข้าไปที่รหัส

4

กรุณาวางโค้ดด้านล่างบน surfaceview ขยายคลาสคอนสตรัคเตอร์ .............

การเข้ารหัสตัวสร้าง

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    SurfaceView sur = (SurfaceView)findViewById(R.id.surfaceview);
    sur.setZOrderOnTop(true);    // necessary
    holder = sur.getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);

การเข้ารหัส xml

    <com.welcome.panelview.PanelViewWelcomeScreen
        android:id="@+id/one"
        android:layout_width="600px"
        android:layout_height="312px"
        android:layout_gravity="center"
        android:layout_marginTop="10px"
        android:background="@drawable/welcome" />

ลองใช้รหัสด้านบน ...


holder.setFormat (PixelFormat.TRANSPARENT); มันใช้ได้กับฉัน
Aaron Lee

3

นี่คือโค้ดของตัวอย่างขั้นต่ำที่แสดงว่าคุณต้องวาดใหม่ทุกพิกเซลของ Canvas ในแต่ละเฟรมเสมอ

กิจกรรมนี้วาดบิตแมปใหม่ทุกวินาทีบน SurfaceView โดยไม่ต้องล้างหน้าจอก่อน หากคุณทดสอบคุณจะเห็นว่าบิตแมปไม่ได้ถูกเขียนลงในบัฟเฟอร์เดียวกันเสมอไปและหน้าจอจะสลับกันระหว่างสองบัฟเฟอร์

ฉันทดสอบบนโทรศัพท์ของฉัน (Nexus S, Android 2.3.3) และบนโปรแกรมจำลอง (Android 2.2)

public class TestCanvas extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TestView(this));
    }
}

class TestView extends SurfaceView implements SurfaceHolder.Callback {

    private TestThread mThread;
    private int mWidth;
    private int mHeight;
    private Bitmap mBitmap;
    private SurfaceHolder mSurfaceHolder;

    public TestView(Context context) {
        super(context);
        mThread = new TestThread();
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        mWidth = width;
        mHeight = height;
        mThread.start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {/* Do nothing */}

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mThread != null && mThread.isAlive())
            mThread.interrupt();
    }

    class TestThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        c.drawBitmap(mBitmap, (int) (Math.random() * mWidth), (int) (Math.random() * mHeight), null);
                    }
                } finally {
                    if (c != null)
                        mSurfaceHolder.unlockCanvasAndPost(c);
                }

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }   
    }
}

ดูเหมือนว่าคุณคิดผิดดูการจับภาพหน้าจอของฉันที่นี่: img12.imageshack.us/i/devicey.png/#เมื่อคุณเพิ่มความล่าช้าอย่างหนึ่งวินาทีการบัฟเฟอร์สองครั้งจะสังเกตเห็นได้มากกว่า แต่ (!) ยังคงมีภาพวาดก่อนหน้านี้บนหน้าจอ นอกจากนี้รหัสของคุณเป็นสิ่งที่ผิด: มันควรจะเป็นไม่เพียงSurfaceHolder.Callback Callback
Wroclai

1
ฉันคิดว่าคุณไม่เข้าใจที่ฉันหมายถึง สิ่งที่คาดหวังได้คือความแตกต่างระหว่างเฟรมnและเฟรมn + 1คือมีบิตแมปอีกหนึ่งบิต แต่นี่ผิดอย่างสิ้นเชิงมีอีกหนึ่งบิตแมประหว่างเฟรมnและเฟรมn + 2แต่เฟรมnและเฟรมn + 1ไม่เกี่ยวข้องกันแม้ว่าฉันจะเพิ่งเพิ่มบิตแมปก็ตาม
Guillaume Brunerie

ไม่ฉันเข้าใจคุณทั้งหมด แต่อย่างที่คุณเห็นรหัสของคุณไม่ทำงาน หลังจากนั้นไม่นานหน้าจอจะเต็มไปด้วยไอคอน ดังนั้นเราจำเป็นต้องล้างCanvasถ้าเราต้องการวาดใหม่ทั้งหมดทั้งหน้าจอ นั่นทำให้คำพูดของฉันเกี่ยวกับ "ภาพวาดก่อนหน้า" เป็นจริง Canvasช่วยให้ภาพวาดก่อนหน้านี้
Wroclai

4
ใช่ถ้าคุณต้องการCanvasภาพวาดก่อนหน้านี้จะเก็บไว้ แต่สิ่งนี้ไร้ประโยชน์อย่างสิ้นเชิงปัญหาคือเมื่อคุณใช้lockCanvas()คุณไม่รู้ว่า "ภาพวาดก่อนหน้านี้" คืออะไรและไม่สามารถสรุปอะไรเกี่ยวกับสิ่งเหล่านี้ได้ บางทีหากมีสองกิจกรรมที่มี SurfaceView ที่มีขนาดเท่ากันพวกเขาจะแชร์ Canvas เดียวกัน บางทีคุณอาจได้รับ RAM ที่ไม่ได้เริ่มต้นพร้อมกับไบต์แบบสุ่ม บางทีอาจจะมีโลโก้ Google เขียนอยู่ใน Canvas เสมอ คุณไม่สามารถรู้ได้ แอปพลิเคชันใด ๆ ที่ไม่ได้วาดทุกพิกเซลหลังจากlockCanvas(null)เสีย
Guillaume Brunerie

1
@GuillaumeBrunerie 2.5 ปีหลังจากที่ฉันเจอโพสต์ของคุณ เอกสารอย่างเป็นทางการของ Android สนับสนุนคำแนะนำของคุณเกี่ยวกับ "การวาดทุกพิกเซล" มีเพียงกรณีเดียวที่รับประกันว่าส่วนหนึ่งของผืนผ้าใบจะยังคงอยู่ที่นั่นพร้อมกับการเรียกใช้ lockCanvas () ในภายหลัง อ้างถึงเอกสาร Android สำหรับ SurfaceHolder และสองวิธี lockCanvas () developer.android.com/reference/android/view/…และdeveloper.android.com/reference/android/view/…
UpLate

3

สำหรับฉันการโทรCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)หรือสิ่งที่คล้ายกันจะใช้งานได้หลังจากที่ฉันสัมผัสหน้าจอเท่านั้น ดังนั้นฉันจะเรียกรหัสบรรทัดด้านบน แต่หน้าจอจะชัดเจนหลังจากที่ฉันแตะหน้าจอแล้ว ดังนั้นสิ่งที่ได้ผลสำหรับฉันคือการโทรinvalidate()ตามด้วยinit()ซึ่งเรียกในขณะที่สร้างเพื่อเริ่มต้นมุมมอง

private void init() {
    setFocusable(true);
    setFocusableInTouchMode(true);
    setOnTouchListener(this);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);

    mCanvas = new Canvas();
    mPaths = new LinkedList<>();

    addNewPath();
}

3
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);

2
โปรดเพิ่มคำอธิบายว่าโค้ดของคุณแก้ปัญหาได้อย่างไร นี่ถูกตั้งค่าสถานะว่าเป็นโพสต์คุณภาพต่ำ - จากรีวิว
Suraj Rao

1

การลบบน Canvas ใน java android นั้นคล้ายกับการลบ HTML Canvas ผ่านทางจาวาสคริปต์ด้วย globalCompositeOperation ตรรกะคล้ายกัน

คุณจะเลือกตรรกะ DST_OUT (ปลายทางออก)

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

หมายเหตุ: DST_OUT มีประโยชน์มากกว่าเนื่องจากสามารถลบได้ 50% หากสีของสีมีอัลฟา 50% ดังนั้นเพื่อให้ชัดเจนถึงความโปร่งใสอัลฟาของสีต้องเป็น 100% แนะนำให้ใช้ paint.setColor (Color.WHITE) และตรวจสอบให้แน่ใจว่ารูปแบบภาพแคนวาสเป็น RGBA_8888

หลังจากลบแล้วให้กลับไปที่ภาพวาดปกติด้วย SRC_OVER (Source Over)

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));

อัปเดตการแสดงผลพื้นที่ขนาดเล็กจะต้องเข้าถึงฮาร์ดแวร์กราฟิกอย่างแท้จริงและอาจไม่รองรับ

ใกล้เคียงที่สุดเพื่อประสิทธิภาพสูงสุดคือการใช้เลเยอร์ภาพหลายภาพ


คุณสามารถช่วยฉันที่นี่? คุณเป็นทางออกเดียวที่ได้ผลสำหรับกรณีของฉันดังนั้นฉันจึงได้รับการโหวตมีปัญหาเล็กน้อยที่ต้องจัดการ
hamza khan

ฉันใช้ผ้าใบกับที่ยึดพื้นผิวดังนั้นฉันจึงทำสิ่งนี้เพื่อล้างผ้าใบ (ผ้าใบที่ถ่ายจากที่ยึดพื้นผิว): paint !!. setXfermode (PorterDuffXfermode (PorterDuff.Mode.DST_OUT)) canvas !!. drawPaint (paint !!) surfaceHolder! ! .unlockCanvasAndPost (canvas) แล้วจึงจะสามารถวาดใหม่ได้: paint !!. setXfermode (PorterDuffXfermode (PorterDuff.Mode.SRC)) canvas !!. drawPaint (paint !!) surfaceHolder !!. unlockCanvasAndPost (canvas) ตอนนี้ปัญหา คือหลังจากล้างแคนวาสแบบนี้แล้วเมื่อฉันวาดบิตแมปบนผืนผ้าใบมันจะถูกวาดหลังจากสีกระพริบตาซึ่งน่ารำคาญคุณช่วยแสดงวิธีที่นี่ได้ไหม @phnghue
hamza khan

@hamza khan คุณเคยลองกับ SRC_OVER หรือยัง? เนื่องจาก SRC_OVER เป็นค่าเริ่มต้นปกติ ตรรกะ SRC เขียนทับข้อมูลพิกเซลเก่าแทนที่อัลฟ่า!
phnghue


0

พยายามลบมุมมองที่ onPause () ของกิจกรรมและเพิ่ม onRestart ()

LayoutYouAddedYourView.addView (YourCustomView); LayoutYouAddedYourView.removeView (YourCustomView);

เมื่อคุณเพิ่มมุมมองของคุณเมธอด onDraw () จะถูกเรียก

YourCustomView เป็นคลาสที่ขยายคลาส View


0

ในกรณีของฉันฉันวาดผืนผ้าใบของฉันเป็น linearlayout ในการทำความสะอาดและวาดใหม่อีกครั้ง:

    LinearLayout linearLayout = findViewById(R.id.myCanvas);
    linearLayout.removeAllViews();

จากนั้นฉันเรียกชั้นเรียนด้วยค่าใหม่:

    Lienzo fondo = new Lienzo(this,items);
    linearLayout.addView(fondo);

นี่คือคลาส Lienzo:

class Lienzo extends View {
    Paint paint;
    RectF contenedor;
    Path path;
    ArrayList<Items>elementos;

    public Lienzo(Context context,ArrayList<Items> elementos) {
        super(context);
        this.elementos=elementos;
        init();
    }

    private void init() {
        path=new Path();
        paint = new Paint();
        contenedor = new RectF();
        paint.setStyle(Paint.Style.FILL);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        contenedor.left = oneValue;
        contenedor.top = anotherValue;
        contenedor.right = anotherValue;
        contenedor.bottom = anotherValue;

        float angulo = -90; //starts drawing at 12 o'clock
        //total= sum of all element values
        for (int i=0;i<elementos.size();i++){
            if (elementos.get(i).angulo!=0 && elementos.get(i).visible){
                paint.setColor(elementos.get(i).backColor);
                canvas.drawArc(contenedor,angulo,(float)(elementos.get(i).value*360)/total,true,paint);

                angulo+=(float)(elementos.get(i).value*360)/total;
            }
        } //for example
    }
}

0

ด้วยวิธีการต่อไปนี้คุณสามารถล้างผืนผ้าใบทั้งหมดหรือเพียงบางส่วนก็ได้
โปรดอย่าลืมปิดการใช้งานการเร่งฮาร์ดแวร์เนื่องจากPorterDuff.Mode.CLEARไม่ทำงานกับการเร่งฮาร์ดแวร์และในที่สุดก็เรียกsetWillNotDraw(false)เพราะเราแทนที่onDrawวิธีการ

//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_SOFTWARE, null);

//view's onDraw
Paint TransparentPaint = new Paint();
TransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, TransparentPaint); 

มันใช้งานได้ แต่หลังจากนั้นการจับรางวัลของฉันก็ไม่ปรากฏให้เห็นอีก
Dyno Cris

1
@DynoCris บางทีคุณอาจใช้วัตถุสีเดียวกัน!? ลองใหม่และอย่าลืมโหวตให้คะแนนด้วย
ucMedia

มันคือรหัสของฉันpastebin.com/GWBdtUP5เมื่อฉันพยายามวาดอีกครั้งฉันไม่เห็นเส้นที่ไม่เป็นระเบียบมากขึ้น แต่กระป๋องใส
Dyno Cris

1
@DynoCris โปรดเปลี่ยนLAYER_TYPE_HARDWAREเป็นLAYER_TYPE_SOFTWARE
ucMedia

1
โอ้มันเป็นความผิดพลาดของฉันจริงๆ แต่มันก็ไม่ได้ช่วยให้ฉันไม่สบายใจอยู่ดี
Dyno Cris

-1

ข้อกำหนดแรกของคุณวิธีการล้างหรือวาดใหม่ทั้งผืนผ้าใบ - คำตอบ - ใช้วิธี canvas.drawColor (color.Black) เพื่อล้างหน้าจอด้วยสีดำหรืออะไรก็ตามที่คุณระบุ

ข้อกำหนดประการที่สองของคุณวิธีอัปเดตส่วนหนึ่งของหน้าจอ - คำตอบ - ตัวอย่างเช่นหากคุณต้องการให้สิ่งอื่น ๆ ทั้งหมดไม่เปลี่ยนแปลงบนหน้าจอ แต่ในพื้นที่เล็ก ๆ ของหน้าจอเพื่อแสดงจำนวนเต็ม (พูดว่าตัวนับ) ซึ่งจะเพิ่มขึ้นทุกๆห้าวินาที จากนั้นใช้วิธี canvas.drawrect เพื่อวาดพื้นที่เล็ก ๆ นั้นโดยระบุซ้ายบนขวาล่างแล้วระบายสี จากนั้นคำนวณค่าตัวนับของคุณ (โดยใช้ postdalayed เป็นเวลา 5 วินาทีเป็นต้นเช่น Handler.postDelayed (Runnable_Object, 5000);) แปลงเป็นสตริงข้อความคำนวณพิกัด x และ y ใน rect ขนาดเล็กนี้และใช้มุมมองข้อความเพื่อแสดงการเปลี่ยนแปลง มูลค่าเคาน์เตอร์


-1

ฉันต้องใช้บัตรวาดภาพแยกต่างหากเพื่อล้างผืนผ้าใบ (ล็อควาดและปลดล็อก):

Canvas canvas = null;
try {
    canvas = holder.lockCanvas();
    if (canvas == null) {
        // exit drawing thread
        break;
    }
    canvas.drawColor(colorToClearFromCanvas, PorterDuff.Mode.CLEAR);
} finally {
    if (canvas != null) {
        holder.unlockCanvasAndPost(canvas);
    }
}

-3

เพียงโทร

canvas.drawColor (สี TRANSPARENT)


16
ไม่ได้ผลเพราะมันจะดึงความโปร่งใสที่ด้านบนของคลิปปัจจุบัน ... Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)อย่างไรก็ตามคุณสามารถเปลี่ยนโหมดการถ่ายโอนพอร์เตอร์ดัฟฟ์เพื่อให้บรรลุผลที่ต้องการ: ถ้าจำไม่ผิดจริงๆแล้วสีอาจเป็นอะไรก็ได้ (ไม่จำเป็นต้องเป็น TRANSPARENT) เพราะPorterDuff.Mode.CLEARแค่จะล้างคลิปปัจจุบัน (เหมือนเจาะรูผ้าใบ)
ashughes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.