Jetpack Compose: is it possible to have multiple canvases in one page? - android

Can I stack multiple canvases in a column? In the example below, each DeviceView has a canvas inside.
Column() {
DeviceView(PVSUM)
DeviceView(PVSUM)
}
Asking, because it doesn't seem to work. Only one canvas is shown.
Also tried to draw each with a different offset.
Column() {
DeviceView(x1,y1, PVSUM)
DeviceView(x2,y2, PVSUM)
}
But only the first DeviceView is shown.

Related

How to draw over small portions of custom view?

I'm using a custom View to draw rectangles(which will have text inside them at a certain point) and I want to highlight each rectangle when selected, which will happen every few seconds when user selects a rectangle. Should I implement highlighted rectangle in onDraw or is there a way just to redraw each rectangle without redrawing the whole View? I was thinking of using "invalidate(rect)" but it's been deprecated.
I'm trying to be considerate of the cost of invalidating the whole View compared to just redrawing a rectangle.
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for(CellCoordinates cellCoordinate : mCoordinateCells) {
canvas.drawText(" ", cellCoordinate.getRect().exactCenterX(), cellCoordinate.getRect().exactCenterY(), cellPaint);
}
}
Using invalidate() and onDraw() is fine. Dirty rect is not really have effect on API21+
... In API 21 the given rectangle is ignored entirely in favor of an internally-calculated area instead. ...
Dirty rect is deprecated because of different drawing model in hardware accelerated views. Checkout this link for more information
Also, it seems your rectangles can be implemented as custom Drawables with states (selected and normal). It will not give you extra performance, but might help to divide and structure code for drawing. This might help

Clear previous canvas working with RecyclerView on Android

I am drawing custom ovals using canvas in Android as follows. In fact, each shape is a view and created with the help of RecyclerView. When I click any shape, I draw another oval with stroke attribute(white one).
What I want to do here is to remove previous border oval whenever I touch another shape and draw a border for it. Do you have any idea? Thanks.
Code for drawing a shape:
override fun drawOval(canvas: Canvas) {
canvas.drawOval(shapeRectF, shapePaint)
}
I suppose you have a list of models. In each model, you need to have filed isSelected: Boolean. When you need to draw stroke you set isSelected = true to the item you need and isSelected = false to the item you want to remove the previous border. Then set new data to the adapter.
In you ViewHolder draw stroke if isSelected == true

How can I anchor my DynamicLayout to the bottom of my canvas?

