I am a newbie. I make a simple game using Canvas. I wrote almost all the code inside the onDraw() method and there is a lot of calculations there. There is an invalidate() method in the end of onDraw() in my code. That's how I call to redraw my view. How can I redraw only a part of Canvas? The main problem is that I have a lot of calculations inside the onDraw() and it slows the whole game. I tried to use bitmaps like here:
creating a bitmap - stackOverflow
but it didn't resolve the problem because creating a bitmap is too slow process. Is it a good idea to use SurfaceHolder and Callback? I tried to use it but I don't know if it is a right way to do what I want to do. Can anybody help me? How to redraw my view only partially to stop chosen elements always redrawing by new calculations (to drawing them from saved state)? I want to redraw whole view only when it is needed. It would be great if somebody post a code which would resolve this problem (it could be even two rectangles).
use the same bitmap instead of creating a new one, and call invalidate with a rectangle (or with the bounds) as its parameter.
in the onDraw, you can call canvas.getClipBounds() in order to find the rectangle to invlidate.
also, in order to improve your code, try to avoid creating new objects on the onDraw method.
in fact, if it's a heavy game, consider using openGL instead. for simplicity, you can use third party libraries like libGDX or AndEngine.
Try creating the Bitmaps in the Class method and calling them from onDraw().
public class DrawView extends View {
public DrawView(Context context, AttributeSet attributeSet) {
super.DrawView(context attributeSet)
//Create your bitmaps in here
}
}
Related
I want to draw a bitmap to the canvas.
However, I am an inexperienced programmer and don't know how to make the canvas the main screen.
Basically, I want to draw a bitmap to the main activity using a canvas. I know how to draw bitmaps to canvases but it doesn't show up anywhere that I can see (with only one activity). I want the bitmap to show up on the main activity. Any tips?
Sorry if the wording is confusing, thanks for any help.
see these links. might think they may be helpful.
https://www.linux.com/learn/tutorials/707993-how-to-draw-2d-object-in-android-with-a-canvas
http://www.linux.com/learn/tutorials/703911-2d-drawing-with-android-motion-sensors
you can try searching online..
some example
http://www.edu4java.com/en/androidgame/androidgame2.html
or some game engine which will help you to develop game with proper memory management.
https://stackoverflow.com/questions/17163446/what-is-the-best-2d-game-engine-for-android
What you are trying to do is create your own CustomView. When you are putting a button or anything in your layout file that is actually a view. Android does allow you to create your own view to manually handle things on the screen. Games are usually implemented that way. They use customview by extending SurfaceView/GLSurfaceView.
As for the solution of your problem:
create a custom view by extending the View.
add all the constructor from superclass.
override onDraw method
onDraw method will pass you a canvas for you to draw
draw whatever you like(Bitmap, line ,....) using canvas
In your layout file include the customview you just created.
<my.packagename.MyCustomView android:width .... > </my.packagename.MyCustomView>
Hope this helps.
Also you will find lots good resources on how you can create your own customview.
I am trying to develop an android application to display a zoom-able, pan-able map, (which is just a bitmap image), that also allows the user to click on certain points on the map.
I am struggling to find the most effective way of implementing such an app. After trying numerous other methods, (including Webviews, OpenLayers), the best way, (according to this site at least), seems to be using a SurfaceView with a Canvas. The code I have so far is pieced together from snippets I found all over the internet, so it just crashes. I have included it here anyway in the hope it gives some idea of what I am trying to achieve:
public class Main extends Activity {
private Bitmap bmp;
private SurfaceView surfaceView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = (SurfaceView)findViewById(R.id.surface);
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.testmapbmp);
//decode the bitmap file
Canvas canvas = new Canvas(bmp);
//create a canvas from the bitmap, then display it in surfaceview
surfaceView.draw(canvas);
}
}
Is this the best way to achieve the functionality I want for my application? Or is there a better way, especially if I could run into problems later on, implementing the clickable sections of the map, for example.
I really need help from someone who has created something like this before, so I can get my train-of-thought on the problem, but I greatly appreciate any help/pointers/tips at all!
Thanks
Your piece of code is not really correct.
Usualy if you want to do this kind if things you need to create your own custom view (either by inheriting View or SurfaceView). In your View subclass you need to override method onDraw(Canvas) and draw your bitmap on canvas by using one of canvas methods.
To make it pannable and pinch-zoomable you need to use Scroller and ScaleGestureDetector classes. Usually panning or scaling is done by applying affine transformations to a canvas by using it's methods (rotate, scale, translate).
Difference between SurfaceView and View is that in SurfaceView you can draw directly from separate thread, which means you can organize sort of rendering loop there and draw from it. It is good for simple games and animation effects. I believe, for purpose of drawing a bitmap this is overkill and much simpler to subclass View.
I'd start with this and this, if I were you.
I'm creating a custom TextView by using TextPaint in the onDraw() method.
however this is causing severe problems for my app.
performance wise I mean.
The onDraw() method gets called over and over again .
but i just want it to draw once :(
i tried using setDrawingCacheEnabled(true); but no effect there.
There is also a viewflipper with textviews in the main layout rotating automaticly,
could this be causing everything to redraw ?
can anyone give me some pointers here ?
As well as enabling the drawing cache, try creating a new bitmap instance in the inDraw and pass that to the Canvas to draw to. In the next call to onDraw, simply draw that bitmap if it is not null. I'm doing this myself and it works a charm to improve performance, though unable to copy the code right now (out using phone).
As for why it is being consistently redrawn, are there any moving overlapping graphics causing it to be invalidated?
I'm developing chess game for Android (androidchess.appspot.com). If I want to add animations, should I use custom View extending Canvas (I do this now), or custom View extending SurfaceView?
I haven't tried using a View to extend Canvas, but for my game I'm using the same method as the LunarLander example game:
public class CustomView extends SurfaceView implements SurfaceHolder.Callback
The usefulness of this is that it gives you handles for SurfaceHolder (so you can call up the canvas which is drawn to the screen), and the callbacks for surfaceCreated, surfaceChanged and surfaceDestroyed. That lets you do things like drawing a custom animation as soon as the surface is available or make sure that you don't try to draw to the canvas after it has been deactivated. Looking through LunarLander should show you how to use these properly.
Edit: I remembered another reason why using a SurfaceHolder was useful. This is because, as I mentioned above, it lets you get direct access to the canvas which is drawn to the screen. With a SurfaceHolder this is done not by overriding onDraw but by using something like Canvas canvas = mSurfaceHolder.lockCanvas(). (See LunarLander for exact syntax). The reason this is important is because it lets you control exactly when the drawing happens. If you can only work by overriding onDraw(), then the drawing doesn't happen until your program reaches a 'waiting' phase. In other words, you can't use invalidate() and onDraw() in a loop because the drawing won't happen until the loop finishes. And since you're likely to use loops for things like drawing a piece moving across the screen, this becomes a problem.
Note: It may be possible to avoid this problem by using multiple threads. I simply haven't tried that since it isn't required for my game; the only animation is has is fixed-length animations in response to user input rather than something continuously moving in the background, so I haven't experimented with multiple threads yet.
I'd like to include a simple draw feature on my app. A friend told me I can't use canvas because I need to control the frame buffer and not redraw the entire screen every for every frame. He suggested I find a openGL 2d engine. I've searched around and I've only found Rokon which doesn't have any documentation and the examples aren't quite what I need.
Any suggestions?
I don't really understand what the problem is?
If you simply wish to redraw some portion of the canvas you can use invalidate(rect).
http://developer.android.com/reference/android/view/View.html#invalidate()
Just create a custom veiw by extending the view class. in this custome view override the onDraw method. Android itself takes care of the pixels that have been changed and calling invalidate only refreshes the pixels that have been marked dirty