Gmail like Flip animation get's interrupted if second animation starts - java

I have implemented an Android listview with flip checkboxes (GMail style) as shown here: http://techiedreams.com/gmail-like-flip-animated-multi-selection-list-view-with-action-mode/
The problem I have (even in the source code example): If there are multiple items I click/check in a fast sequence, the previous animation stops and will be restared. In other words, the previous animation does not finish and is interrupted by the second one.
Simple download the source code and try it on your own. In comparisson to gmail all animations, no matter how fast I'm clicking, are performed from the start to the end.
I can't find the piece of code in the demo source code to change this behaviour.
Any hints?
Thanks in advance :)

This is the closest I could get to Gmail's flip animation:
In the getView() method (I'm using contextual action mode):
holder.check.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mActionMode == null) {
checked = new SparseBooleanArray(alllists.size());
mActionMode = ((Activity) getActivity()).startActionMode(mActionModeCallback);
animateRow(position);
checked.put(position, true);
mActionMode.setTitle("1");
mActionMode.getMenu().getItem(0).setVisible(true);
} else {
animateRow(position);
if (checked.get(position)) {
checked.put(position, false);
if (checked.indexOfValue(true) < 0) {
mActionMode.finish();
} else {
mActionMode.setTitle(String.valueOf(getCheckedCount()));
}
} else {
checked.put(position, true);
mActionMode.setTitle(String.valueOf(getCheckedCount()));
}
}
}
}
);
Then the animateRow() method:
private void animateRow(final int position) {
if (position >= listView.getFirstVisiblePosition() && position <= listView.getLastVisiblePosition()) {
Log.i("animateRow", String.valueOf(position));
ScaleAnimation anim = new ScaleAnimation(1, 0, 1, 1, Animation.RELATIVE_TO_SELF, 0.5f, 0, 0);
anim.setDuration(150);
anim.setRepeatCount(1);
anim.setRepeatMode(Animation.REVERSE);
viewa = listView.getChildAt(position - listView.getFirstVisiblePosition());
final Button chkButton = (Button) viewa.findViewById(R.id.logo);
if (checked.get(position)) {
anim.setAnimationListener(
new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.i("anim" + position, "Start");
}
#Override
public void onAnimationRepeat(Animation animation) {
Log.i("anim" + position, "Repeat" + animation.getRepeatCount());
viewa.setBackgroundResource(R.color.row_background);
chkButton.setBackgroundResource(R.color.button_background);
chkButton.setText(String.valueOf(alllists.get(position).itemsCount));
}
#Override
public void onAnimationEnd(Animation animation) {
Log.i("anim" + position, "END");
}
}
);
chkButton.startAnimation(anim);
} else {
anim.setAnimationListener(
new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.i("anim" + position, "Start");
}
#Override
public void onAnimationRepeat(Animation animation) {
viewa.setBackgroundResource(R.color.checked_row_background);
chkButton.setBackgroundResource(R.color.checked_button_background);
chkButton.setText("✓");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.i("anim" + position, "END");
}
}
);
chkButton.startAnimation(anim);
}
}
}
I hope it helps.. :)

Now you can forget that method to flip a view, since I've developed a new library FlipView fully customizable, this is exactly what you want. You will be able to swap any kind of views and layouts with any kind of animation you desire.
Please have a look.

Related

Detect when animation is done

So this is my spin the bottle animation:
public static final Random RANDOM = new Random();
private int lastAngle = -1;
private ImageView bottle;
private void spinTheBottle() {
int angle = RANDOM.nextInt(3600 - 360) + 360;
float pivotX = bottle.getWidth() / 2;
float pivotY = bottle.getHeight() / 2;
final Animation animRotate = new RotateAnimation(lastAngle == -1 ? 0 : lastAngle, angle, pivotX, pivotY);
lastAngle = angle;
animRotate.setDuration(1500);
animRotate.setFillAfter(true);
bottle.startAnimation(animRotate);
}
How can I detect when the animation is done? I tried adding Animator.AnimatorListener, but that does not execute at all:
Animator.AnimatorListener listener = new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationStart", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationEnd", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationCancel(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationCancel", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationRepeat(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationRepeat", Toast.LENGTH_SHORT).show();
}
};
Any tips?
It looks like you're creating the listener, but not assigning it to your animation. Try calling setAnimationListener on your animation object like this:
animRotate.setAnimationListener(new Animation.AnimationListener() {
//Listener methods
});
The first.Keep the ImageView witch and height above of zero at time
rotateAnimation.setDuration(1500);
rotateAnimation.setFillAfter(true);
rotateAnimation.setFillEnabled(true);
rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.d(TAG, "onAnimationStart: ");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd: ");
}
#Override
public void onAnimationRepeat(Animation animation) {
Log.d(TAG, "onAnimationRepeat: ");
}
});
view.startAnimation(rotateAnimation);
it is working in my project.
But I use the animation always in xmls,it is Easy to operate and relatively by code.
Animation and Animator is not a same things.
That's all.
Assign your listener that you have created to the animation
animRotate.setAnimationListener(listener);

