How to give percentage values in ObjectAnimator in Android

I am using objectAnimator for animating a button from bottom to top in Android. Now i am using the below code

ObjectAnimator transAnimation = ObjectAnimator.ofFloat(button,"translationY",0,440);
        transAnimation.setDuration(440);
        transAnimation.start();

I have also tried with sample code below. But still the problem exists

ObjectAnimator transAnimation = ObjectAnimator.ofFloat(loginLayout, "translationY",0f,0.8f);
                    transAnimation.setDuration(480);
                    transAnimation.start();

It works fine in large screen devices. But when it comes to small screen devices it goes off the screen. I want to stay it in the top of the screen irrespective of different screen sizes. I think i have to give values in percentage (say 0% to 100% or 0 to 100%p). So my question is how to give values in percentage in objectAnimator in Android. I also noticed one thing that this objectAnimator is introduced only in HoneyComb. So is there any backward compatibility libraries for running it in low versions. Could anyone guide me to find a solution for this.

I also tried extending View and writing getter and setter for the property in offset(). Still it does not move fully to top of screen. Here is the code I have used.

@SuppressLint("NewApi") public float getXFraction()
    {
        int width = context.getWindowManager().getDefaultDisplay().getHeight();
        return (width == 0) ? 0 : (getY());
    }

    @SuppressLint("NewApi") public void setXFraction(float xFraction) {
        int width = context.getWindowManager().getDefaultDisplay().getWidth();
        setY((width > 0) ? (width) : 0);
    }

Thanks inAdvance


Solution 1:

To use ObjectAnimator on pre-Honeycomb devices add NineOldAndroids library to your project and change your imports to use com.nineoldandroids.animation.ObjectAnimator.

To use percentage values in ObjectAnimator instead of getXFraction and setXFraction you have to add getYFraction and setYFraction methods like this

public float getYFraction() {
    final WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    int height = wm.getDefaultDisplay().getHeight();
    return (height == 0) ? 0 : getY() / (float) height;
}

public void setYFraction(float yFraction) {
    final WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    int height = wm.getDefaultDisplay().getHeight();
    setY((height > 0) ? (yFraction * height) : 0);
}

And then you can create xml file project-folder/res/animator/move_bottom.xml like this

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:propertyName="yFraction"
    android:valueFrom="0"
    android:valueTo="0.8"
    android:valueType="floatType" />

Or create animation in code

final LoginLayout loginLayout = (LoginLayout) findViewById(R.id.login_layout);
final ObjectAnimator oa = ObjectAnimator.ofFloat(loginLayout, "yFraction", 0f, 0.8f);
oa.start();

Solution 2:

If you want to create animation from outside of screen with ObjectAnimator. You can do this with Android display size.

    @Override
    public void onCreate(Bundle savedInstanceState) {

        ...

        sampleImage = BitmapFactory.decodeResource(getResources(), R.drawable.sample);

        myImage = (ImageView) findViewById(R.id.image_view);
        myImage.setImageBitmap(sampleImage);

        //In case API Level is 14 above.
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        float displayWidth = size.x;

        //In case API Level is 13 below.       
        //WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        //Display display = wm.getDefaultDisplay();
        //displayWidth = display.getWidth();

        animator = ObjectAnimator.ofFloat(myImage, "translationX", displayWidth,  0);
        animator.setDuration(500);

    }

Sorry, if my suggestion missed the point.

Solution 3:

Try using a custom property for ObjectAnimator, instead of creating custom view with custom property, you can create a custom property that accepts a 'fraction':

Property<View, Float> property = new Property<View, Float>(Float.TYPE, "translation_x_fraction") {
        @Override public Float get(View view) { 
            return view.getWidth() <= 0 ? 0 : view.getTranslationX() / view.getWidth();
        }

        @Override public void set(View view, Float value) {
            view.setTranslationX(view.getWidth() * value);
        }
}

ObjectAnimator.ofFloat(view, property, 0f, 1f);