WHAT I HAVE DONE
I used the following function to resize the size of scrollview (used as a slidinglayout)
the second child if slidinglayout is a map fragment. there is a button "select from map" where the sliding view is completely hided.
Problem
problem is that sometimes when i select from map. the sliding layout collapses but the map fragment doesnt expand properly and it remains as previous . THUS A BIG WHITE SPACE IS LEFT BEHINF.
KeyBoard soft input doesnt resize properly. I am usinf adjust pan but it scrambles the whole view and scroll view doesnt scroll till the end
public void resizeScrollView(final float slideOffset) {
// The scrollViewHeight calculation would need to change based on what views are
// in the sliding panel. The calculation below works because the layout has
// 2 views. 1) The row with the drag view which is layout.getPanelHeight() high.
// 2) The ScrollView.
// Log.d("resizeScrollView - height %d panelHeight %d slideOffset %f", mySlidinglayout.getHeight(), mySlidinglayout.getPanelHeight(), slideOffset);
int scrollViewHeight = (int) mySlidinglayout.getPanelHeight();/*mySlidinglayout.getHeight() - mySlidinglayout.getPanelHeight()) * (1.0f - slideOffset)*/
if(slideOffset==0.0f)
{
scrollViewHeight=(int)(mySlidinglayout.getHeight());
}
final ViewGroup.LayoutParams currentLayoutParams = scrollView.getLayoutParams();
currentLayoutParams.height = scrollViewHeight-30;
scrollView.setLayoutParams(currentLayoutParams);
}
Related
I have a viewpager which displays a next and prev views as preview. Each displayed view has a scrollview. Since my viewpager shows preview there are some padding and margin given for the viewpager. Now what i need to do is, On scrolling the view of the visible item the viewpager the view should become animate and become full screen. I tried adjusting the padding and margin on scroll but its not working. Is there any other way to get that.
achieved the view pager animation using the following code
final float MIN_SCALE = 0.90f;
final float MAX_SCALE = 0.95f;
#Override
public void transformPage(View page, float position) {
page.setTranslationY(0);
float scaleFactor = MIN_SCALE + (MAX_SCALE - MIN_SCALE) * (1 - Math.abs(position));
page.setScaleY(scaleFactor);
}
Now the visible view has scrollview. On scrolling it should become full screen by some smooth animation.
I got a layout in which there's a RelativeLayout with a visibility of GONE. This rl is a layout for a bar with buttons which appears at the bottom of the fragment when setting the visibility to visible. While the RL is still not visible, there are 2 buttons and when I set it to visible, the RL is covering the buttons.
What I want to do is simply move the buttons up above that bar which becomes visible. What I tried to do it:
rl.setVisibility(View.VISIBLE);
rl.post(new Runnable()
{
int dpToPx(final int dp)
{
return (int) (dp * getResources().getSystem().getDisplayMetrics().density + 0.5f);
}
#Override
public void run() {
int h = rl.getHeight(); //height is ready
h = dpToPx(h);
ImageButton button = (ImageButton)inflate.findViewById(R.id.button1);
float y = button.getY();
button.setY((float)h+y - 1100);
ImageButton button2 = (ImageButton)inflate.findViewById(R.id.button2);
y = button2.getY();
button2.setY((float)h+y);
}
});
The button with the -1100 (That number was just something I checked to see how it affects the position of the button and will not stay there obviously) is showing where I want it to be. The other button is so high or low which is no longer visible.
How do I set the position such that the button's Y position will be the old position + the height of the newly shown relative layout so the buttons will show just above it?
This is straightforward, all we need to do is to position the buttons at the y coordinate of our RelativeLayout.
We can get the y coordinate by calling:
rl.getY();
And since we want the button to be above the rl, we will subtract its height from the y coordinate of rl, something like this:
button.setY(rl.getY() - button.getHeight());
I'm using the following code to expand a view with an animation:
public class HorizontallyAnimate extends Animation {
private int toWidth;
private int startWidth;
private View view;
private String TAG = HorizontallyAnimate.class.getSimpleName();
private int newWidth;
public HorizontallyAnimate(View view) {
this.view = view;
this.startWidth = this.view.getWidth();
this.toWidth = (this.startWidth == view.getHeight() ? this.startWidth * 4 : view.getHeight());
Log.d(TAG,"Start width" + this.startWidth);
Log.d(TAG,"view hieght " + view.getHeight());
}
protected void applyTransformation(float interpolatedTime, Transformation t) {
newWidth = this.startWidth + (int) ((this.toWidth - this.startWidth) * interpolatedTime);
this.view.getLayoutParams().width = newWidth;
this.view.requestLayout();
}
}
The above code animates the view from left to right when the width changes.
But, I'm trying to animate it from the right to left. In other words, the width should grow in opposite direction. How can I be able to do so?
The problem you're dealing with here is an anchoring issue. A view's anchor (or pivot point) determines which point on the view stays still when other parts change.
A view's anchor when adjusting its dimensions highly depends on how the view is laid out. Since you didn't supply any information on how your view is laid out in the code you posted, I'll assume from the problem you're experiencing that the view's horizontal anchor is its left side.
This anchoring issue would produce a growth which would cause the left-most side to stay still, while the right side expands right-wards.
Making the view's left side to expand leftwards while the right side stays still can be achieved in several ways. One way would be to alter the way the view is laid out in its parent (i.e., if the parent is a RelativeLayout, set the view to alignParentRight=true, or playing with gravity in other containers).
However, since you didn't specify how the view is laid out, I will give you a solution which does not make any assumptions on its container. This solution isn't perfect as it may cause some stuttering, but it should still achieve what you're trying to do.
In your applyTransformation method, you will need to compensate for the right growth by translating leftwards. You can compensate for this by using translationX:
protected void applyTransformation(float interpolatedTime, Transformation t) {
// hold the change in a separate variable for reuse.
int delta = (int) ((this.toWidth - this.startWidth) * interpolatedTime);
newWidth = this.startWidth + delta;
this.view.getLayoutParams().width = newWidth;
// shift the view leftwards so that the right side appears not to move.
// shift amount should be equal to the amount the view expanded, but in the
// opposite direction.
this.view.setTranslationX(-delta);
this.view.requestLayout();
}
As you can see, this is a bit of "trick". While the view is expanding to the right, we are moving it to the left at the exact same ratio which causes the illusion of the view expanding to the left.
Test this code and see if it works for you. I would also recommend seeing if you can play around with the view's alignment or gravity from within its container. Doing this would solve your issue in a more standard manner, i.e., without any "tricks".
Hope this helps.
I have a View that has an OnClickListener. When clicked, the view translates up to a certain position on the page. This is no problem, the view goes where it should. When the view is clicked again, I would like to position it somewhere else, but this is not the case. After a little bit of trouble shooting, I found that my View's getTop() method returns the same value - even after the translation animation has moved the view to a different part of the screen. For the second animation, it is not using the current position (as I would expect), it instead uses the initial position.
Few things that I am doing: I am using the ObjectAnimation class rather than the TranslationAnimation class, since I wanted to keep the OnClickListener functioning. With the TranslationAnimation class, I found that the view was correctly moved, but the OnClickListener was only working in the area that the View started from. Using the ObjectAnimation class, I was able to easily get the translation to work AND the OnClickListener functions correctly - it is triggered where the view currently is on the screen.
Here's what I have so far:
final LinearLayout child = layouts.get(i); //ArrayList containing some dynamic layouts
final int offset = target - child.getTop();
ObjectAnimator anim = ObjectAnimator.ofFloat(child,"translationY",offset);
anim.setDuration(250);
anim.start();
This is what happens when the view is clicked the first time. It translates up along the Y axis, where the offset determines how far the View needs to move from its current position.
Now, here's what happens on the second click. The goal here was to align the view with the parent's base.
target = parent.getBottom();
offset = target - child.getTop();
anim = ObjectAnimator.ofFloat(child, "translationY",offset);
anim.setDuration(250);
anim.start();
prev = child;
This is where things fall apart - child.getTop() returns the Y coordinate of the view's ORIGINAL position. Not the current position. So after the animation, the view is placed well below the bottom of the parent. I read a different question which stated that I should use child.getY() instead, which is supposed to give me the translationY position plus the top position, but this didn't lead to any better results. I can't seem to get this to work just right. I'd simply like to move the view from its current position to the bottom of the screen, but this appears to be a hard thing to accomplish. Any help would be appreciated.
EDIT
I have added an animation listener:
ObjectAnimator anim = ObjectAnimator.ofFloat(child,"translationY",offset);
anim.setDuration(250);
anim.addListener(new ObjectAnimator.AnimatorListener(){
#Override
public void onAnimationStart(Animator animation) {
System.out.println("start: " + child.getTop() + " " + child.getY());
}
#Override
public void onAnimationEnd(Animator animation) {
System.out.println("end: " + child.getTop() + " " + child.getY() + " " + child.getTranslationY());
child.setTop((int)child.getY());
System.out.println(child.getTop());
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
});
anim.start();
Here I am setting the listener to try to change where the Top of the view is located. Behaviour is again not working as expected. The view is actually sent up above the screen when I do this. Output of the System.out looks like this:
start: 2008 2008.0
end: 2008 478.0 -1530.0
478
So calling child.getTop() after the animation is complete and setting a new position returns a positive integer, but the view is not actually completely on screen. It is above the screen, partly visible. The height of the view itself is about 700px. I am still so confused as to why this is such a hard thing to accomplish.
EDIT 2
I have also tried setting layoutparams inside the onAnimationEnd method:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)child.getLayoutParams();
params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
params.topMargin = (int)child.getY();
child.setLayoutParams(params);
Result: child.getTop() still returns the original position of 2008.
You can get the very bottom of the screen coordinates like this :
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels;
but you probably want it minus the height of your LinearLayout or else your LinearLayout will be cut off by the bottom :
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels
- child.getHeight();
// if you want a little more space to the bottom
// try something like - child.getHeight()*2;
Then use ViewPropertyAnimator to animate your LL like this :
child.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250);
The Interpolator is just to make the animation more realistic.
In the case that child.getHeight() returns 0 , your Linear Layout has not been finished setting up by the system, in that case you might want to do something like :
child.post(new Runnable() {
#Override
public void run() {
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels
- child.getHeight()*2;
child.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250);
}
});
Remember that a duration of 250 milliseconds is very fast, and does usually not look cool translating stuff on the screen, so you might want to set it a little higher, but thats just a matter of taste.
I have framelayout which contains two relative layouts, one is on top of the other. When user clicks a button, the one on the top move 80% off the screen to the right. Then one on the bottom becomes clickable. This is what it looks like.
FrameLayout
RelativeLayout (bottom) RelativeLayout (top)
FilterWidgets Open/close button, ListView
It's really easy to achieve on 3.0+ with the new animation api which is Property base Animation. For the pre 3.0, because animation is view based. So I end up manually modify the layout property on onAnimationEnd. The call requestLayout to make it permanent, but only to find out the layout reverts back to original position. Anybody know how to move layout permanently?
see my other post if you want to see the whole picture:
https://stackoverflow.com/questions/14541265/changecursor-cause-layout-container-of-the-listview-to-reposition
theTranslationX.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator nullPointer) {
v.clearAnimation();
int theL = isMenuOn() ? 0 : v.getLeft() + getFilterWidth();
int theR = isMenuOn() ? v.getWidth() : v.getLeft() + getFilterWidth() + v.getWidth();
int theHeight = v.getHeight();
int theT = 0;
v.layout(theL, theT, theR, theHeight);
v.requestLayout();
}
});
This is 9 months late but try using:
yourView.layout(left,top,right,bottom); //all parameters are type int
However I don't think this is permanent, the position of the view will still be reset when you call requestLayout(), but give it a try.