I have a custom widget based on the Android Gallery view. It is slightly customized to show the elements from the left of the view without a gap and pass required events to my listener.
On the very first view layout everything works perfect. However when I pause and resume the activity the view freezes. It is visible, I can see OnTouch() event handlers working, view positions adjusted, but the picture is not changing. The OnDraw() method for the Gallery widget is not called at all!
I have another widget in this layout (a sliding drawer) and as soon as I barely move the drawer everything starts working back again as it should.
I am completely out of ideas how to fix this. Tried different ways to force the OnDraw() method but it is just not working.
Any ideas?
Thanks
Make sure you override onDraw(android.graphics.Canvas) and not OnDraw() (both the Canvas argument and the lower case initial 'o').
If it's not that, then please post some code to look at it.
Related
This has been bugging me for a few days now. I have a FrameLayout and one of the elements within the layout moves to reveal a menu. I can paste the code if requested, it's a bit long since it's my play code and I haven't used any styles. I digress...
When the user presses a particular button it calls a startAnimation on a custom LinearLayout which is layered on top of another stock LinearLayout. Pushing the button again will put the custom LinearLayout back to it's original location, thus hiding the menu.
I had to create a custom LinearLayout to override onAnimationEnd so the layout would stop and stay at the final animated position (I found this based on some other questions asked here on StackOverflow).
The problem arises when the user actually presses one of the visible menu items. One of the items, for example, sorts or reverse sorts the displayed list. It appears that right after I call notifyDataSetChanged on my BasicAdapter the screen redraws itself and my menu is hidden. I have no code that closes the menu, it's almost like the entire Activity is re-created or reset when the list is told to redraw.
I should also point out that I'm extending an Activity not a ListActivity. I'm targeting API 10 (Gingerbread, 2.3) and up.
If any one has any pointers, I would greatly appreciate it. I've been wracking my brain on this for days now and it's driving me crazy. Please let me know if I can provide any more info.
EDIT:
Here's the SO post about overriding the onAnimationEnd method.
Android TranslateAnimation resets after animation
Do you record which item's menu has been opened yourself? If not, then it means that you let the UI system do the remembering for you, which would mean that this information would be lost or rendered useless (since you have changed the item ordering), so all the items reverts to their initial states.
The solution is to associate the menu opened/closed state with each data in the list, then when the adapter's getView method is called, you can rebuild the correct UI state.
Doubtless this is caused by my decidedly unorthodox layout - I have buttons in a LinearLayout in an Activity which is placed by an ActivityGroup into a Gallery. The ActivityGroup is also the adapter implementation and the over-all effect is full-screen sliding, snapping panels.
This is working (a treat, actually) except that a touch event on the parent layout puts all the buttons into the pressed state (and any release removes the state). A touch on an individual button is only delivered to that button.
The buttons are not receiving any events, they're only changing state.
Have I done something obviously wrong? Is this a known bug and is there a work-around?
Any insights would be very much appreciated.
As obscure as this problem is its solution may be of use to someone else, so I'll answer my own question.
As mentioned, I'm (mis)using the Gallery to provide a slidey-panel à la iPhone. I do this by returning the top level window of an Activity when the Gallery asks its Adapter implementation for a view.
Typical use of a Gallery would result in small Views to which it's desirable for the press event to be applied - it's more like a button then it is a panel. Our use means that there are many buttons in a single view and we don't want the press event to ever be applied globally.
So the work-around was very easy. I extended Gallery and deliberately broke pointToPosition(int x, int y), returning INVALID_POSITION every time. The Gallery still does everything else expected of it but skips trying to apply the touch down event to any elements but itself (to prepare itself to scroll or fling).
I hope this is of value to someone.
I have a custom view being dynamically inserted and the onDraw is not being called. I initially made the custom view without the dynamic insertion and it worked fine, however when moving it to my working code base, I cannot get onDraw to get called ever, even though the view constructor gets called and the onMeasure also gets called. I've tried putting invalidate() and postInvalidate() calls around the place, but they don't seem to force the view to draw. The view hierarchy looks the same for both version and I'm lost.
Can anyone help?
EDIT: A bit more testing has shown that onDraw is getting called on the emulator, but not the handset. Also onSizeChanged on the handset has the correct values coming through, but on the emulator the values are all 0.
EDIT: I've been playing about with it and still can't get anywhere, so have put a bounty on it. If you need more code / xml / info then please let me know.
This sounds a lot like a problem i had recently, with my first custom view. Did you notice if, when loading view hierarchy, your custom views show up? and anyway do they appear laid out in the wireframe preview or not?
If the latter is the case, it's requestLayout() that doesn't get called (loading view hierarchy calls that on every view - that's why it makes views show up). i've also found that a similar bug was reported already here.
I changed the View to a TextView and it seems to work now, although I'm a little confused as to why the View didn't work.
I was wondering if there is some opposite method of View.bringToFront()?
When I call bringToFront() my whole screen get locked cause i have some problem with overriding the onMeasure() method(when I implement onMeasure, my custom View doesn't draw itself even it enters onDraw method) and my custom View takes up the whole screen ...
I badly need bringToFront() but I need to start some animation that lasts for three seconds and by calling bringToFront() user input doesn't work anymore.
Can I reset that bringToFront()?
I was also looking for a sendToBack() method. However, this does not exist in the current API.
call bringToFront() on the view you want to get in the front, and then call the invalidate() method on all the view including the view which you want in the front. Repeat same for all the listeners. So when another view's listener will get called, the previous view will get invalidated and will be in background.
The views are not cached in a ViewFlipper. Is there a way wherein we can get an image of the view and show it to user so that he sees the Ui as we see on Home scrren(when we swipe the previous view also moves along and when we lift our finger, only then the next view is shown completely.)
What I want to do is that when the user starts moving his finegr on screen, the view should also move along(create an image of view).
I am not getting to do this, as when we swipe the present view goes and next view comes, we do not get both visible when we r moving our finger on screen.
Please if anyone gets what I am trying to do, do help me.
Thanks,
Farha
It's tricky to get scroll and swipe tracking working on Android, while using ViewAnimator or its subclasses.
They allow you to set in and out animations and start them at a given moment, but they work with discrete, either-this-or-the-other-view animations. They are actually using FrameLayout and after in or out animation is executed, other views' visibility is set to View.GONE to hide them from showing up under/over your current View.
The Launcher and the Gallery application are actually doing the functionality you want, by using a different approach.
They track the user touch input (onTouchEvent()), on MotionEvent.ACTION_MOVE they perform animations manually and on MotionEvent.ACTION_UP snap to the appropriate view, just like in the iPhone.
Unfortunately, this approach is actually more complicated than it looks like.
With the manual handling, you have to ensure that you are taking care of everything related to the touch input. This includes a lot of flag-raising, value-checking, event-delegating, etc.
If you want to get better acquainted with this, take a look at these classes from Gallery3D or Launcher's source code.
One other way to get nice horizontal scrolling is to use HorizontalScrollView.
You have to figure out a way to recycle your views, like you would with a ListView and you have to add the snap-to-view logic, but if you have to take care of a small number of views it could be the easiest approach.
Hope that helps.