When are views drawn in android? - android

I want to get the size of a view that is in my activity but I am not able to get that information in any of the activity lifecycle callbacks (onCreate, onStart, onResume). I'm assuming this is because the views have not been drawn yet. At what point are views drawn and is there a callback I can put my code so I can get the size of the view?
findViewById(R.id.header).getHeight();

How are views drawn provides a good overview of the process of drawing views. Basically, there is a pass where the measure what everything wants to be, and then a second pass when things are layed out.
It sounds like for your problem though, you should be able to accomplish your goal with resorting to setting height values by hand. Have you played around with the stretchMode, gravity, layoutHeight, etc of your gridview? See GridView javadoc for some details of the param choices.

It should work in onCreate(), onStart(), and onResume() after you've instantiated your layouts. Try:
findViewById(R.id.header).getLayoutParams().height

Related

Why is my layout completely redrawing when I invalidate one of it's views?

I have a complex frame layout containing several custom views. The main view is a graph.
Overlaying the graph is a custom view which represents a cross hair pointer that the user can drag around the graph to read off detailed information about a particular data point.
The frame layout captures all touch events, calls "hit test" methods on each of it's child views to determine if the touch was on that view then dispatches the touch event to the appropriate view.
When the user touches the cross hair and drags it, I pass the touch event to the cross hair which it uses to update it's position and invalidate itself.
Everything is working except...
All views in the layout are redrawing when I invalidate any of these child views. I know this as I have turned on "show screen updates" in developer options. At no point do I invalidate the containing FrameLayout - or at least, not knowingly.
Certainly, the Activity handling the layout does not invalidate it and I do not have any references to the parent in the child views.
I haven't posted code since a) I don't know if this might be normal behaviour, b) there's a lot of it! and c) if it's not normal behaviour, I don't know which part of the code is problematic. Of course, I'm happy to give anything that might be requested.
My minimum API is 2.3.3 and my target is 4.0. This happens on both of those versions so I suspect my code is the problem but where to start?
Any clues as to what might be going on?
There is no way for View to draw "just itself", since it depends on it's parent (which provides it's clipped and translated Canvas via dispatchDraw method). Invalidation requires whole view tree to be invalidated - this is the answer that you're looking for :)
If you'll check out the source of ViewGroup, you'll find there two important methods: dispatchDraw (which responsible for dispatching draw event down to it's childs) and drawChild (which called by dispatchDraw and let's you specify how childs will be drawn). Note, that there is no check on which View starts invalidation, although there is a RectF that specifies invalidation region. As far as I understand - you need to make sure that your invalidating View (cross) doesn't takes the whole screen, so redrawn will be only that part that it actually takes.
If understand you right, the lines of the cross-hair view cover the whole screen, i.e. one vertical line from top to bottom and one horizontal from left to right.
Now if you change the center of the cross-hair and the other views would not be redrawn, your screen would soon be cluttered with old lines from previous cross-hair positions. You would not want this, so you can be glad that the other views redraw itself too.
If you want, you can specify a 'dirty' rectangle and call invalidate(Rect dirty), which would not redraw Views that are completely outside that rectangle. Though it's up to you in that case, not to change anything outside that rectangle.
try this:
setDrawingCacheEnabled(true);
Enabling drawing cache for view will make view not be redrawn if view not changed
Take a look : Android Invalidate() only single view
May be my answer so simple, but I resolved this problem with help:
this.invalidate()
Run it for each canvas-view, and it will updating one by one (not all at once)

Android EditText over SurfaceView

I have a custom View inherited from SurfaceView and I have EditText in the same RelativeLayout (both custom View and EditText are siblings in layout's xml).
When I make visible an EditText, this way
setVisibility(View.VISIBLE);
the custom View receives continuous calls of onDraw(Canvas c) method.
Does anybody know why? I never called invalidate() explicitly.
There isn't anything wrong here. This in normal behaviour. onDraw() is called a lot of times because Android redraws your activity whenever it feels there is a change it needs to display. There are a lot of sophisticated internal algorithms that decide when and why an activity is redrawn. Android takes care of it for us and we don't need to worry about it.
Once an activity is redrawn, all it's children are redrawn as well. This happens with all views and not custom views. Rest assured that there isn't any problem with your code.
Interested in learning more about the internals? Check out the source code for the View class!

Too many views in activity

I have an activity with more then 200 diffident views and layouts. Some of the views are images and some are texts or buttons. The visibility of the views changes from time to time, and so some of the textView contents, but nothing more.
The problem is with devices with big screens when the activity is out of focus and gets deleted from the stuck (see here under "Saving activity state" section). Unfortunately, to restore it with onRestoreInstanceState() , is a real mess.
I was wondering maybe I should not use Views but implement it in a different way in order to save memory?
Maybe just bitmap images on a Canvas or something else?
Any suggestion tricks, tips will be appreciated.
I suggest you to use Fragments, if you have a lot of views and layouts in one activity.
you can use any number of views as layout, you saying that it will change depends on time,
use setVisibility(View.Visible)
setVisibility(View.GONE)
setVisibility(View.INVISIBLE)

Using a FrameLayout as a Live Wallpaper

I'm trying to use a FrameLayout as the content of a Live Wallpaper. According to this answer by Romain Guy, it should be possible, but I didn't have much luck calling .measure() and .layout() on the view. Could anyone give me a brief example of how to use a regular layout inside a Live Wallpaper?
It's a wallpaper that you can mess around with, right? If you are going above the usual views, you may have to implement some custom logic, especially if you are drawing images. A FrameLayout has background and foreground drawable functions. You can use XML or Java to add regular views into a FrameLayout
You also can create a custom Drawable object to do a lot of fun things with regards to custom painting. The Drawable object simply gets sent the view's canvas.
If you want to measure views, you are going to have to do it after the view runs through its measure and layout codes. This means doing this in onCreate() returns 0. Lots of people have had better luck doing it in a callback like onWindowFocusedChanged

Changing View properties after onCreate()

First time poster, new to Android, and I seem to have hit a roadblock on this problem:
I'm creating a dynamic layout, consisting of several identical "composite" objects (these are basically "floating" LinearLayouts, each containing an icon (ImageView) and a caption (TextView)). The (x,y) coordinates of each LinearLayout are subject to change, based on user actions, and require precise placement (ie: can't use RelativeLayout, etc), so I'm positioning them inside an AbsoluteLayout.
During onCreate(), I'm adding each of these objects as a child View inside an AbsoluteLayout object, then setting the (x,y) manually. No problems so far, works great, initial layout is perfect.
The problem:
After the initial onCreate(), I can't get the (x,y) positions of these objects to change on the screen. I can update their layoutParams, but the on-screen layout (inside the AbsoluteLayout) is never refreshed. I've tried forceLayout(), invalidate(), requestLayout(), none of them work.
Is there a problem with my basic approach here, or is there something I'm just missing?
I'm thinking of changing to a SurfaceView and just doing the rendering the hard way, but my code works 99% great right now and I don't want to change it if I don't have to. The only problem is that the layout manager simply refuses to register the position changes for my child objects.
Help, what am I doing wrong?
Did you try creating a handler for UI and then updating your UI from that..
UI will not be able update from different thread. So, create a thread handler for UI and update the changes to UI using that handler.
-vinay

Categories

Resources