24

私はAndroidが初めてです。

ビューの OnDraw(Canvas canvas) メソッド内の Canvas にビットマップ、線、および図形を描画しています。ユーザーのドラッグに応じてスムーズなスクロールを実装する方法についてのヘルプを探しています。検索しましたが、これに役立つチュートリアルは見つかりませんでした。

Canvas の参照は、Canvas がビットマップ (たとえば bmpBuffer と呼ばれる) から構築されている場合、Canvas に描画されるものはすべて bmpBuffer にも描画されると言っているようです。bmpBuffer を使用してスクロールを実装することは可能でしょうか...おそらく一度に数ピクセルずつシフトされたキャンバスにコピーして戻しますか? しかし、Canvas.drawBitmap を使用して bmpBuffer を Canvas に描画し、数ピクセルずらして戻すと、bmpBuffer は破損しませんか? したがって、bmpBuffer を bmpBuffer2 にコピーしてから、bmpBuffer2 を Canvas に戻す必要があります。

より簡単なアプローチは、線、形状などをバッファ Bitmap に直接描画し、そのバッファを (シフトして) Canvas に描画することですが、私が見ることができる限り、さまざまなメソッド: drawLine()、drawShape()などは、ビットマップへの描画には使用できません...キャンバスにのみ使用できます。

キャンバスを2枚いただけますか?そのうちの 1 つはバッファ ビットマップから構築され、単純に線や形状などをプロットするために使用されます。その後、バッファ ビットマップはビューに表示するために他のキャンバスに描画されますか?

どんなアドバイスでも歓迎します!

ここ (および他の Web サイト) での同様の質問への回答は、「ブリッティング」に言及しています。概念は理解できますが、Android ドキュメントで「blit」または「bitblt」について何も見つかりません。Canvas.drawBitmap と Bitmap.Copy は Android の同等物ですか?

4

5 に答える 5

13

答えを見つけたようです。(以前は onDraw() にあった) 描画コードの大部分を新しい doDrawing() メソッドに入れました。このメソッドは、画面よりも大きい (完全な描画を保持するのに十分な大きさの) 新しいビットマップを作成することから始めます。次に、詳細な描画を行うための 2 つ目の Canvas を作成します。

    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 は、アプリケーションの onCreate() メソッドで 0 に初期化されます。アプリケーションは OnGestureListener を実装し、OnScroll 通知で返された distanceX および distanceY 引数を使用して、posX および posY をインクリメントします。

スムーズなスクロールを実装するために必要なことは、これでほぼすべてのようです。それとも私が何か見落としているの!?

于 2010-01-17T18:01:55.003 に答える
1

Viktorへの返信の続き...

実際、状況はもっと複雑です。doDrawing プロセスは非常に遅いため (私の遅い古い HTC Hero フォンでは 2 ~ 3 秒かかります)、Toast メッセージをポップアップして、それが発生していることをユーザーに通知し、理由を示すことが望ましいと判断しました。これを行う明白な方法は、2 行だけを含む新しいメソッドを作成することでした。

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

doDrawing() の代わりに、プログラム内の他の場所からこのメソッドを呼び出します。

しかし、Toaster がまったく表示されないか、一瞬点滅して読めないことがわかりました。私の回避策は、タイム チェック Handler を使用して、Toast の表示と doDrawing() の呼び出しの間にプログラムを 200 ミリ秒間強制的にスリープさせることでした。これは再描画の開始を少し遅らせますが、ユーザーは何が起こっているかを知っているので、プログラムの使いやすさの点でこれは支払う価値があると思います. reDrawBuffer() は次のようになります。

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

Handler コード (View クラス内にネストされている) は次のとおりです。

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);
    }
}`
于 2011-03-26T22:27:10.923 に答える
1

アクティビティを再開する必要はありません。(prepbgg の 2010 年 1 月 27 日の「回答」に対する 1 月 27 日の返信による) ビットマップをリサイクルし、アクティビティをリロードするオーバーヘッドが発生するのではなく、以下に示す「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>

このメソッドを使用して、方向が変更されたときに通知を受け取ることができます。

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
于 2011-01-04T14:14:45.347 に答える
1

私もこの問題を抱えていました、

私は次のように描きました。

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);
}

スムーズなスクロールのためには、スクロール後にいくつかのポイント(つまり、最初のスクロールポイントと10番目)を取るある種のメソッドを作成し、それらを減算し、for eachループでその数だけスクロールして、徐々に遅くする必要があります( ScrollAmount - ターン - 摩擦 )。

これにより、さらに洞察が得られることを願っています。

于 2010-06-18T11:02:01.853 に答える
0

prepbgg:canvas.drawBitmapはビットマップに描画されませんが、ビットマップをキャンバスに描画するため、コードは機能しないと思います。

私が間違っている場合は私を訂正してください!

于 2010-05-04T10:01:56.333 に答える