Improve drawing speed of images inside viewpager - android

I'm using a viewpager to show static information to the user, this includes textviews, imageviews, etc. Now my swiping of my viewpager isn't really fluid when I include images to my viewpager. So I used the hierarchy viewer to check how much time it cost to draw my images. To draw only one image (filetype: JPG, filesize: 40kB) it took more than 50ms to actually draw it. So every time the screen is redrawn (during swiping from the user) it will take up more than 50ms to fully redraw the screen, what I suspect to be the culprit of the 'swiping lag'.
Does anybody know a way to improve the drawing speed of the images? I searched through the topics here, but couldn't find a definite answer to my problem.
Thanks in advance!!

implement image loader to load image in your viewpager will increase scroll speed try This

If all the images are stored locally then while drawing them in the layout write your code in OnDraw() method of Pager Adapter.It will not take any time.
to call onDraw() use this
Call this method in the onDraw function:
protected void onDraw (Canvas canvas) {
drawyourImages(canvas);
}
Every time when your UI is refreshed, the onDraw function will be called. To trigger the UI refresh. Just invalidate your custom view. For example
mCustomerView.invalidate();
OR
if your image is coming from server then use AQuery/Picasso or any image loading library to load your image in onDraw() method.before calling onDraw() you have to invalidate your view.To invalidate your view you should call
mCustomerView.invalidate();
in viewpager swipe method listener.

Related

Did Android re-draw all the screen when only one small view changed?

I just did an experiment, a big ImageView in full-screen size and a small ImageView in the center. I changed the src of small ImageView and only small ImageView's onDraw is called.
I was wondering if the big ImageView's onDraw wasn't called, why can I see it on screen?
I guess the GPU rendering is based on the last snapshot of the GPU buffer and only submits the change in every VSYNC. So if there's no change in this area, it will show the content as the last frame.
Am I wrong? Please give me your idea about this.
Only the views that change need to be redrawn. Why would the rest need to be?
What happens when you change the image in an imageView is that it calls invalidate() on that view. This marks the view as dirty and needing a redraw. This will cause its onDraw to be called on the next render pass. Views that aren't invalid don't change, thus don't need their onDraw called.

Finger drawing application with unlimited scroll

I want to make finger-draw app with vertical scroll and possibly unlimited space to draw. Scroll can be locked/unlocked.
I know 2 ways to do that:
Make a bitmap with given width and height, draw points/lines in onTouchEvent(MotionEvent) via Canvas(Bitmap) and draw that bitmap in onDraw(Canvas).
Save touch points to array and draw them directly in onDraw(Canvas).
But both ways have disadvantages:
OutOfMemoryException with big bitmap.
Very slow with numerous points while scrolling and OOM possible too.
I have an idea to use window and read/write regions of bitmap on demand. So there is a problem: how to write/append bitmap to another bitmap?
I cant find an appropriate way to append 200x200px bitmap to 8000x8000px bitmap for example. Is there a way to do that without native libs?
Or am I totally wrong and there is an easier method to do what I need to?
What about using a grid of small bitmaps, without appending them to a larger bitmap at all? When one of your bitmaps goes out of the screen you save it to the disk and destroy it or recycle it, a bit like how GridView recycles cells (it reuses the same 10 cells or so to display a potentially infinite grid of cells). Saving the whole drawing would just mean saving all bitmaps to the disk.
The main concern with this approach is the time it takes to save/load chunks from disk while the user scrolls through the view, which may cause the app to freeze for a short time, but there are ways to make it smooth (for example by preloading bitmaps in a background thread).
Storing touch points in a list is also completely possible, there are many ways to speed up the drawing part, for example by caching what's on the screen and drawing only what's missing when the user scrolls. Which one is best depends on what you will draw on your view.

imageView.setImageBitmap(Bitmap) slows my app extremly

