3

I have started venturing into a bit of Canvas stuff and managed to add some statis PNG files to it.

Now I'd like to load in a PNG sequence, which I believe is an AnimationDrawable (rather then Bitmap)

I have written the XML file for the animation but then I am stumped.

I cannot find any examples of people adding PNG sequences to a Canvas object.

Mr Pablo
  • 4,109
  • 8
  • 51
  • 104

3 Answers3

2

here is sample:

public class MainActivity extends Activity {

    private static final int FRAME_DELAY = 200; // in ms

    private ArrayList<Bitmap> mBitmaps;
    private final AtomicInteger mBitmapIndex = new AtomicInteger();
    private View mView;
    private Thread mThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // load resources
        mBitmaps = new ArrayList<Bitmap>();
        for(int resId : new int[]{
                // resource ids here
                R.drawable.ic_launcher,
                R.drawable.ddms_128,
                R.drawable.ddms_icon
                }){
            mBitmaps.add(BitmapFactory.decodeResource(getResources(), resId));
        }

        // create View and implement 'draw'
        ViewGroup root = (ViewGroup) findViewById(R.id.root);
        root.addView(mView = new View(this){
            @Override
            public void draw(Canvas canvas) {
                canvas.drawBitmap(mBitmaps.get(Math.abs(mBitmapIndex.get() % mBitmaps.size())), 10, 10, null);
                super.draw(canvas);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();

        mThread = new Thread(){
            @Override
            public void run() {
                // wait and invalidate view until interrupted
                while(true){
                    try {
                        Thread.sleep(FRAME_DELAY);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        break; // get out if interrupted
                    }
                    mBitmapIndex.incrementAndGet();
                    mView.postInvalidate();
                }
            }
        };

        mThread.start();
    }

    @Override
    protected void onStop() {
        mThread.interrupt();
        super.onStop();
    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</RelativeLayout>
user2399321
  • 605
  • 7
  • 13
0

Canvas allows to draw line/shapes/bitmaps. You managed to draw one bitmap. Animation is just drawing one bitmap from bunch of them. Canvas does nothing with drawables. The logic neither related to Canvas nor to drawables.

user2399321
  • 605
  • 7
  • 13
  • I understand what you are saying, but I just need an example on how to achieve it. It's pretty important that I am able to get these animations to play on the Canvas. Failing that, would OpenGl ES be able to take over the job of Canvas? (i am currently displaying an audio waveform drawn with a drawLine() and then there is the animated drawables to take care of) – Mr Pablo Jun 14 '13 at 14:19
-1

Draw the first frame, then use a Handler to post delayed Message that when handled moves to the next frame and calls invalidate().

What you need to do is:

Step #1. Override VisualizerView.verifyDrawable(Drawable who)

@Override
protected boolean verifyDrawable(Drawable who) {
    return true;
}

Step #2. Modify MainActivity.addAnimationRenderer()

private void addAnimationRenderer() {
    final AnimationDrawable anim = (AnimationDrawable) getResources().getDrawable(R.drawable.png1);

    AnimationRenderer animRenderer = new AnimationRenderer(anim);
    mVisualizerView.addRenderer(animRenderer);

    anim.setCallback(mVisualizerView);
    mVisualizerView.post(new Runnable() {
        @Override
        public void run() {
            anim.start();
        }
    });
}

Step #3. Modify AnimationRenderer: delete

mBitmap.setCallback(null);
mBitmap.start();
tomrozb
  • 25,773
  • 31
  • 101
  • 122
pskink
  • 23,874
  • 6
  • 66
  • 77
  • Hmm OK. I'm really very new to Android development, so I have no idea what you just said :) – Mr Pablo Jun 14 '13 at 14:11
  • try googling about Handler then – pskink Jun 14 '13 at 14:27
  • Thing is, I want to be able to use the AnimationDrawable and as far as I can see, you cannot add that to Canvas. Could I do the following? AnimationDrawable to ImageView, ImageView to Canvas? – Mr Pablo Jun 14 '13 at 14:32
  • ok so see Drawable.draw() method, ots purpose is drawing on Canvas – pskink Jun 14 '13 at 14:44
  • I don't think you understand my question correctly. You cannot use Drawable.draw() with an AnimationDrawable. I tried, I Googled. You cannot do it, they are two different things. – Mr Pablo Jun 14 '13 at 15:04
  • of course you can use it. what do you think how Drawable draws itself on any Canvas? – pskink Jun 14 '13 at 15:18
  • So why can I not find a single instance on the Internet of an example where an AnimationDrawable is drawn to Canvas? – Mr Pablo Jun 14 '13 at 15:21
  • well, it doesnt prove anything, if you have sources see draw method on some Drawables e.g. BitmapDrawable, GradientDrawable etc – pskink Jun 14 '13 at 15:29
  • Do you have any personal knowledge of how to add a PNG sequence to a Canvas object? – Mr Pablo Jun 14 '13 at 15:31
  • I told you, you cannot use that. AnimationDrawable is NOT a Bitmap object, hence you cannot use drawBitmap(). I tried it, trust me. – Mr Pablo Jun 14 '13 at 15:35
  • you have two choises: use AmimarionDrawable and its draw method or store your pngs in some collection an draw it usung canvas.drawBitmap – pskink Jun 14 '13 at 15:41
  • I am currently trying to use mAnim.setBounds(rect); mAnim.draw(canvas); mAnim.start(); but it doesn't work. – Mr Pablo Jun 14 '13 at 15:44
  • try view.invalidate() after anim.start() – pskink Jun 14 '13 at 15:49
  • speaking of Drawables, see this http://stackoverflow.com/questions/16729169/how-to-maintain-multi-layers-of-imageviews-and-keep-their-aspect-ratio-based-on how i draw Drawables on a Canvas – pskink Jun 14 '13 at 16:30
  • as a prove that you can use AnimationDrawable.draw(Canvas) to draw on any Canvas i added AnimationDrawable to my custom LayeredImageView demo, see: http://stackoverflow.com/questions/16729169/how-to-maintain-multi-layers-of-imageviews-and-keep-their-aspect-ratio-based-on – pskink Jun 15 '13 at 16:53
  • I did "mdrawable.setBounds(rect); mDrawable.draw(canvas); mDrawable.start();" and it still doesn't work. – Mr Pablo Jun 18 '13 at 12:21
  • there is nothing? dont you even see the first frame? so how did you setBounds and when you call draw() and start() k – pskink Jun 18 '13 at 13:59
  • i dont see anything. the bounds are set using a Rect object, set using "mRect.set(0, 0, getWidth(), getHeight());" – Mr Pablo Jun 18 '13 at 14:26
  • what do you see when calling Log.d(TAG, "rect " + mRect) – pskink Jun 18 '13 at 14:43
  • rect: Rect(0, 0 - 1280, 670) – Mr Pablo Jun 18 '13 at 14:53
  • so bounds are ok, maybe try first replace AnimationDrawable w/ BitmapDrawable to verify that everything works fine? – pskink Jun 18 '13 at 14:59
  • I think I need to also add "mDrawable.setCallback()" but I don't know what I need to put in there? Eclipse hints at either "mDrawable" (itself) or null. Neither work... – Mr Pablo Jun 18 '13 at 15:07
  • see the link i already posted stackoverflow.com/questions/16729169/how-to-maintain-multi-layers-of-imageviews-and-keep-their-aspect-ratio-based-on, one Layer uses AnimationDrawable, replace it with your AnimDrwble and see what happens – pskink Jun 18 '13 at 15:22
  • the problem is, I am not using "normal" views. I am using an extension of the View class. Here is the project: https://github.com/paulcanning/MuVis. look in src / com / paulcanning / muvis / visualizer / renderer / AnimationRenderer.java I need to be able to add it like this because I need to use the audio data, and do everything dynamically – Mr Pablo Jun 18 '13 at 15:25
  • funny thing is your view uses set of Renderers my uses list of Layers, you call addRenderer i call addLayer, my view's onDraw iterates on layers and directly call Drawable.draw you call Renderer.render, so its almost 1:1 relationship, see how i did this, its a short claass – pskink Jun 18 '13 at 16:25
  • your layerview is extending imageview, but non of my classes extend imageview. could you look at my github code and see how i would get this to work? – Mr Pablo Jun 19 '13 at 14:29
  • maybe your animationdrawable is broken? did you try to add it as a layer to my view? – pskink Jun 19 '13 at 14:50
  • I have no idea how to combine your code with what I have. I am very very new to Android (I'm a PHP developer) so this has me totally stumped. – Mr Pablo Jun 19 '13 at 14:58
  • the most important is Callback which is implemented by View and its method invalidateDrawable also you have to override verifyDrawable – pskink Jun 19 '13 at 15:15
  • sorry, but I have no idea what you are on about. I'm gonna leave this project alone for now as I simply cannot figure out how it works properly and I really need to get animationdrawables working. – Mr Pablo Jun 19 '13 at 15:19
  • @MrPablo, have you found solution? – Ivan Vovk Feb 26 '19 at 11:24