سؤال

أنا جديد على Android.

أنا أرسم خلفات الصورة النقطية والخطوط والأشكال على قماش داخل طريقة Ondraw (Canvas Canvas) في وجهة نظري. أنا أبحث عن مساعدة حول كيفية تنفيذ التمرير السلس استجابة لسحب المستخدم. لقد بحثت ولكن لم أجد أي برامج تعليمية لمساعدتي في هذا.

يبدو أن مرجع القماش يقول إنه إذا تم بناء قماش من صورة نقطية (تسمى bmpbuffer ، على سبيل المثال) ، يتم رسم أي شيء مرسوم على القماش على BMPbuffer. هل سيكون من الممكن استخدام BMPbuffer لتنفيذ التمرير ... ربما نسخه مرة أخرى إلى القماش الذي تم تحويله ببضع بكسل في وقت واحد؟ ولكن إذا استخدمت canvas.drawbitmap لرسم bmpbuffer مرة أخرى إلى القماش الذي تم تحويله ببضع بكسل ، فلن يتم تالف BMPbuffer؟ ربما ، يجب أن أسد BMPbuffer إلى BMPbuffer2 ثم رسم BMPbuffer2 مرة أخرى إلى القماش.

تتمثل النهج الأكثر وضوحًا في رسم الخطوط والأشكال وما إلى ذلك مباشرة في صورة نقطية عازلة ، ثم ارسم هذا المخزن المؤقت (مع تحول) على القماش ولكن بقدر ما أستطيع رؤية الطرق المختلفة: Drawline () ، drawshape () وهكذا لا تتوفر للرسم إلى صورة نقطية ... فقط إلى قماش.

هل يمكنني الحصول على لوحين؟ أحدها سيتم بناؤه من صورة نقطية عازلة واستخدامها ببساطة لتخطيط الخطوط والأشكال ، وما إلى ذلك ، ثم يتم رسم صورة نقطية عازلة على القماش الآخر للعرض في العرض؟

يجب أن أرحب بأي نصيحة!

إجابات على أسئلة مماثلة هنا (وعلى مواقع الويب الأخرى) تشير إلى "Blitting". أنا أفهم المفهوم ولكن لا يمكنني العثور على أي شيء عن "blit" أو "bitblt" في وثائق Android. هل canvas.drawbitmap و bitmap.copy android معادلات؟

هل كانت مفيدة؟

المحلول

كان لي هذه المشكلة أيضا،

فعلت الرسم مثل هذا:

Canvas BigCanvas = new Canvas();
Bitmap BigBitmap = new Bitmap(width,height);

int ScrollPosX , ScrollPosY  // (calculate these with the onScrollEvent handler)

void onCreate()
{
   BigCanvas.SetBitmap(BigBitmap);
}

onDraw(Canvas TargetCanvas)
{
   // do drawing stuff
   // ie.  BigCanvas.Draw.... line/bitmap/anything

   //draw to the screen with the scrolloffset

   //drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
   TargetCanvas.DrawBitmap(BigBitmap(new Rect(ScrollPosX,ScrollPosY,ScrollPosX + BigBitmap.getWidth(),ScrollPosY + BigBitmap.getHeight(),new Rect(0,0,ScreenWidth,ScreenHeight),null);
}

من أجل التمرير السلس ، ستحتاج إلى صنع نوع من الطريقة التي تأخذ بضع نقاط بعد التمرير (أي نقطة التمرير الأولى والعاشرة) ، قم بطرحها والتمرير بهذا الرقم في كل حلقة تجعلها أبطأ تدريجياً (Scrollamount - المنعطفات - الاحتكاك).

آمل أن يعطي هذا المزيد من البصيرة.

نصائح أخرى

يبدو أنني وجدت إجابة. لقد وضعت الجزء الأكبر من رمز الرسم (الذي كان سابقًا في Ondraw ()) بطريقة doDrawing () جديدة. تبدأ هذه الطريقة بإنشاء صورة نقطية جديدة أكبر من الشاشة (كبيرة بما يكفي للاحتفاظ بالرسم الكامل). ثم ينشئ قماشًا ثانيًا للقيام بالرسم التفصيلي:

    BufferBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888);
    Canvas BufferCanvas = new Canvas(BufferBitmap);

يتم تناول بقية طريقة doDrawing () مع رسم مفصل إلى Buffercanvas.

تقرأ طريقة OnDraw () بالكامل الآن على النحو التالي:

    @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(BufferBitmap, (float) -posX, (float) -posY, null);
}

