Setting android view location has no effect - android

I have a simple view inside of a RelativeLayout that I animate up & down so it slides off and on screen. This works every time except the very first time, where the animation does nothing.
This lead me to trying to set the Y location manually in the activity's onCreate() method. Oddly, that had no effect either.
Is there some reason a view's Y location can't be set until after the activity has been fully displayed? If not, why am I seeing this weird behavior, and is there a way to fix it?

The first time you're calling it's before the view has laid out.
You can get around this by listening for the view to be laid out.
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Perform whatever actions you want here
}
});

Related

Scrolling is delayed when inflating view

Hope you can help me, this has been bugging me for quite some time now-
I have an activity that at some point inflates a view which has its own layout and logic behind. This view contains a ScrollView which I want to be scrolled down x dp when its shown to the user (I don't want user to actually see the scrolling, I want ScrollView to be at the right position as the view displays).
Here's what I tried so far:
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(0, someInnerView.getBottom());
}
});
I've tried using this code in different parts of my view logic such as onFinishInflate() but that doesn't work as the data isn't binded to the view at that point. So I added OnGlobalLayoutListener and called the Runnable inside onGlobalLayout() which does work but with a short delay which can clearly be detected.
How do I solve this problem? All I want to do is to have some part of my ScrollView hidden when it's presented to the user.
All help appreciated!
EDIT : to make my intentions clearer- I want to create something similar to this, only that I'm using ScrollView

Refreshing custom view layout position

I have to implement slidable menu in my app. User should be able to show/hide it by tapping on it and move left/right.
To implement this, I`ve created custom SlidableFrameLayout that extends FrameLayout.
By overriding onTouchEvent method I calculate slide position and call
private void setLeftLayout(int left) {
layout(left, getTop(), getRight(), getBottom());
}
to change position for SlidableFrameLayout. Everything works fine, but when I keyboard shows (after focusing EditText), SlidableFrameLayout changes its left value to 0, so if menu was closed, it becomes opened. The same thing happens when I hide the keyboard (generally, it appears in all actions that prevents calling layout methods, I think).
I can not invent how to fix it. Could you help me? If any additional info is required, I`ll attach it. Thanks
I think your issue is related to calling layout directly. When the container view changes size as a result of the keyboard being shown/hidden onMeasure/onLayout will be called with the view's default bounds. In your case I'm guessing the left bound is 0, so layout is being called with 0 for left every time your window resizes.
Instead you probably want to use something like setTranslationX or scrollTo ..
Good luck!
As a result, I changed my logic:
private void setLeftLayout(int left) {
FrameLayout.LayoutParams params = getFrameLayoutParams();
params.leftMargin = left;
params.rightMargin = -left;
requestLayout();
}
In my case, view is a parent of FrameLayout, so I haven`t added any conditions in 1st line of the method. This method works pretty fine.

Showing lots of views in a ViewFlipper

I have a ViewFlipper that shows a lot of views. The flipper "moves" only in one direction, meaning once a view got hidden, it will never be shown again. Here's what I call to move to the next view:
mViewFlipper.addView(myNewView);
mViewFlipper.showNext();
Although this works fine I'm not sure if it's actually clean and memory friendly. Would I need to remove any of the previous views? Or can I just keep pushing new views in?
If old views had to be removed - where would I do that? With some sort of callback, that gets fired once a view becomes replaced/hidden?
EDIT: here's the complete method:
private void OnBtnNextPressed()
{
mViewFlipper.addView(new TestView());
mViewFlipper.showNext();
}

How do you find the bottom scrollable position in a ScrollView?

In an android scrollView, how do you find the lowest position in the scrollview so you can then use the scrollTo(x,y) method to scroll right to the bottom. I need the actual numeric value. Using the getHeight() method does not ever return the right value. The scrollbar will sometimes scroll to the end, and sometimes not reach it. There is a linearlayout with a textview in the scrollview. There has to be something that I am missing?
If you want to just scroll to the end, you should be able to just use fullScroll(ScrollView.FOCUS_DOWN). If you need a particularly numerical value based on the height of the scroll view, you will have to subclass your scroll view and override onSizeChanged, which will give you the actual numerical height. Keep in mind onSizeChanged will only be called after onResume, and will not necessarily be called every time your activity resumes.
Part of the reason why you sometimes scroll to the end and sometimes don't is probably because of a race condition. Sometimes your scroll happens before other important things (like populating the view) have happened, so it doesn't appear to do anything.
Try posting your calls to your scroll view's handler:
yourScrollView.post(new Runnable(){
#Override
public void run(){
yourScrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
};
Sometimes even adding a short delay can help:
yourScrollView.postDelayed(new Runnable(){
#Override
public void run(){
yourScrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 200);
Thanks for the response. I found a quick hack if anyone is interested.
sView.fullScroll(View.FOCUS_DOWN);
sView.fullScroll(View.FOCUS_DOWN);
y = sView.getScrollY();
sView.fullScroll(View.FOCUS_UP);
This will jump down to the bottom of the scrollable, collect y, then jump up again. It happens so fast it is not visible and it will get you the bottom value of y every time. You have to call focus down twice or else y will return 0.

View Animation in onResume doesn't work after rotation change

I animate a view in onResume() based on a certain boolean.
mView.startAnimation(mAnimation);
The animation always starts when returning to the activity, but it never starts when onResume() is called following a screen orientation change. I know that the above line of code is getting called because I checked it with debugging, so the boolean is not the problem.
What's different about an Activity that's coming back from a rotation that would cause an animation not to work?
My Animation was my own extended Animation that slides a view down by modifying its top margin. To find out the correct distance to slide it, I feed it the height of the view that it's sliding down to reveal. However, views don't have any height until onResume() is done, so I was inadvertently feeding it an offset of zero.
When returning from other activities, the view tree already has the heights left over from before. But after a screen rotation, the Activity is completely destroyed, so the views don't have any dimensions in onResume().
I fixed it by doing the following:
final ViewTreeObserver observer = mObscuredView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
boolean mDone=false;
#Override
public void onGlobalLayout() {
if (!mDone){
mAnimation.setTranslation(mObscuredView.getMeasuredHeight());
mView.startAnimation(mAnimation);
mDone=true;
}
}
});

Categories

Resources