Long Long Ago, wechat 8.0 updated a “fried shit” new function, quite innovative.
I was talking to a friend for two days and I thought, hey! Isn’t that what this article is all about? ! Make it happen over the weekend.
Let’s take a look at the overall implementation:
This article is non-technical and purely entertaining
Train of thought
After continuous test, repeatedly view the effect of wechat fried π©, basically can be broken down into several small parts.
- Select the bomb emoticon, after sending the bomb will be sent to the other party in the form of parabola, at the same time π£ will be flipped;
- [Fixed] An explosion animation appears when π£ meets π© emoji.
- At the same time as the animation explodes, about seven π© emoticons appear, pointing in random directions, amplifying, and finally moving down and fading away.
The effect has been disassembled, and the specific technical implementation ideas are as follows:
- IM chat interface, mainly Recyclerview is divided into two types of sender and receiver;
- Bezier curve to achieve the effect of bomb parabola, here with the second-order Bezier curve can be;
- [Fixed] Use animation to rotate bombs as they are thrown.
- Lottie achieves the explosion effect;
- Zoom, pan, gradient animation to achieve 7 π© blast effects.
The specific implementation
IM Chat interface
Im chat interface is very simple, a Recyclerview, divided into two types of left and right, according to the type value, respectively load the layout on the left and right.
class ImAdapter : BaseDelegateMultiAdapter<ImMsg? .BaseViewHolder> (){
companion object {
private const val TAG = "ImMsgAdapter"
private const val TYPE_LEFT = 0
private const val TYPE_RIGHT = 1} init { setMultiTypeDelegate(object : BaseMultiTypeDelegate<ImMsg? >() { override fun getItemType(data: List<ImMsg? >, position: Int): Int {if(data[position]? .type ==0) {
return TYPE_LEFT
}
return TYPE_RIGHT
}
})
Objects.requireNonNull(getMultiTypeDelegate())!!
.addItemType(TYPE_LEFT, R.layout.item_im_left)
.addItemType(TYPE_RIGHT, R.layout.item_im_right)
}
override fun convert(holder: BaseViewHolder, item: ImMsg?) {
if(holder.itemViewType == TYPE_LEFT) { holder.setText(R.id.tv_chat_left_msg,item? .msg) }else{ holder.setText(R.id.tv_chat_right_msg,item? .msg) } } }Copy the code
Here we create an entity class, ImMsg, to simulate chat data.
data class ImMsg(val type:Int.val msg:String) // Initializes chat messages to simulate dataval msgList = mutableListOf<ImMsg>()
msgList.add(ImMsg(0."HelloοΌ"))
msgList.add(ImMsg(0."Let's test that out."))
msgList.add(ImMsg(0."Wechat Explosion effect"))
msgList.add(ImMsg(1."Oh!))
msgList.add(ImMsg(0."\uD83D\uDE14"))
msgList.add(ImMsg(0."\uD83D\uDCA9"))
msgList.add(ImMsg(0."\uD83D\uDCA9"))
msgList.add(ImMsg(0."\uD83D\uDCA9"))
val adapter = ImAdapter()
imRv.adapter = adapter
adapter.addData(msgList)
Copy the code
Of course, the chat interface also needs to add input box, as well as the expression bar, which is not shown here.
Send bombs π£
The chat interface is set up, and then we start to get down to business, starting with dropping bombs.
As has been analyzed above, the process of dropping bombs is actually a parabolic process, starting from the right side of the chat sent out to the left side of π©.
When seeing the process of throwing bombs, the first reaction is to use Bezier curves to solve the problem of bomb route. The traveling route of bombs is relatively simple, and the second-order Bezier curve can be realized here.
We all know that in order to achieve a second-order Bezier curve, we need to know at least two points, one is the control point, and one is the coordinate of the end point.
From the figure above, we can basically know that the control point is the upper position between the start point and the end point. Here, the screen width and height are calculated to simulate the control point.
val resources: Resources = this.resources
val dm: DisplayMetrics = resources.displayMetrics
val scWidth = dm.widthPixels
val scHeight = dm.heightPixels
val controlX : Int = scWidth/2 - 400// control point x
val controlY : Int = scHeight/2 - 400// control point y
Copy the code
The end point is the same, with the starting point as the reference value, calculate the coordinates
val lastX = ivBomb.x-200
val lastY = ivBomb.y-800
Copy the code
You have the coordinates of the control point and the end point, so you start to draw the second order Bezier curve, implement bezier curve, Android already has a ready API, there is a quadTo method in Path, you just pass in the coordinates of the control point and the end point, which is to generate the Bezier curve Path.
path.quadTo(
-controlX,
-controlY,
-lastX,
-lastY
)
Copy the code
With path, the next step is to move the bomb according to the Bezier curve. Here, we need to use attribute animation combined with PathMeasure to move the bomb π£ according to the path.
pathMeasure = PathMeasure(path, false)
valueAnimator = ValueAnimator.ofFloat(0f, pathMeasure.length)
valueAnimator.duration = MILLS + 100
valueAnimator.interpolator = LinearInterpolator()
valueAnimator.addUpdateListener { animation ->
val animatedValue = animation.animatedValue as Float
pathMeasure.getPosTan(animatedValue, mCurrentPosition, null)
ivBomb.translationX = mCurrentPosition[0]
ivBomb.translationY = mCurrentPosition[1]
ivBomb.rotation = animatedValue
}
Copy the code
The bomb of wechat is a parabola at the same time, it has the effect of constantly flipping.
Then we just need to listen for the update listener of the property animation. In the process of listening for movement, set the rotation so that the bomb keeps flipping.
Let’s look at the effect:
Explosion effect
The next thing to talk about is the explosive effect of the bomb, the solution given here is to use Lottie library to load. Wechat explosion effect or very realistic, looking for a long time, did not find the corresponding material, here is true to simulate.
I found a JSON file that looked like an explosion from lottiefiles.com/ and combined it with Lottie to achieve the explosion effect.
Lottie is also simple to use, adding dependencies
implementation 'com. Reality. The android: Lottie: 3.4.0'
Copy the code
Add LottieAnimationView to layout
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_layer_view"
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintBottom_toTopOf="@id/cl_ed_send"
android:layout_marginBottom="140dp"/>
Copy the code
At the end of the bomb execution parabola, play begins
MLottieAnimation? .playAnimation()Copy the code
Let’s take a look at the combined effect of the bomb
π© blast effect
When the bomb explodes, there is an effect of π© being blown apart, as shown below.
From the perspective of wechat effect, there are 7 π© expressions, and each expression is randomly tilted, starting from the explosion animation, and popping up from small to large, forming the effect from far to near.
The solution is to draw 7 identical emoticon diagrams from a customized View, rotate the Angle randomly by Math.random, and place the 7 emoticon graphs randomly within a controllable range.
// At the beginning of the explosion, 7 graphs were randomly divided, and the rotation Angle was random
for (i in 0.6.) { dst? .let { it.left = i *50 + 150
it.top = mHeight + (Math.random() * 400).toInt() - mHeight / 4
it.right = it.left + 100
it.bottom = it.top + 100
}
val matrix = Matrix()
matrix.postScale(i.toFloat() + 4, i.toFloat() + 4)
matrix.postTranslate((-bitmap.width / 2).toFloat(), (-bitmap.height / 2).toFloat())
matrix.postRotate((Math.random() * 70).toFloat()) matrix.postTranslate(dst!! .top.toFloat(), dst!! .left.toFloat()) val bitmap1 = Bitmap.createBitmap(bitmap,0.0, bitmap.width, bitmap.height, matrix, true)
canvas.drawBitmap(bitmap1, null, dst!! , paint) matrix.reset() }Copy the code
For far and near effects, you need to animate your custom baba View by zooming in and out.
val scaleXAni = ObjectAnimator.ofFloat(baView, "scaleX", 0f, 1.8f)
val scaleYAni = ObjectAnimator.ofFloat(baView, "scaleY", 0f, 1.5f)
Copy the code
In addition, at the end of the π© explosion, π© will move down and gradient transparent at the same time, so after scaling the animation start the translation animation and gradient animation alpha.
val tranY1Ani = ObjectAnimator.ofFloat(baView, "translationY", 0f, -300f)
val tranYAni = ObjectAnimator.ofFloat(baView, "translationY", -300f, 300f)
val alphaAni = ObjectAnimator.ofFloat(baView, "alpha", 1f, 0f)
Copy the code
Finally, use AnimatorSet to assemble the animation and start playing.
val animatorSet = AnimatorSet()
animatorSet.play(scaleXAni).with(scaleYAni).with(tranY1Ani).before(tranYAni)
.before(alphaAni)
Copy the code
Look at the effect.
Pretty much every piece of the disassembly is done, and now it’s time to put together the IM interface, the bomb parabola, the explosion effect, and finally the explosion effect.
Finally, the result is as follows:
In the moment of the bomb explosion, the user profile picture and expression will be shaken to the effect of shaking, here did not achieve, interested partners can try.
Well, that’s all for this article. Feel still ok, can give three even yo!
Recommended reading:
Compose theme list for Compose Mimicking free naked eye 3D effect
eggs
A few days ago successfully applied to the nuggets surrounding, then open the lottery below this article, thanks to the nuggets official support.
Lucky draw:
Until September 10, if more than 10 people interact in the comments section (excluding myself), the top two lucky viewers will be selected from the popular comments section and each will be given a “gold digging badge”. (Note: Comments for yourself are not included)
Drawing time: September 11th 12:00 noon