IMS
IMS

Reputation: 265

Android - Animation with only 2 images and mask

I'm trying to make an animation with only 2 images and using a mask. But I do not know how. I can not use animation-list. I need help to do so. Thank you.

The effect of the animation would look like this:

enter image description here

public void makeMaskImage(ImageView mImageView, int mContent) {

    Bitmap original = BitmapFactory.decodeResource(getResources(), mContent);
    Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask);
    Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas mCanvas = new Canvas(result);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    mCanvas.drawBitmap(original, 0, 0, null);
    mCanvas.drawBitmap(mask, 0, 0, paint);
    paint.setXfermode(null);
    mImageView.setImageBitmap(result);
    mImageView.setScaleType(ImageView.ScaleType.CENTER);
    mImageView.setBackgroundResource(R.drawable.img_b);
}

animation

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:fillEnabled="true"
android:interpolator="@android:anim/linear_interpolator">

<translate
    android:duration="3000"
    android:fromXDelta="-100%p"
    android:toXDelta="0%p" />

</set>

Upvotes: 2

Views: 3522

Answers (2)

IMS
IMS

Reputation: 265

I modified the class of Nicolas Simon and code works perfectly

public class RevealView extends ImageView {

    private Bitmap secondBitmap;
    private float mAnimationPercentage;
    private Path mPath;
    private Paint mPaint;

    public RevealView(Context context) {
        super(context);
        init();
    }

    public RevealView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RevealView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setPercentage(0);

        mPaint = new Paint();
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
        mPath = new Path();
    }

    public void setPercentage(int p) {
        if(p > 100) {
            p = 100;
        }
        mAnimationPercentage = p / 100f;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Bitmap mRegularBitmap = ((BitmapDrawable) getDrawable()).getBitmap();
        if (mRegularBitmap != null && secondBitmap != null) {
            //First draw your regular image
            canvas.drawBitmap(mRegularBitmap, 0, 0, null);

            //Then clip the canvas depending on the animation percentage, using a Path
            mPath.reset();
            mPath.moveTo((float) canvas.getWidth() * mAnimationPercentage, 0.0f);
            mPath.lineTo((float) canvas.getWidth() * mAnimationPercentage, canvas.getHeight());
            mPath.lineTo(canvas.getWidth(), canvas.getHeight());
            mPath.lineTo(canvas.getWidth(), 0.0f);
            mPath.close();

            canvas.drawPath(mPath, mPaint);
            canvas.clipPath(mPath);

            //Then draw the gray bitmap on top
            canvas.drawBitmap(secondBitmap, 0.0f, 0.0f, null);
        }
    }

    public void setSecondBitmap(Bitmap secondBitmap) {
        this.secondBitmap = secondBitmap;
    }
}

MainActivity

@Override
public void onResume() {
    super.onResume();

    revealView.setSecondBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img_1));

    percentage = 0;
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (percentage <= 100) {
                        revealView.setPercentage(percentage);
                        percentage++;
                    } else {
                        cancel();
                    }
                }
            });
        }
    }, 0, 120);
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.example.animation.RevealView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:src="@drawable/img_2" />

</RelativeLayout>

Upvotes: 1

NSimon
NSimon

Reputation: 5287

I would create a custom View for that, to work with the onDraw method, and especially the clip function. This class is working for me, but is left very opened to modifications on your side. An implementation would be as follow :

public class RevealView extends View {
private Bitmap                  mRegularBitmap;
private Bitmap                  mGrayScaleBitmap;
private float                   mAnimationPercentage;
private Path                    mPath;
private Paint                   mPaint;

public RevealView(Context context) {
    super(context);
    init();
}

public RevealView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public RevealView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mRegularBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sign_in_up_icon);
    mGrayScaleBitmap = toGrayScale(mRegularBitmap);
    mAnimationPercentage = 0.0f;

    mPaint = new Paint();
    mPath = new Path();
}

public void reset() {
    mAnimationPercentage = 0.0f;
}

public void setPercentage(float p) {
    mAnimationPercentage = p;
}

private Bitmap toGrayScale(Bitmap origin) {
    int width, height;
    height = origin.getHeight();
    width = origin.getWidth();

    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bmpGrayscale);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(0);
    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
    paint.setColorFilter(f);
    c.drawBitmap(origin, 0, 0, paint);
    return (bmpGrayscale);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //First draw your regular image
    canvas.drawBitmap(mRegularBitmap, 0, 0, null);

    //Then clip the canvas depending on the animation percentage, using a Path
    mPath.reset();
    mPath.moveTo((float)canvas.getWidth() * mAnimationPercentage, 0.0f);
    mPath.lineTo((float)canvas.getWidth() * mAnimationPercentage, canvas.getHeight());
    mPath.lineTo(canvas.getWidth(), canvas.getHeight());
    mPath.lineTo(canvas.getWidth(), 0.0f);
    mPath.close();

    canvas.drawPath(mPath, mPaint);
    canvas.clipPath(mPath);

    //Then draw the gray bitmap on top
    canvas.drawBitmap(mGrayScaleBitmap, 0.0f, 0.0f, null);
}

Then define your own animation, and simply call myRevealView.setPercentage(float);

Depending on the Thread you're calling it, then either use myRevealView.invalidate()//main thread or myRevealView.postInvalidate()//background thread

Upvotes: 1

Related Questions