I already have a PopupWindow and a defined XML scale animation in res/anim/ that is applied on show and on dismiss of that popup window. But the case is I want to change pivotX and pivotY of the style of animation dynamically so it starts (grows) from different points of the screen.
So either I'm able change pivotX and pivotY dynamically in res/anim/in.xml or create new ScaleAnimation and apply it. I cannot see how to do the first option, and unfortunately the latter doesn't work when I write:
public class MyPopup {
private PopupWindow popupWindow;
private Integer growFromX;
private Integer growFromY;
public MyPopup(Integer growFromX, Integer growFromY) {
if (growFromX != null && growFromY != null) {
this.growFromX = growFromX.intValue();
this.growFromY = growFromY.intValue();
}
}
public void show() {
LayoutInflater layoutInflater = (LayoutInflater) this.activity
.getBaseContext().getSystemService(
Activity.LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(
R.layout.map_selector_dialog_layout, null);
ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 0.0f,
1.0f, 1.0f, Animation.RELATIVE_TO_SELF,
(float) this.growFromX, Animation.RELATIVE_TO_SELF,
(float) this.growFromY);
scaleAnimation.setFillAfter(false);
scaleAnimation.setDuration(4000);
popupView.setAnimation(scaleAnimation);
this.popupWindow = new PopupWindow(popupView,
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
this.popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);
}
}
It doesn't have to be WindowPopup. I can use Dialog or whatever so I can I achieve such a behaviour. Could you help?
few things to tweak to make your code work:
set width and height for the 'popupView' inside the 'popupWindow'
set an interpolator for the ScaleAnimation
either use
popupView.startAnimation(scaleAnimation);
instead of
popupView.setAnimation(scaleAnimation);
or set the start time of you animation before calling 'setAnimation' and make sure the view's parent gets invalidated when the animation starts
replace
this.popupWindow = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
with
this.popupWindow = new PopupWindow(popupView, width, height);
where width and height have to be bigger than the dimensions of the 'popupView' during and after the scaling process. with LayoutParams.WRAP_CONTENT the ScaleAnimation won't work.
hope it helps
Related
I'm trying to move an ImageView down using ObjectAnimator. The setDuration() method doesn't seem to impact the duration of the animation. I can't set this animation in the XML as I want to play this dynamically.
ObjectAnimator an= ObjectAnimator.ofFloat(img, View.TRANSLATION_Y, 0, 100);
an.setDuration(5000);
an.start();
Sorta off topic here but say I want to play more than one of those ObjectAnimation after each other, Is there a way to do that? I've looked at the Animator set but I wasn't sure if it would move the actual object like an Object Animator, instead of just appearing as so as in the TranslateAnimation.
Thanks in advance!
Maybe you are testing on Samsung device? In this case, under developer options there is the option Animator duration scale that is set to off by default. If you switch to the normal value you can see the animations.
Hope this help.
LayoutInflater inflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View popupView = inflater.inflate(R.layout.loading_popup, null,false);
popup = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
popup.setContentView(popupView);
popup.setOutsideTouchable(true);
ImageView loadingPlane=(ImageView)popupView.findViewById(R.id.loading_plane);
RotateAnimation anim = new RotateAnimation(0.0f, 360.0f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
// Step 2: Set the Animation properties
anim.setInterpolator(new LinearInterpolator());
//anim.setRepeatCount(Animation.INFINITE);
anim.setRepeatCount(-1);
anim.setDuration(1500);
loadingPlane.startAnimation(anim);
findViewById(R.id.flyinstyle).post(new Runnable() {
public void run() {
popup.showAtLocation(findViewById(R.id.flyinstyle), Gravity.CENTER, 0, 0);
}
});
In imageAdapter class, I set the image alpha to 0.5 handler.imageView.setAlpha(0.5f); inside a try/catch.
It's made like this, and not inside the layout xml, because previous versions of android haves int instead of float, so, in the catch, setAlpha is 128.
In the activity, I have an AlphaAnimation(float from, float to) so I can make smoother transitions when sliding between items. I've put from = 0.5f to match the initial value, and to = 1.0f to full opaque image. I really achieved a part from this. The item that is not selected shows an alpha with 0.5, but when it's selected, it's not 100% opaque, just a bit more.
Activity code:
private View antView = null; //Last view seen
...
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
if(antView != null)
setItemViewMode(antView, false);
antView = v;
setItemViewMode(v, true);
}
});
//This method is to detect the item selected, and change styles to selected and the view from before
public void setItemViewMode(View item, boolean selected) {
Animation animationImage;
ImageView img = (ImageView) item.findViewById(R.id.imageView1);
if(selected) {
animationImage = new AlphaAnimation(0.5f, 1.0f);
}
else {
animationImage = new AlphaAnimation(1.0f, 0.5f);
}
animationImage.setDuration(250);
animationImage.setFillAfter(true);
img.startAnimation(animationImage);
}
As said above, the animation occurs, but, the alpha from the selected image is not 100% opaque.
May something wrong setting the opacity inside the animation?
Find it out, someway, I thought that before adding the animation, I should put the opacity to 1.0f and then make the animation from 0.5f to 1.0f, and this worked.
So it would be:
if(selected)
animationImage = new AlphaAnimation(0.5f, 1.0f);
else
animationImage = new AlphaAnimation(1.0f, 0.5f);
img.setAlpha(1.0f);
img.startAnimation(animationImage);
try this...
public void setItemViewMode(View item, boolean selected) {
Animation animationImage;
ImageView img = (ImageView) item.findViewById(R.id.imageView1);
if(selected) {
animationImage = new AlphaAnimation(0f, 1.0f);
}
else {
animationImage = new AlphaAnimation(1.0f, 0f);
}
animationImage.setDuration(250);
animationImage.setFillAfter(true);
img.startAnimation(animationImage);
}
I initialize a ViewGroup with the code below. When a button is pressed I run this.startAnimation(moveMenu). startAnimation will run the view's invalidate so it will draw something on the view. However, if I run setTranslationY in the function below then the view does not have the drawing show up properly. If I remove it then it works and slides down and then back up.
This is not the behavior I want though, I want the viewGroup to be hidden above the screen and slide down when the button is pressed, then slide back up to hide again. So this is why I need the this.setTranslationY.
void init(Context context) {
this.setBackgroundColor(Color.WHITE);
this.setTranslationY(this.height * -1); // if I remove this the drawing works
Resources r = this.getContext().getResources();
loadBitmapArray(0, r.getDrawable(R.drawable.the_drawable)) ;
show = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, height);
show.setDuration(1000);
show.setFillAfter(true);
hide = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -height);
hide.setStartOffset(show.getDuration() + 2000);
hide.setDuration(1000);
hide.setFillAfter(true);
moveMenu = new AnimationSet(true);
moveMenu.addAnimation(show);
moveMenu.addAnimation(hide);
}
In a RelativeLayout, I added an ImageView with some margin set in LayoutParams:
RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlLayoutParams.topMargin = (int) convertDpToPixel(kMARGIN_HEADER);
rlLayoutParams.leftMargin = (int) myMAGIC_MARGIN;
Now this ImageView is somewhere in the middle of the screen. I want to have it slide a few hundred pixels to its right, and stay there, so I applied the following TranslateAnimation:
private TranslateAnimation getAnimation(ImageView view, int displacement, int duration) {
int[] view_pos = new int[2];
view.getLocationOnScreen(view_pos);
TranslateAnimation slide = new TranslateAnimation(
view_pos[0],
view_pos[0] + displacement,
view_pos[1],
view_pos[1]);
slide.setFillAfter(true);
slide.setDuration(duration);
return slide;
}
Immediately after applying this animation, the whole view is gone. I checked the value of view_pos[] in debug mode, they are fine (not all zeroes). If I make the setFillAfter to false, then the view will come back after animation duration (for obvious reasons). So where did it go?
I also tried the following:
TranslateAnimation slide = new TranslateAnimation(
view_pos[0],
view_pos[0], // don't do the + displacement,
view_pos[1],
view_pos[1]);
I was expecting the view to stay where it is. But no, it was vanished as well, with a chance of coming back afterwards, depending on the value of setFillAfter.
I start to think I cannot apply TranslateAnimation if the view was placed by LayoutParams in a RelativeLayout. How should I achieve the goal of sliding the view?
The parameters for TranslateAnimation are deltas not positions, so you just want:
slide = new TranslateAnimation(0, displacement, 0, 0).
If you don't need to support Android <3.0 then use a Property Animation instead of a View Animation - see the Android docs for more details.
I have an Activity with a main screen that simply has a title bar (among other things). I have another TextView below the title bar that I have animate from top to bottom into place (it starts out as View.GONE, then I animate it visible and into place after an event from the user).
This works fine and dandy, except the TextView below the title bar animates above the title bar into place. I want it to seem as if the TextView came from underneath the title bar. Both views are in a LinearLayout, so I'm not able to address the z-order like I would in a FrameLayout. Any suggestions?
I eventually solved this by encompassing the textview inside of a LinearLayout, then setting a LayoutAnimationController to the LinearLayout. This causes all the childs to be animated with respect to the parent container, which made the drop-down only to be rendered within the LinearLayout (which worked perfectly). Here is the code I used for the Animation Controller and ListView:
private void addDeleteDropAnimation() {
AnimationSet set = new AnimationSet(true);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(150);
set.addAnimation(animation);
animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f,Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f,Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(300);
set.addAnimation(animation);
controllerDel = new LayoutAnimationController(set, 0.5f);
vw_delLinearLayout.setLayoutAnimation(controllerDel);
}
Handler handler = new Handler();
new Thread(){
public void run(){
TextView tv = (TextView)findViewById(R.id.xx);
LayoutParams params = (LayoutParams)tv.getLayoutParams();
handler.post(new Runnable(){
public void run(){
tv.setVisible(View.Visible);
}
}
int height = params.height;
for(int i = 0; i < height + 1; i++) {
params.topMargin = i - height;
handler.post(new Runnable(){
public void run(){
tv.requestLayout();
}
}
try{
Thread.sleep(5);
}catch(InterruptedException e){
}
}
}
}.start();
you can try this.