[JAVA] Implementation comparison of production that makes images shine on iOS and Android

Since the animation production made in the iOS version has been ported to the Android version, I will leave that time as a memorandum.

Finished product for iOS

stamp_short_ios.gif

Animation execution flow

The finished product gif is processed as follows.

  1. Place a normal image
  2. Process a normal image to generate a shiny image
  3. Add the glowing image generated in ↑ to the same position as the normal image with an alpha value of 0 (overlaid on top).
  4. Display a normal image with a fade-in + scale-out animation
  5. When the animation of ↑ is over, display the glowing image with fade-in.
  6. When the animation of ↑ is over, erase the glowing image with the fade-out + scale-out animation.

Below are the key iOS and Android codes. I'm omitting the parts that don't need to be written.

Generate a glowing image

iOS(Swift)

//Blend white with original image in hardLight mode
let image = UIImage.imageFromAsset(name: "stamp_complete")?
                .colorizeImage(color: UIColor.white, blendMode: CGBlendMode.hardLight)

//Method to blend
public func colorizeImage(color: UIColor, blendMode: CGBlendMode = CGBlendMode.plusLighter) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(self.size, false, 0)
    let context = UIGraphicsGetCurrentContext()
    let rect    = CGRect(origin: CGPoint.zero, size: self.size)
    context?.scaleBy(x: 1, y: -1)
    context?.translateBy(x: 0, y: -rect.size.height)
    context?.saveGState()
    context?.clip(to: rect, mask: self.cgImage!)
    color.set()
    context?.fill(rect)
    context?.restoreGState()
    context?.setBlendMode(blendMode)
    context?.draw(self.cgImage!, in: rect)
    let colorizedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return colorizedImage   
}

Android(Java)

ImageView glowView = new ImageView(getContext());
glowView.setLayoutParams(new RelativeLayout.LayoutParams(
        LayoutParams.WRAP_CONTENT,
        LayoutParams.WRAP_CONTENT
));
//Set the original image
glowView.setImageResource(R.drawable.stamp_star);
glowView.setAdjustViewBounds(true);
//Filter to brighten the image
ColorFilter filter = new LightingColorFilter(Color.rgb(255, 255, 255), Color.rgb(100, 100, 100));
glowView.setColorFilter(filter);

In iOS, UIImage itself is processed, but in Android, the filter method of ImageView is used.

Display normal images with fade-in + scale-out

iOS(Swift)

//Appearance animation(Scale out)
//Shrink in advance
stampView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
UIView.animate(withDuration: 0.3,
               delay: delay,
               usingSpringWithDamping: 0.5,
               initialSpringVelocity: 1.0,
               options: [.beginFromCurrentState],
               animations: {
                //Return to original size
                stampView.transform = CGAffineTransform.identity
},
               completion: { (finished) in
})

//Appearance animation(Fade-in)
let alphaAnim = CABasicAnimation(keyPath: "opacity")
alphaAnim.duration  = 0.15
alphaAnim.toValue   = 1.0
alphaAnim.fillMode  = kCAFillModeForwards
alphaAnim.isRemovedOnCompletion = false
CATransaction.begin()
CATransaction.setCompletionBlock {
}
stampView.layer.add(alphaAnim, forKey: "stamp")
CATransaction.commit()

Android(Java)

//Appearance animation (scale out + fade in)
ViewAnimator.animate(view)
        .fadeIn()
        .duration(150)
        .andAnimate(view)
        .scale(0, 1)
        .duration(200)
        .interpolator(new BounceInterpolator())
        .onStop(() -> {
        })
        .start();

Easing is each method, so it is not completely complete. The Android version can be written neatly thanks to a nice library called ViewAnimator.

Fade-in display of glowing images

iOS(Swift)

UIView.animate(withDuration: 0.15, delay: delay, options: [.beginFromCurrentState, .curveLinear], animations: {
    imageView.alpha = 1
}, completion: { (finished) in
    UIView.animate(withDuration: 0.3, delay: delay, options: [.beginFromCurrentState, .curveEaseOut], animations: {
        imageView.transform = CGAffineTransform(scaleX: 1.8, y: 1.8)
        imageView.alpha     = 0
    }, completion: { (finished) in
    })
})

Android(Java)

ViewAnimator.animate(view)
        .onStart(() -> {
            view.setVisibility(VISIBLE);
        })
        .fadeIn()
        .duration(150)
        .thenAnimate(view)
        .scale(1.0f, 1.8f)
        .fadeOut()
        .interpolator(new DecelerateInterpolator())
        .duration(300)
        .onStop(() -> {
        })
        .start();

Differences between iOS version and Android version

Easing

The easing of the magnified animation when the stars are displayed is different because each method is used. I think that it will be aligned if you make fine adjustments. (Bounce Interporator on Android, animateWithSpringDumping on iOS.)

Image of star after processing

I feel that white is stronger on iOS, so I think that if you make fine adjustments, you can get closer.

Impressions

If you can prepare a shining image, no processing is required, but if you can change it dynamically, it is convenient when you want to try various things or make fine adjustments. I have extracted the code and put it partially, so if there is something wrong, please let me know.

Recommended Posts

Implementation comparison of production that makes images shine on iOS and Android
Thorough comparison of Android and iOS implementations
Implementation of vertical and horizontal scrolling that is often seen on Android recently
[Android] Display images and characters on the ViewPager tab
Comparison of processing times based on awk, shell command, and Java
Get the acceleration and bearing of the world coordinate system on Android