Android: Invisible objects still clickable - android

I have an activity that has buttons and images that can appear and disappear depending on user interactions.
What I am finding is that objects at the back, which have been set to invisible, are still triggering clicks, sort of. They are not processing the code related to being clicked, but they sort of momentarily reappear, and then disappear again instantly when clicked on.
They also appear to be interfering somewhat with buttons laid over the top of them. These buttons become very fiddly and difficult to click at times, when there is an invisible object behind them.
I am using simply:
object.setVisibility(View.VISIBLE);
And:
object.setVisibility(View.INVISIBLE);
To make my items appear and disappear. Is this not what I should be doing?
EDIT:
People keep asking me for the exact same code that they are giving me. This is the code I have been given, and that I am using currently.
btnLifePlus5.setVisibility(View.GONE);
btnLifePlus5.setFocusableInTouchMode(false);
txtLifePlus5.setVisibility(View.GONE);
txtLifePlus5.setFocusableInTouchMode(false);
btnLifePlus1.setVisibility(View.GONE);
btnLifePlus1.setFocusableInTouchMode(false);
txtLifePlus1.setVisibility(View.GONE);
txtLifePlus1.setFocusableInTouchMode(false);
btnLifeMinus5.setVisibility(View.GONE);
btnLifeMinus5.setFocusableInTouchMode(false);
txtLifeMinus5.setVisibility(View.GONE);
txtLifeMinus5.setFocusableInTouchMode(false);
btnLifeMinus1.setVisibility(View.GONE);
btnLifeMinus1.setFocusableInTouchMode(false);
txtLifeMinus1.setVisibility(View.GONE);
txtLifeMinus1.setFocusableInTouchMode(false);
This makes no difference to just setting them as invisible.

Making any View invisible don't prevent us to trigger their listeners. It's just you can not see it every other thing would be same as if it was visible.
If you don't want to use it at all change it to View.GONE
Difference in View.INVISIBLE and View.GONE: Invisible objects keep on utilizing the space assigned to it while object set as View.GONE would leave the space of space as if its not on screen.
Use
object.setVisibility(View.GONE);
rather than
object.setVisibility(View.INVISIBLE);

Use object.setVisibility(View.GONE); instead object.setVisibility(View.INVISIBLE);
View.GONE Means This view is invisible, and it doesn't take any space for layout purposes.
View.GONE This view is invisible, and it doesn't take any space for
layout purposes.
View.INVISIBLE This view is invisible, but it still takes up space for
layout purposes.
I hope it will helps you .

Try:
object.setClickable(false);
As an alternative, you can:
object.setEnabled(false);

The only way I managed to solve this ridiculous issue was to create a sort of view panel that sits between the objects in my activity. This view panel is the size of the screen, uses the same colour background, and starts invisible.
Normally, I make object A disappear, and make object B appear. When I click the space previously occupied by object A, it momentarily flashes back onto the screen and then disappears again. It looks terrible. Subsequent clicks do not reproduce this bug until the next time I make object A disappear.
The fix is to make object A disappear, make the new view panel visible on top of it, and then make object B appear on top of the view panel. So the panel acts as a sort of barrier between the hidden object, and user interactions. The user is not aware that this view panel even exists, as it blends in to the standard background, but when I now click the space where object A would be, it now no longer flashes back onto the screen momentarily. While this is a poor solution to have to use, this OS is bugged and I am left with no choice.
My activity now looks as though it is perfectly stable and working perfectly. I don't like it, but it works.
Thanks a lot, google.

Try object.setVisibility(View.GONE)
View.GONE prevents view to draw its layout bounds (width and height) whereas View.INVISIBLE draws it.

You should use:
object.setVisibility(View.GONE);
View.GONE removes your view completely from the layout, but View.INVISIBLE only makes your view invisible but still found in your layout, thus clickable.

In my case, I was animating a layout and then set it hidden.
However, I was using View.GONE but still, the layout views were taking clicks.
Then I found that in the animation I was using anim.setFillAfter = true
changing it to "False" fixed the clicks issue for me.
Hope it helps someone banging their head.

Related

Leanback.DetailsFragment not scrolling as expected

I have a details fragment that is using a DetailsOverviewRow and FullWidthDetailsOverviewRowPresenter. When the page first loads the action buttons are selected. When I press down once, focus leaves the buttons and nothing else happens. When I press down a second time focus moves to a ListRow that is further down the page. I'm trying to figure out why the overview, or body as it's called in the presenter, section doesn't focus.
Should there not be a second 'state' between the two screenshots where the overview/body is readable?
Possibly of note. The DetailsFragment isn't declared in an activities xml, I'm changing fragments manually using FragmentTransactions. Also, the Fragment is instantiated using a static create method (source below).
Thanks in advance.
Activity xml
DetailsFragment java
I haven't tried this example in particular, but from my time spent with Leanback support library, I learned that even though a lot of helpful stuff is indeed provided, a lot is not :D
So I would try these things:
1) Make sure that something in the area you want visible is focusable. (Clickable elements should be focusable by default, but better check too) What I mean is that on the screenshot, there is just text, no buttons or editable content in that area. So when you press down, there is nothing to focus. What happens if you make the body TextView focusable?
(Yes, one would expect that the support library would take care of that, but that might not be the case.)
2) Find out what actually gets focused when you press down, since as you said, the focus leaves the buttons - but where does it go? (How to find out which view is focused?) You might have a "direction problem" somewhere. That is - the focus travels based on the view hierarchy tree, not based on what we see on the screen. In some cases, it is possible to skip some elements or get stuck somewhere by moving focus through an unexpected part of the view tree, that makes sense for the algorithm, but isn't logical from the human perspective.
The details presenter focus works this way :
1) First focus is given to Action buttons. Right/left nav press shifts the focus right/left between action buttons.
2) Down nav press from actions row shifts the focus from actions row to details row (individual details items itself are not focusable), this is achieved by shifting the Thumbnail anchoring position to further south.
3) Down nav press from details row shifts the focus from details row to related row.
So the details row gains focus by changing the anchoring position of Thumbnail image. Is your thumbnail image changing its anchoring position when pressing down from actions row?
Hate to answer my own question. This was due to my failure to RTFM. I was creating the fragment UI after a network request completes. For the FullWidthDetailsPresenter to work properly it and the ClassPresenterSelector() should be initialized in the fragments onCreate() method.