Android java Listview scroll automatic a slow time

I have a listview with some elements, I have to make this list scroll automatically, with a slow scroll.
When he reaches the last element he stops.
If new items are added in the queue, then the listview must restart, until it reaches the last element again.
Any suggestions?
I suggest, thought your adapter implemented in effective way. so this code is just scrolls listview
you need to try another values of variables
final long totalScrollTime = Long.MAX_VALUE; //total scroll time. I think that 300 000 000 years is close enouth to infinity. if not enought you can restart timer in onFinish()
final int scrollPeriod = 20; // every 20 ms scoll will happened. smaller values for smoother
final int heightToScroll = 20; // will be scrolled to 20 px every time. smaller values for smoother scrolling
listView.post(new Runnable() {
#Override
public void run() {
new CountDownTimer(totalScrollTime, scrollPeriod ) {
public void onTick(long millisUntilFinished) {
listView.scrollBy(0, heightToScroll);
}
public void onFinish() {
//you can add code for restarting timer here
}
}.start();
}
});
use the below method to scroll your listview. for example:
scrollMyTableView(activityListview,11,0,getTotalHeightofListView(activityListview),0);
method:
private void scrollMyTableView(View v,final int var, int fromY, int toY, int delay){
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(v, "scrollY", fromY, toY).setDuration(2000);
objectAnimator.setStartDelay(delay);
objectAnimator.start();
objectAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
});
}
and if new item added to adapter and need to again go to top of listview and again come back to bottom.you can use below code to do this:
myAdapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
activityListview.setSelection(0);
scrollMyTableView(activityListview,11,0,getTotalHeightofListView(activityListview),0);
}
});
To calculate the height of listview use below method
public int getTotalHeightofListView(ListView listView) {
ListAdapter mAdapter = listView.getAdapter();
int totalHeight = 0;
for (int i = 0; i < mAdapter.getCount(); i++) {
View mView = mAdapter.getView(i, null, listView);
mView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
totalHeight += mView.getMeasuredHeight();
}
return totalHeight;
}
Use listview smoothScrollToPosition(int position) function.
Please have a look on this post also
https://www.codota.com/code/java/methods/android.widget.ListView/smoothScrollToPosition

using onLongClickListener to change values quickly