i have written a litte app that should display a tacho that gets it data about rpm... over bluetooth. when the data changes i rotate a needle and some other imageViews to display the current values on the screen.
rotate code:
bMapRpm=bMapcanvasBackTacho.copy(bMapcanvasBackTacho.getConfig(), true);
canvasRpm.setBitmap(bMapRpm);
canvasRpm.save();
canvasRpm.rotate((float)Rpmdegree+(float)Rpmcurrentdegree,bMapRpm.getWidth()/2,bMapRpm.getHeight()/2);
canvasRpm.drawBitmap(bMapNadel,0,0,paint);
canvasRpm.restore();
bMapcanvasBackTacho is just a transparent background.
bMapNadel is the bitmap of the needle.
bMapRpm is the bitmap of the canvas to draw on
to update the imageView i allways call:
ivNadel.setImageBitmap(bMapRpm);
i tryed out what slows the app by commenting parts of the code out.
after commenting the setImageBitmap() out the slow down disapeared.
doese someone know how to update the imageView in an other way or whta i could change to get it to work faster?
thx =)
You can do two things:
First, don't call copy() each time you need to update the Bitmap this creates a new Bitmap and is both time and memory consuming.
Second, call invalidate() on the ImageView. This will notify the View that something has changed and it redraws itself without having to update anything else that is happening when you replace the Bitmap completely.
In the end you might even want to create your own View implementation so you can just override onDraw() and perform rotations there.

Draw an image floating over another in Android

I want to be able to dynamically place image(s) over another image in my app.
Consider the first image as background and the other images to be on top level, I will also need to move those top level images (change their x and y on the screen) by code too.
Imagine, for example, a sea in which the user places fish and sea animals, then those sea animals start to move here and there on the screen: it will be like that.
How can I do this? If you don't know but remember any simple program or demo that does that, it will be also very welcome!
Thank you!
There is, of course, more than one way to do this, but I would say that the best way to do it would be to create a custom View (class that derives from View) and have this handle your bitmap drawing and all of your touch events.
There's a lot of code to write for loading the Bitmaps and keeping track of all of their positions (and then drawing them to the canvas in onDraw), but if you start really small by just allowing one image to be drawn and dragged around the screen, you can build on that and keep your code organized.
You would need to override onDraw(Canvas) and onTouchEvent(MotionEvent) in your custom View. You'll load your bitmaps with BitmapFactory (decodeResource method if you're including your images as resources in your project) and you'll need to remember to call recycle on your bitmaps when you're no longer using them.
In onDraw, you draw your bitmaps to the canvas at a specific location using Canvas.drawBitmap. There are two overloads of this method you can choose from, one that takes the top and left coordinates of the bitmap as floats (and therefore performs no scaling or stretching) and one that takes a destination and source rectangle to perform scaling, stretching and placement.
I always use the latter as it gives me finer tuned control. If you choose this route, you'll want to keep two Rect instances and a Bitmap instance for each image being drawn, update them in the touch events and draw them to the canvas in the draw event.
When something changes inside your view (as in the case of a touch event), call invalidate() method and the framework will know to redraw everything which triggers your onDraw method.

Scrollview Optimizations

I have a scrollview that contains a custom view. The custom view is bigger than the area of the screen and draws properly.
The scrollview however tends to call onDraw() non-stop when scrolling, and I can't seem to make it smooth.
I used ScrollView.getDrawingRect() to calculate the visible portion of the screen and only draw to that, but it still returns the entire viewport (so it's optimized to not draw offscreen areas), and not the delta between the last position and the current one. Ideally I'd want to draw only the delta, and not the entire visible window.
If anyone can point me to more information about how to use the drawing caches, and if that will help optimize scrolling, I'd love to implement it, or any other possible solutions it would be greatly appreciated.
When content is scrolled, the entire viewport needs to be redrawn because all of the content has moved. I don't think there's anything that needs to be done to optimize a ScrollView - if scrolling is slow then it's the drawing method of your custom view that is too slow.
Try to avoid object creation in your draw methods which is usually the main culprit for poor drawing performance.
Edit: Also the scrollview could blit the old content up or down quickly that is still drawn on the screen, and then request a redraw of only the "new" portion of the screen. (only applies to opaque views).
I encountered the same problem. I solved it by using the function setDrawingCacheEnabled(true). By enabling this setting, your canvas view will be cached as bitmap, so you don't have to call canvas' draw method each time onDraw() is called.
In your custom view's constructor, you will need something like this:
public CustomView(Context context) {
setDrawingCacheEnabled(true);
drawnFlag = false;
}
In your onDraw method, you will need something like this:
public void onDraw(Canvas canvas) {
if (! drawnFlag) {
canvas.drawPath(...);
canvas.drawPath(...);
drawnFlag = true;
}
}
Now, scrolling on this custom view should be smooth since we only call the drawing methods once.
Afaik the ScrollView sets a proper clip rect on the canvas your view gets in onDraw so you only need to draw what's inside that rect.
You could also implement cache bitmaps based on the clip rect's size.

Categories

Resources