I am working on a custom View that includes frequently updated text that I want to anchor to the bottom of the canvas.
The text length changes as well, and I'd like it to wrap, moving up the screen as more lines are needed. (DynamicLayout thus seems like a solid choice for automating this)
However, I don't see any options in the docs about specifying where on my canvas the text is drawn or in which direction it should "grow".
Here is my initialization:
TextPaint subtleTextPaint = new TextPaint();
DynamicLayout dl = new DynamicLayout(text,subtleTextPaint,getWidth()
,Layout.Alignment.ALIGN_CENTER,1,0,true);
And in onDraw(), I simply pass the canvas to the DynamicLayout object like so:
dl.draw(c);
Right now, the text is drawn at the very top of the screen and word-wraps downwards as the text gets longer.
After quite a bit of searching, I found nothing that did what I wanted. So, in true hacker style, I created my own solution. By extending the DynamicLayout class and overwriting the getLineTop() function, I was able to achieve the functionality I was looking for.
I've posted the source code here.
What i think 1st you get the Width of the screen and then set the Text with the X y according to your screen dimension
that will work
snippet is following
width=canvas.getWidth();
if(width==720)
{
canvas.drawText(String, x , y, drawText);
}
else if(width==480)
{
canvas.drawText(String, x , (y, drawText);
}
else
{
canvas.drawText(String, x , (y, drawText);
}

Dynamically create / draw images to put in android view

I'm not sure I'm doing this the "right" way, so I'm open to other options as well. Here's what I'm trying to accomplish:
I want a view which contains a graph. The graph should be dynamically created by the app itself. The graph should be zoom-able, and will probably start out larger than the screen (800x600 or so)
I'm planning on starting out simple, just a scatter plot. Eventually, I want a scatter plot with a fit line and error bars with axis that stay on the screen while the graph is zoomed ... so that probably means three images overlaid with zoom functions tied together.
I've already built a view that can take a drawable, can use focused pinch-zoom and drag, can auto-scale images, can switch images dynamically, and takes images larger than the screen. Tying the images together shouldn't be an issue.
I can't, however, figure out how to dynamically draw simple images.
For instance: Do I get a BitMap object and draw on it pixel by pixel? I wanted to work with some of the ShapeDrawables, but it seems they can only draw a shape onto a canvas ... how then do I get a bitmap of all those shapes into my view? Or alternately, do I have to dynamically redraw /all/ of the image I want to portray in the "onDraw" routine of my view every time it moves or zooms?
I think the "perfect" solution would be to use the ShapeDrawable (or something like it to draw lines and label them) to draw the axis with the onDraw method of the view ... keep them current and at the right level ... then overlay a pre-produced image of the data points / fit curve / etc that can be zoomed and moved. That should be possible with white set to an alpha on the graph image.
PS: The graph image shouldn't actually /change/ while on the view. It's just zooming and being dragged. The axis will probably actually change with movement. So pre-producing the graph before (or immediately upon) entering the view would be optimal. But I've also noticed that scaling works really well with vector images ... which also sounds appropriate (rather than a bitmap?).
So I'm looking for some general guidance. Tried reading up on the BitMap, ShapeDrawable, Drawable, etc classes and just can't seem to find the right fit. That makes me think I'm barking up the wrong tree and someone with some more experience can point me in the right direction. Hopefully I didn't waste my time building the zoom-able view I put together yesterday :).
First off, it is never a waste of time writing code if you learned something from it. :-)
There is unfortunately still no support for drawing vector images in Android. So bitmap is what you get.
I think the bit you are missing is that you can create a Canvas any time you want to draw on a bitmap. You don't have to wait for onDraw to give you one.
So at some point (from onCreate, when data changes etc), create your own Bitmap of whatever size you want.
Here is some psuedo code (not tested)
Bitmap mGraph;
void init() {
// look at Bitmap.Config to determine config type
mGraph = new Bitmap(width, height, config);
Canvas c = new Canvas(mybits);
// use Canvas draw routines to draw your graph
}
// Then in onDraw you can draw to the on screen Canvas from your bitmap.
protected void onDraw(Canvas canvas) {
Rect dstRect = new Rect(0,0,viewWidth, viewHeight);
Rect sourceRect = new Rect();
// do something creative here to pick the source rect from your graph bitmap
// based on zoom and pan
sourceRect.set(10,10,100,100);
// draw to the screen
canvas.drawBitmap(mGraph, sourceRect, dstRect, graphPaint);
}
Hope that helps a bit.

onDraw() on View draws behind the layout

Ok, here's the deal. I want to move items in my extended gallery class to change the order of images. The way i'm doing it now:
on long press remove the current selected item,
use onDraw() to draw the same image so i can move it around using onTouchEvent()
on release add the item again
This works fine but the problem is that when using the onDraw() method it will draw the image behind the gallery items. Is there a way to change the priority of what is drawn?
Well i found this out after going into a totally different direction =/
Here's the solution for people that have the same problem:
In constructor (or anywhere else you initialize the component) set setWillNotDraw(false) and override dispatchDraw(). dispatchDraw() draws the ViewGroup children so you can decide yourself if you want to draw behind or a top of the other views.
Example taken from Custom drawing on top of Gallery view (and it's child views)
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// do your drawing stuff here
canvas.drawPath(mPath,mPaint);
}

Categories

Resources