I'm trying to create a set of buttons that will change a value up or down by 1 with a single tap, and change the value quickly by holding the button. I can't figure out how to get the value to change quickly. Here's what I have:
btPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mTempo=mTempo+1;
setTempo(mTempo + 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btPlus.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public void onLongClick(View view) {
mTempo = mTempo + 1;
setTempo(mTempo + 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mTempo=mTempo-1;
setTempo(mTempo - 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btMinus.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public void onLongClick(View view) {
mTempo = mTempo - 1;
setTempo(mTempo - 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
return rootView;
}
Thanks for your help.
Holding the button is something else than long clicking it. You need an onTouchListener
In the onPressed method check if the MotionEvent is UP or DOWN and then start/stop counting.
EDIT: Try Counting up in a Thread, something like that:
Final Thread t = new Thread(new Runnable(){
#Override public void run(){
while(!t.isInterrupted(){
setTempo(mTempo++);
}
}
switch (event){
case ACTION_DOWN:
t.start();
break;
case ACTION_UP:
t.interrupt();
break
}

Android - Ghost Views after Animations

In my SMS app, I have a dialog that opens when the user clicks on an attached image to expand it.
Everything worked fine until I decided to add animations. This dialog has 3 buttons (one close ImageButton in the top right corner and two buttons in a bottom bar of the dialog). When the user clicks on the image, the buttons anime out/in. This all works fine except the buttons are still clickable even after they're hidden.
Before Animations:
After Animations:
My code for the dialog below:
// Declare these here to increase scope. (Listeners)
private static boolean ContainerChanged;
private static boolean ActionsHidden;
private static boolean AnimStarted;
private static boolean closeAnimFinished;
private static boolean barAnimFinished;
private void showExpandedImageDialog(Uri imgUri)
{
// Initialize Dialog
final Dialog dialog = new Dialog(ActivitySend.this, R.style.FullHeightDialog);
dialog.setContentView(R.layout.dialog_attachment_image_send);
// Initialize Views
final RelativeLayout Container = (RelativeLayout) dialog.findViewById(R.id.Container);
final LinearLayout actions = (LinearLayout) dialog.findViewById(R.id.Actions);
final ImageButton btnClose = (ImageButton) dialog.findViewById(R.id.btnClose);
Button btnReplace = (Button) dialog.findViewById(R.id.btnReplace);
Button btnRemove = (Button) dialog.findViewById(R.id.btnRemove);
ImageView image = (ImageView) dialog.findViewById(R.id.Image);
// Load Image & Make Zoomable
PhotoViewAttacher mAttacher = new PhotoViewAttacher(image);
image.setImageURI(imgUri);
mAttacher.update();
// Get animations ready
final Animation fiCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_in);
fiCloseAnim.setFillEnabled(true);
fiCloseAnim.setFillAfter(true);
final Animation foCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_out);
foCloseAnim.setFillEnabled(true);
foCloseAnim.setFillAfter(true);
final Animation dBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_down);
dBarAnim.setFillEnabled(true);
dBarAnim.setFillAfter(true);
final Animation uBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_up);
uBarAnim.setFillEnabled(true);
uBarAnim.setFillAfter(true);
// Reset static variables
ActionsHidden = false;
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
// Initialize listeners
AnimationListener closeAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
closeAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
AnimationListener barAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
barAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
// Set listeners
fiCloseAnim.setAnimationListener(closeAnimListener);
foCloseAnim.setAnimationListener(closeAnimListener);
dBarAnim.setAnimationListener(barAnimListener);
uBarAnim.setAnimationListener(barAnimListener);
// Actions Appear/Disappear onTap (Animate)
mAttacher.setOnPhotoTapListener(new OnPhotoTapListener()
{
#Override
public void onPhotoTap(View view, float x, float y)
{
if (!AnimStarted && ActionsHidden)
{
actions.startAnimation(uBarAnim);
btnClose.startAnimation(fiCloseAnim);
}
else if (!AnimStarted)
{
actions.startAnimation(dBarAnim);
btnClose.startAnimation(foCloseAnim);
}
}
});
// Make dialog square
ContainerChanged = false;
ViewTreeObserver vto = Container.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
// Set boolean to save processing power
if (!ContainerChanged)
{
int width = Container.getMeasuredWidth();
Container.getLayoutParams().height = width;
ContainerChanged = true;
}
return true;
}
});
// Set button listeners
btnClose.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.dismiss();
}
});
btnReplace.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
btnRemove.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
// Show dialog
dialog.show();
}
Everything works perfectly if I remove the animations and only use view.setVisibility(View.GONE) but I really like the animations...
Any ideas on what I could do to fix this?
I could probably use view.setClickable(false); but I'm sure there's a better solution than that.
You can do it like this:
Let your activity implement AnimationListener. Then there will be an overridden method public void onAnimationEnd(Animation arg0), write setClickable(false) or setEnabled(false) in this method for all three of your buttons, enable them again when you are starting your animation....hope you got me..

Animation don't work with a changing of the ImageView Drawable

Hi have a problem with Animation, actually i want to fade my ImageView while it's changing it resource.
It's not working, i can change the resource but without any animation.
private void checkX() {
// TODO Auto-generated method stub
switch (x) {
case (1): {
startingAnimation();
xImg.setImageResource(R.drawable.test_uno);
endingAnimation();
break;
}
case (2): {
startingAnimation();
xImg.setImageResource(R.drawable.test_due);
endingAnimation();
break;
}
case (3): {
startingAnimation();
xImg.setImageResource(R.drawable.test_tre);
endingAnimation();
break;
}
case (4): {
startingAnimation();
xImg.setImageResource(R.drawable.test_quattro);
endingAnimation();
break;
}
case (5): {
x = 1;
checkX();
break;
}
case (0): {
x = 4;
checkX();
break;
}
}
}
private void endingAnimation() {
// TODO Auto-generated method stub
ObjectAnimator animation2 = ObjectAnimator.ofFloat(xImg, "alpha", 255);
animation2.setDuration(1000);
animation2.start();
}
private void startingAnimation() {
// TODO Auto-generated method stub
ObjectAnimator animation = ObjectAnimator.ofFloat(xImg, "alpha", 0);
animation.setDuration(1000);
animation.start();
}
checkX is called each time i press a button(that add or subtract 1 to X).
How i can make both animations and ImageView resource change?
Try changing the image source when the animation's onAnimationEnd is called. For example:
animation.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationRepeat(Animator animation) { }
#Override
public void onAnimationEnd(Animator animation) {
// change your ImageView's source here
}
#Override
public void onAnimationCancel(Animator animation) { }
});
Apply fade out animation on your ImageView and set animationListener to it. on animation end change your views resource and set fade in animation on it
For fade in animation
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
final AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
For fade out animation
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(300);
final AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeOut);
Thats how you implement listner on animation
fadeout.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
//change resource of Imageview here
}
});

Categories

Resources