Currently I have a class that draws a bunch of squares dynamically based on the contents of a sqlite file. As the data is quite large the drawing is many times larger than the screen. I've read a lot of proposed methods to do this and am unsure of the best approach. As I will not change the image after I render it (only need to dynamically render it upon restart) the first answer listed here seems to be the best but I'm not fully understanding how to do so.
If I understand correctly I:
create a bitmap,
create my canvas (that is larger than the screen resolution)
grab the cached bitmap and
render the bitmap versus the canvas.
But I'm lacking the knowledge to make this happen within my existing code. My existing code simply creates a very large canvas (I do not define the bounds, I just start drawing). My main class looks like this:
package com.example.drawdemo;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
public class DrawDemo extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new DrawView(this);
drawView.setBackgroundColor(Color.WHITE);
setContentView(drawView);
}
}
And the DrawView class something like this:
public class DrawView extends View {
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
//LOTS OF CODE HERE to figure out how to render rectangles through loops
// similar to lines like this
canvas.drawRect(xStart, rectYPointer, xEnd, rectYPointer+rectSize, paint);
// or this
canvas.drawText(String.valueOf(rectSize), 130, rectYPointer*2, paint);
}
}
Is the approach I am taking the correct approach to allow me to scroll down and see this large image that is bigger than the android screen? If so, how do I migrate my code to conform to the approach listed in the answer I believe is the correct method?
Well I'm affraid you didn't get the point of the linked topic. It's quite different as what you try to achieve.
this topic is about drawing on a bitmap to be used later.
you already have a constructed bitmap do you ? ( or at least you can load it from resources using :
BitmapFactory.decode... (resource or file according to your input, see the documentation here)
Your canvas doesn't have to be huge in order to scroll it inside the screen. The size of the canvas is the size of your view (here, the size of the screen) but you will be drawing the bitmap according to the scroll position you want to apply.
see : canvas.drawBitmap() 's documentation
and canvas.translate can help too.
Basically what you want is : get a reference on a loading bitmap (using bitmapdecode) in your view.
then in the onDraw, draw the bitmap on the view's canvas to show it on screen.
then, to add the scroll effect, try to change the y translation of the canvas when drawing on it.
hope that helps.
For more information (and a good example) about drawing on a canvas I suggest you open the API demo project source code :
API Demos -> Graphics -> TouchPaint
Related
Good day to you all, I am creating a ride app and I was asking for some assistance in the following problem I am facing.
So, On the image below the grey background represents a google map fragment and above it sits two views(black) I wanted to know if it were possible to only show a polyline and markers between the black views only in the red area and have the rest of the map showing in the background as well.
If it helps I have managed to get the LatLng's of the corners of the red box using:
googleMap.getProjection().fromScreenLocation();
Thank you in advance!
Yes, it is possible. Several ways. For example, the red area of your figure can be View (e.g. custom view) with transparent background and you can draw your polylines on it (you need to take into account position of transparent "red" view on map view for correction of fromScreenLocation()/toScreenLocation() methods results). Also, probably, you can use two MapViews one over another and synchronize its scrolling and zooming, but IMHO best way is to to implement custom view component based on MapVew (or MapFragment) an override onDraw() for MapVew-based (or dispatchDraw() for MapFragment-based) method like in this or that answers:
..
#Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawPolylinesInRegion(canvas);
canvas.restore();
}
...
In drawPolylinesInRegion(canvas); method you should draw your polylines and markers "manually" converting coordinates of them via method opposite you mentioned: toScreenLocation() and taking into account size of "gray regions" of you example figure.
I'm trying to make my first game in JavaFX, where a player object (not a Node) will move inside a level. However, the full level shouldn't be visible inside the window, only a part of it surrounding the player should be. I've searched quite a bit for a solution to this that works with the way I've done my project, but haven't been successful. The following code describes how I've set up my GUI:
private VBox appRoot;
private Pane gameRoot;
private Canvas canvas;
private GraphicsContext gc;
private HBox uiRoot;
This is the different panes I use. The appRoot contains both the gameRoot and the uiRoot, in that order. The gameRoot contains the canvas. Everything inside the level, including the level itself, is drawn onto the canvas, like this:
canvas = new Canvas(ROOM_WIDTH, ROOM_HEIGHT);
gc = canvas.getGraphicsContext2D();
createLevel(ROOM_WIDTH, ROOM_HEIGHT, CELL_WIDTH, CELL_HEIGHT);
gc.scale(2, 2);
drawLevel(gc, ROOM_WIDTH, ROOM_HEIGHT, CELL_WIDTH, CELL_HEIGHT);
player.render(gc);
createLevel and drawLevel just creates a level and draws squares where different blocks should be. The player object's render method draws the player at its x- and y-coordinates. As you can see I've scaled the canvas, so as of now the entire level isn't shown when the game is started.
The problem is that I can't make it so that what is shown in the window is the things surrounding the player object. I've seen some code utilizing the methods setLayoutX and setLayoutY, but I've been unable to reproduce this so that it works.
I would be very grateful if anybody could help me out with this, and hopefully without changing too much of how the drawing is done.
Thanks! :)
Also, here are two pictures showing how it looks; the first is when the player is not inside the current view, and the second is with the player in the view.
Image without player in view
Image with player in view
Do not us the Canvas directly to display the level. Instead you can use an image that represents your level and then have the image in an ImageView. On that ImageView you can define a viewport of the area of the image that is visible.
To get the image you can either use your Canvas node and take a snapshot (See this question). This is probably the easiest way with what you have. Or you can forego the Canvas altogether and draw the image. If the levels are predefined (and not generated at runtime), this seems the best approach, then you can supply the images as resources along with the code.
I have an Activity containing an ImageView and I'd like to allow the User to select part of it's content with the touch (or mouse click) capabilities.
I'd like to write a procedure able to achieve two things:
Draw a highlighted window over the selected parts of the image
Return an object containing the coordinates of the selected (highlighted) pixels.
For better understanding you can check the little mock up I've created:
The User should touch the screen over some part of the image and it should get highlighted. When pressing the back button I'd like to obtain via Java the coordinates of the pixels that were highlighted.
Can you help me understand how to do?
In particular I'd like to find out the following:
should I access pixel level information of the image?
which classes are needed to implement this functionality?
some idea of pseudo code?
Thks for any kind of help!
I would subclass ImageView then you can capture the touch events by overriding onTouchEvent(...)
When you get to the onDraw(...) method you can call super to draw the image as normal, then add your own code to draw a highlight over the top.
EDIT
Well instead of using ImageView you can extend it and write your own class, all this class has to do is override onTouchEvent(...) so you know when the view is being touched and can save the location on screen of the touch events. Next you edit the drawing methods:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); // So the image you want is drawn as normal
myMethodForDrawingAFancyHighlight(Canvas canvas); // add your special effects on top of the image
}
I am attempting to build an augmented reality application for Android and have come across the problem of layering surface views. I need a surface view to display the camera preview onto which I will overlay graphics, and I need a surface view to draw my graphics on. This second surface also needs to be drawn above the camera preview but have a transparent background. In my current implementation, I have both surface views working and appearing as they are supposed to, but the background is not transparent and therefore there is no appearance of the second surface view with the graphics drawn being superimposed on the camera preview surface view. How could this be achieved? Upon searching numerous stack overflow questions as well as other forums I've come across many conflicting opinions pertaining to this matter. Some say that layering surface views in Android is impossible whilst others say that it is a matter of using a different layout (FrameLayout vs. LinearLayout?) Specifically, my implementation includes two views: a class, CustomCameraView, that extends SurfaceView, and a class, CustomDrawView, that also extends SurfaceView contained in a FrameLayout with the CustomDrawView appearing after the CustomCameraView. How can these be layered so that CustomDrawView seems superimposed on CustomCameraView?
I think a lot of people have tried this. A Google Enginee stated (here) clearly, that you should avoid stacking Surface Views. Even if somebody has found some trick to do it, it is probably incompatible and will lead to problems.
I think this gives three options, depending on your requirements:
View(s) on Top of Surface View
Use a Surface View for the Camera preview and stack Views on top of it. The disadvantage of this approach is that drawing on "normal" Views a) is slower and b) takes place in the UI thread. You can get around b) if you implement the threads yourself. But generally, that is probably the way to go if your overlays contain something like UI elements or a few Drawables that don't need to be updated too often.
Do everything in a SurfaceView
This will give yo better performance and less overhead during runtime. You have just one SurfaceView. Composite the overlays on your SurfaceView and and draw everything there. Of course, you can combine both approaches.
Do everything in a GLSurfaceView
This is probably the way to go for real performance. Like above, but with the camera view rendering to a OpenGL texture in a GLSurfaceView.
I got this working having 2 transparent views above the camera's SurfaceView using the following approach:
My activity sets up all its views in the onCreate() method, I make no use of any layout file for that. It looks as follows:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null); //savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
cameraPreview = new CameraPreview(this);
addContentView(cameraPreview, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
animationView = new AnimationView(this);
addContentView(animationView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
crosslinesView = new CrosslinesView(this);
addContentView(crosslinesView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
cameraPreview is of type SurfaceView, animationView and crosslinesViews are of type View. The onDraw() of the 2 latter views looks as follows:
protected void onDraw(Canvas canvas) {
// Have the view being transparent
canvas.drawARGB(0, 0, 0, 0);
// Your drawing code goes here
// ...
}
Good luck!
Is there a possibility to add a view or derivative (button, textview, imageview etc...) to another view without having to go through layouts?
I have a class called ScreenView, it derives from View (e.g. public class ScreenView extends View).
I wanted to display text into it, labels, images etc..
On an iPhone it's trivial, simply create my objects and use addSubview method ; you can embed any UI objects into another. Most UI toolkits work that way too.
Problem with layouts is that I haven't found an easy way to properly position a subview (say a text view) in a given location of the enclosing View. I want one to contain the other...
I was hoping I had missed something in the documentation (which is far from being intuitive that's for sure) and I could do something like myView.addView(subview). But it ain't so :)
As a side question, what is the closest to iPhone's UILabel in the Android world?
A UILabel can contain a text or a graphic. Right now I've been using TextView and ImageView but they aren't anywhere as flexible when it comes to layout as a UILabel
Edit: Making my View inherit from ViewGoup instead, let me add subview..
However, I want to draw in my view. I found that when ScreenView extends ViewGroup, the onDraw function is never called then.
Something like:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
// make the entire canvas yellow
paint.setColor(Color.YELLOW);
canvas.drawPaint(paint);
}
Would paint in yellow my view if ScreenView extends View ; but not if it extends ViewGroup.
How do you draw directly in the view then?
Thanks
JY
Use a ViewGroup, that's what they are for. And then you can call addView() :)
After making my class inherit from RelativeLayout instead, it does draw my subviews.
GroupView doesn't draw anything by default, and onLayout needs to be fully written. With no documentation on this matter it's going to be a hard thing to do.
onDraw isn't called by default, it does get called if you set the background colour or add any drawable item.
Otherwise you need to draw during dispatchDraw instead.