Android: Lock/Freeze layout for the time changes are made programmatically? - android

I do reorganization of my layout programmatically adding and removing several views. The problem is after the first removeView the activity/fragment starts to measure/layout the remaining views. Is it possible to put this on hold until I have done all the changes?

Inspired by the post from Arkde I finally found a solution for my problem. I simply override requestLayout() and prevent the call to be propagated to the parent ViewGroup on demand. This enable me to stop the layout process from interfering as long as I reorganize my views.

1st idea
Removes a range of views during layout.The removeView() method looks like this in ViewGroup
public void removeView(View view) {
removeViewInternal(view);
requestLayout();
invalidate(true);
}
The calls to requestLayout() and invalidate() cause your group to trigger measure/layout methods.
In order to avoid this mechanism, you should extend your ViewGroup and override this method, or create a new one to remove chunks of views,and after that trigger requestLayout() and invalidate()
or, if you want to remove all the views starting at a certain position, to another position in layout use,
public void removeViews(int start, int count) {
removeViewsInternal(start, count);
requestLayout();
invalidate(true);
}
that removes a range of views during layout.
2nd idea
If you want your layout to be dynamic and you want to grammatically add or remove parts of the screen, I think you should use Fragments instead.
3rd idea
When you need to change your layout, just create another ViewGroup programatically (or by inflating from xml different layouts), and add all the childs you need there. After that remove all views from current view using ViewGroup.removeAllViews()and add the newly created ViewGroup.

Related

Android - difference between View.OnLayoutChangeListener and ViewTreeObserver.OnGlobalLayoutListener

According to the doc, the first is
Interface definition for a callback to be invoked when the layout bounds of a view changes due to layout processing.
and the second is
Interface definition for a callback to be invoked when the global layout state or the visibility of views within the view tree changes.
///
But they seem pretty similar to me. I was even able to use both of them interchangeably. Can someone give me a practical example of the usage of them? Thanks
An OnLayoutChangeListener is a listener for a specific View and will trigger only when that View goes through a layout pass (i.e. onLayout() is called).
An OnGlobalLayoutListener watches the entire hierarchy for layout changes (so registering one of these on any View in a hierarchy will cause it to be triggered when any View in that hierarchy is laid out or changes visibility).

Child view focus change android

I have a ViewGroup that can have many LinearLayouts. And each LinearLayout can have many nested child views. What I want is that, if any view(even deep nested) inside a LinearLayout gets focus, it should call a custom method of its main parent LinearLayout.
The last thing I want to do is, set OnFocusChangeListener on every single deep nested child views of LinearLayout and that listener will call its parent's custom method. But that is really bad way to go for.
Is there any method I can override of parent LinearLayout that gets called every time its any nested child view's focus changes ?
You could use contentView.getViewTreeObserver().addOnGlobalFocusChangeListener() or override ViewGroup.requestChildFocus() of the root ViewGroup (requestChildFocus() is passed along the view parent chain).

How can I tell when a Layout (and all its child Views) has fully finished inflating?

I have a situation where I have a custom Layout which contains a bunch of children and which I inflate into a ViewFlipper.
My problem is that the ViewFlipper badly stutters its animation as it tries to animate the Layout in, even as the Layout is still loading all its child Views.
I tried using onLayout, but that gets called the moment the parent Layout is done inflating (it doesn't wait for the child views to inflate, so the stutter persists)
I also tried onMeasure, but that's called dozens of times and keeps getting called every time anything in the Layout changes (such as the EditText getting focus, or changing value).
So, I'm stumped... does *ANYTHING happen, that I can listen for, when the Layout is fully inflated, so that I can THEN tell the Flipper to perform the animation?
You can override onFinishInflate() in your custom layout. This is called as the last phase of inflation, after all child views have been added.
You could use an OnPreDrawListener. This will be called immediately before the View is going to draw its first frame, at which point all of the children will be laid out.
CustomView myCustomView = (CustomView) findViewById(R.id.my_custom_view);
final ViewTreeObserver obs = myCustomView.getViewTreeObserver();
obs.addOnPreDrawListener(new OnPreDrawListener () {
#Override
public boolean onPreDraw () {
//We only care the first time it happens, so remove it
obs.removeOnPreDrawListener(this);
//Post your animation here, then return true
return true;
}
});

How to make relative layout GONE inside ViewFlipper on condition

I have an XML, in that XML i have a RelativeLayout say R1, now inside R1 i have one ViewFlipper and inside ViewFlipper i have 7 relative layouts, Everything works fine if i load all seven on my UI, but on condition i want only 3 relative layout (inside ViewFlipper) to be shown on the UI. Can anyone help me to make rest 4 relative layouts to be View.GONE.
I tried setting them
if(X==Y){
findViewById(R.id.relativeA).setVisibility(View.GONE);
findViewById(R.id.relativeB).setVisibility(View.GONE);
findViewById(R.id.relativeC).setVisibility(View.GONE);
findViewById(R.id.relativeD).setVisibility(View.GONE);
}
but this is not working. I set this in onCreate under the require condition, but this view gets GONE only when the activity is launched and when i Fling here and there with the finger, all layouts come on the UI.
Now the only solution I am left is to create another XML with required relativelayouts, but the problem is my XML is quite heavy and i dont wanna use this last option. Kindly help
You could either use viewFlipper.removeViewAt(index) providing the index (position) of the View that you want to remove.
OR
You can use viewFlipper.removeView(viewFlipper.findViewById(ID_OF_RELATIVE_LAYOUT_TO_REMOVE))
There is also a helper method called
removeViews(int start, int count) which removes several Views in one go.
For more information, you could look into the ViewGroup - Android Documentation
Instead of hiding the view, try removing the unwanted views like
viewfliper.removeViewAt(relativeA POSITION);

Android: Generic container / Views / View.OnClickListeners

I have a container, usually a common LinearLayout, where I want to add views. After the user clicks on a view, the view should be removed from the container. Obviously, I can implement the functionality in an OnClickListener, and attach it to the view.
But, if another programmer forgets, to remove the view, after doing his stuff in his OnClickListener, the view will remain in the container.
Is there a way, that the container can enforce the removal? I haven't seen a View#getOnClickListener.
Why don't you create your own container and when addView is called you can modify the view's onClickListener.
EDIT:
This is not possible since there is no getOnClickListener and also the variable that holds the listener has the {#hide}.
I guess the only way out if extending each View and overriding the setOnClickListener method.

Categories

Resources