يتم تهيئة متغيرات الموضع ، posx و posy ، في 0 في طريقة onCreate () للتطبيق. ينفذ التطبيق OngerSurelistener ويستخدم وسيطات Riquistx و Distate في إشعار ONSCROLL لزيادة POSX و POSY.

يبدو أن هذا كل ما هو مطلوب لتنفيذ التمرير السلس. أو هل أفرط في المظهر شيء!؟

استمرار الرد على فيكتور ...

في الواقع ، الوضع أكثر تعقيدًا. نظرًا لأن عملية التغلب بطيئة جدًا (تأخذ 2-3 ثوانٍ على هاتف HTC Hero البطيء البطيء) ، فقد وجدت أنه من المستحسن أن تطفو على السطح رسالة نخب لتقديم المشورة للمستخدم بأنه كان يحدث والإشارة إلى السبب. كانت الطريقة الواضحة للقيام بذلك هي إنشاء طريقة جديدة تحتوي على سطرين فقط:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");`
    doDrawing();
}

والاتصال بهذه الطريقة من أماكن أخرى في برنامجي بدلاً من doDrawing ().

ومع ذلك ، وجدت أن المحمصة إما لم تظهر أو تومض لفترة وجيزة لدرجة أنه لا يمكن قراءتها. كان الحل الخاص بي هو استخدام معالج فحص الوقت لإجبار البرنامج على النوم لمدة 200 مللي ثانية بين عرض الخبز المحمص والاتصال doDrawing (). على الرغم من أن هذا يؤخر قليلاً من بداية إعادة الرسم ، أشعر أن هذا سعر يستحق الدفع من حيث قابلية استخدام البرنامج لأن المستخدم يعرف ما يجري. يقرأ RedRawbuffer () الآن:

public void redrawBuffer(String strReason) {
    Toaster.Toast(strReason, "Short");
    mTimeCheckHandler.sleep(200);    
}`

ورمز المعالج (الذي يتداخل ضمن فئة العرض) هو:

private timeCheckHandler mTimeCheckHandler = new timeCheckHandler();

class timeCheckHandler extends Handler {
@Override
    public void handleMessage(Message msg) {
        doDrawing();
    }
    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
}`

لا حاجة لإعادة تشغيل النشاط! (لكل رد في 27 يناير من قبل Prepbgg على "إجابته" في 17 يناير) بدلاً من إعادة تدوير صورة نقطية وتكبؤ النفقات العامة لإعادة تحميل النشاط ، يمكنك تجنب تحميل التطبيق عن طريق وضع سمة "Android: Configchanges" الموضحة أدناه ، في عنصر "النشاط" في ملف AndroidManifest.xml للتطبيق. هذا يخبر النظام أن التطبيق سوف يتعامل مع تغييرات الاتجاه وأنه لا يحتاج إلى إعادة تشغيل التطبيق.

<activity android:name=".ANote"
    android:label="@string/app_name"
    android:configChanges="orientation|screenLayout">
    <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

يمكن استخدام هذه الطريقة للحصول على إشعار عند تغيير orienation:

public void onConfigurationChanged(Configuration  newConfig) {
    super.onConfigurationChanged(newConfig);
    prt("onConfigurationChanged: "+newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
      prt("  PORTRAIT");
    } else {
      prt("  LANDSCAPE");
    }
} // end of onConfigurationChanged

prepbgg: لا أعتقد أن الكود سيعمل لأن canvas.drawbitmap لا يرسم إلى صورة نقطية ولكنه يرسم صورة نقطية على القماش.

صحح لي إن كنت مخطئ!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top