Drawing custom view at runtime - android

Hi I'm having trouble understanding how to draw a custom view at runtime. For simplicity sake, say I have a custom view (Box) that extends the View class, and basically all it does is create a square which is configured to do in my onDraw() method. Now I want to be able to draw this custom view in an activity depending on if the user clicks a button on the activity.
So if the user clicks the button once, one box is drawn, clicks again another box is drawn maybe 10 pixels down etc. I searched for a solution but all I can find is people using a pre-made xml with the view and then using an inflator but I dont want to have a pre drawn box if the user hasn't pressed the button.
Also another quick question: When is onDraw() called or do I have to explicitly call
Box box = new Box();
box.onDraw(canvas);
Eclipse says that's a suspicious call, I agree.

To make a custom View you have to extend View class and override onDraw method. Then when you want to draw this view you have to add it to your view hierarchy. This is as simple view.add(new Box()), where view is your root view, this way Android system would invoke onDraw method by itself on every rendering cycle. For more information refer to official documentation.

Related

How to get pixel bitmap of everything, including Dialogs and Toasts, in Android?

I've done some search in the internet. Some suggests use of PixelCopy API or Canvas. However, either way is limited to get the bitmap of the decor view. If there is a toast or AlertDialog on top of current activity, their images would not appear in the final bitmap.
So my question is, can I get bitmap of the whole activity, not only view, so the bitmap contains any Dialog or Toast on top of the activity?
So my question is, can I get bitmap of the whole activity, not only view, so the bitmap contains any Dialog or Toast on top of the activity?
Yes, we can use the window manager to get access to all the views in the hierarchy.
How to achieve this:
Get window managger for the activity, which is responsible for managing an ordered list of windows and contains the info on how they are laid out on the screen. This gives Object holding the view hierarchy you needed.
For the targeted class from the object, get the declared fields using the getDeclaredFields() method. This gives all the view fields declared for the given activity view. You can differentiate the view hierarchy with field labels mGlobal,mRoots, and mParams.
This gives you access to all the view fields declared in the activity.
A thoughtful implementation of this is done here Falcon.

Advice on this UI implementation?

Here's the basic UI i intend:
There is central circle:CENTER. As the view is rotated, new circles:NAME are generated on the circumference. The circle at the top is a newly generated circle, i.e. if an already generated circle passes the top it fetches a new name.
I don't know the Android API well enough yet, so can someone point me in the right direction? What classes should I look at? How can I create that sort of pathing? Do I generate circle programmatically or have the views already in the xml layout but invis?
Thanks.
EDIT: Currently I'm working on the custom views that will be each circle.
I think you could do it by extending AdapterView. I would start by looking at the source code for it and some of its decedents to see how they implemented them.
The functionality you are after I don't think is very far removed from a ListView or some of the other simple Adapter ready View widgets.
The main difference is going to be your onDraw() method, you'll need to override that to draw the circles for you. Whether you make the circles programmatically or define your own views in xml is going to depend on how you want to appear visually.
I don't have any sample code for the rotation effect you are after but surely it can be accomplished with a canvas and some geometry.
Once you've got the AdapterView built you'll also probably want to subclass an Adapter to hold your names and override its getView() method to populate the names into the circles for you.
If you have not ever implemented any of the ViewGroup widgets I suggest you start by exploring some of those. ListView, GridView, etc.. Learn how to use it with an adapter and some data to create the dynamic layout. Once you have a good understanding of how to use the ones that are already built then start trying to tackle the one you want to make.

Do I need to call back super.onDraw() in a custom view?

I'm not too clear about this and neither are the docs.
When I'm creating a custom view, I override like so:
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//more code here...
}
My question is whether it's necessary to call super.onDraw(canvas);. The code seems to work fine without it, but I want to be sure that it's okay to leave it out.
So is it necessary?
If you want it to call the superclass onDraw method (think TextView or KeyboardView rather than a generic View), then call super.onDraw. If you don't want that, i.e. you are planning on drawing the entire View yourself (which it seems you are), there's no reason to call it.
Also, if you're extending View (and not some class that extends view), super.onDraw doesn't really do anything.
For me, I call super.onDraw when I want to draw lines over a KeyboardView. So, super.onDraw draws the keyboard, and my custom LatinKeyboardView (which extends KeyboardView) draws the swiping path on top of the keyboard.
A peek at the source code shows that View.onDraw() is an empty method. So, calling super.onDraw(), if the parent class is View itself, does nothing. It's unnecessary yet harmless.
Whether you should go ahead and do it anyway is a separate question of efficiency, safety, and style.
Yes, it is. If you custom a TextView, the super.onDraw will ensure to draw whatever belongs to TextView attributes (like the text, text color, text shadow, etc...) The same with other Views like Button, CheckBox...
In case your custom View extend View (not a specific subclass of View, just View), it is still better to leave super.onDraw(canvas) there for some View's draw methods (like setBackgroundDrawable, etc...)
It's not required unless you are actually overriding the onDraw() method. If the new class doesn't override it, the super's method will automatically be called.

updating a TextView from another concurrent View

So this one is probably very simple, but I'm having a bit of trouble figuring it out.
So I have a custom View, which is now running in an activity along with a standard TextView widget.
What I want to know is whether there is a way to update the TextView from my custom View class
Define a listener interface in the custom view. Define a setXxxListener() method in the view. Override the listener in the activity class. From the custom view, call the listener when needed. In the activity's listener implementation, update the TextView.
Such is the Java way.
In general, view classes should not make assumptions about other views running along. The object that manages both views - in your case the activity - should coordinate the data exchange between them.

How to detect when a drawable is touched

I'm working on an app that has a canvas with a bunch of little images that the user can drag around, and a "box" that the user will drag from to create new image objects or drag an existing image to it, and it will remove it.
What is the best way to detect if the user has touched an area, or an image on the screen? The first thing that comes to mind is obviously comparing the touch coordinates with each object's coordinates, but that seems a little cumbersome. Is there a better, or built in way?
Thanks
It depends on how complicated your interface is, but basically if you override onTouchEvent that will get you the coordinates you were referring to.
In order to find what was touched, without going through every object, you could find ways to simplify this, such as by splitting your screen into perhaps 8 grids, and know which grid(s) every object is in, so that when the screen is touched then you can find the objects that may be in that grid, and so you will have fewer items to look through.
For a brief answer on how to use onTouchEvent you can look at:
http://androidforums.com/android-games/210019-touch-event-image-made-canvas.html
The View class in Android has an onClickListener which you can use to detect when the user clicks on a View. If you implement your 'images' (as you call them) as Views you can simply add a click listener to each to find which view was clicked. Add the listener like this:
// Get a reference to the view from xml (or if you
// have created it dynamically, just use that)
View imageView = findViewById(R.id.my_view);
imageView.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// Do stuff with view (the View v that is passed is the View that was touched)
doStuff(v);
}
});

Categories

Resources