Can components be interacted with when their visibility is set to GONE?

I could not find anything that straight out answers this question. If I set the component (such as a Button, ListView, EditText) in the xml with a visibility of GONE, am I still able to interact with those components even though they are invisible? I tested it out with a Button and it seems to be no but I want to make sure.
When the visibility is set to GONE, the component is removed from the view hierarchy and no space is set aside for it. Moreover, there is no way for the user to interact with it (However, changes made to the View by the programmer while it is GONE become manifest when the visibility is changed to VISIBLE).
When the visibility is set to INVISIBLE, the component is still actually present in the view hierarchy, and space is calculated for it.

Difference between foo.setVisibility(View.GONE) and parent.removeView(foo)

If foo is a view, what is the difference between foo.setVisibility(View.GONE) and fooParent.removeView(foo)? I am particularly interested in memory consumption of the view, before and after both statements.
Does a view with visibility set to GONE consume memory ?
If you need to remove them and then show them again, it could be better to just set visibility to gone and then change back to visible again.
If you on the other hand don't need them visible again, simply remove them.
suppose,
if you need to delete all the available option of flying once you
select a particular flight. then go with fooParent.removeView(foo).
or,
if you need to selection of a particular flight all the flying options
are disappeared, and deselection of flying option again show all the
available options then go with foo.setVisibility(View.GONE) and
foo.setVisibility(View.VISIBLE)
setVisibility(View.VISIBLE) = setVisibility(0)
setVisibility(View.GONE) = setVisibility(8)
setVisibility(View.INVISIBLE ) = setVisibility(4)
I know this question is too old, but after what I have encountered in my recent projects, I want to give an idea of how View.GONE works, and how it can come in handy for some runtime view position manipulations.
Suppose you have added two child views inside a RelativeLayout, cv1 and cv2, and that cv2 is relatively below cv1(using layout_below). Then if you plan to set visibility of cv1 to GONE in runtime, then it won't cause any runtime error.
That's amazing to see because cv2 was relative to cv1, and now cv1's visibility is GONE.
So what happens actually with visibility GONE is that,
view's height and width becomes zero, but, view stays in the parent,
like a tiny dot or point.
So, even if any view is placed relative to it, it will be like, that view will occupy its place(here cv2 will occupy place of cv1 in runtime). Later on, if cv2's visibility is turned back to VISIBLE, than, cv1 will now occupy its actual position, with cv2 below it.
This link describes my usecase.
This approach of showing and hiding view comes in handy, when you don't want to handle the hassle of manipulating the LayoutParams of a view in runtime, when your usecase is this simple.
On the other hand, parent.addView() / parent.removeView() approach is opted when your view hierarchy is complex, and you want to manipulate margins, paddings, and relative positions of the views drastically during runtime.

Replacing views dynamically without changing activity

I would like to know how to go about doing this small problem that I am encountering while making a video player app.
On clicking the first control(the rectangular icon) in the above image the following view must be displayed instead of it which I am quite unsure as to how to do it. Here is what it is replaced by
Also please note, by any chance the activity should not be changed. I have been able to design the views individually but having problem changing them at runtime when user clicks. Could someone go about explaining as to how it can be done or provide some suitable links to achieve my goal. Thanks.
For something as simple as this you can just change the visibility of the views.
view.setVisibility(View.INVISIBLE)
Or the more effective:
view.setVisibility(View.GONE)
Do that on the views you want gone, I suggest a wrapper class. It's either this or changing the contentView as describded below.
this.setContentView(R.layout.newLayoutToUse);
However, I have a feeling there is a better way to do what you want. It's overkill to load a complete new layout if you just want to change the image of some buttons or imageviews.
This might be a stupid solution, 'cause i'm terribly tired right now, but why not use the bringToFront() method on the View that you want to display in the front? Display them both in front of each other, maybe in a RelativeLayout, and then swap between them as you wish.
They are small objects, so don't consume memory. I don't see why this shouldn't work.
OR
Place them above one another, so they overlap and then make the above view visible/invisible depending on which one you need to display.
OR
just remembered I read somewhere that you can scroll through a ScrollView automatically from code. So display both Views in a ScrollView in succession and when pressing the button or whatever, you scroll down to make the next menu visible. When pres back, you scroll up to make the previous thing available. Should work, and might also make a nice animation between changing of the menus.

ViewFlipper caching issue

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.

Categories

Resources