English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
When writing a mall project, there is usually a shopping cart function. When adding items to the shopping cart, there are some parabolic animations. The specific code is as follows:
The effect is shown as follows:
Thoughts:
Difficulties:
Usage of PathMeasure
- getLength()
- Understanding the method 'boolean getPosTan(float distance, float[] pos, float[] tan)'
Knowledge points involved:
How to get the absolute coordinates of a control on the screen
//Get the starting point coordinate of the parent layout (used to assist in calculating the start of the animation/The coordinate of the point at the end) int[] parentLocation = new int[2]; rl.getLocationInWindow(parentLocation);
How to use Bezier curve and property animation interpolator ValueAnimator
// Four, calculate the interpolation coordinates of the intermediate animation (Bezier curve) (which is actually to complete the process from the starting point to the endpoint with the Bezier curve) //Start drawing the Bézier curve Path path = new Path(); //Move to the starting point (the starting point of the Bézier curve) path.moveTo(startX, startY); //Use quadratic Bézier curve: note that the larger the starting coordinate, the greater the horizontal distance of the Bézier curve will be. Generally, the following formula can be used path.quadTo((startX + toX) / 2, startY, toX, toY); //mPathMeasure is used to calculate the length of the Bezier curve and the coordinates of the intermediate interpolation of the Bezier curve, // If it is true, the path will form a closed loop mPathMeasure = new PathMeasure(path, false); //★★★Attribute animation implementation (interpolation calculation between 0 and the length of the Bezier curve to obtain the distance value of the intermediate process) ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength()); valueAnimator.setDuration(1000); // Uniform linear interpolation valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // When the interpolation calculation is going on, get each value in the middle // This value is the length of the curve in the middle process (the midpoint coordinates will be obtained based on this value below) float value = (Float) animation.getAnimatedValue(); // ★★★★★Encapsulate the current point coordinates into mCurrentPosition // boolean getPosTan(float distance, float[] pos, float[] tan) : // Pass a distance distance (0 <= distance <= getLength()), and then calculate the current distance // The coordinates of the point and the tangent, pos will automatically fill in the coordinates, this method is very important. mPathMeasure.getPosTan(value, mCurrentPosition, null);//mCurrentPosition is the coordinates of the midpoint at this time // Set the coordinates of the moving goods image (animation image) to the coordinates of the midpoint goods.setTranslationX(mCurrentPosition[0]); goods.setTranslationY(mCurrentPosition[1}); } }); // Five, start executing the animation valueAnimator.start();
All code:
package cn.c.com.beziercurveanimater; import android.animation.Animator; import android.animation.ValueAnimator; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Path; import android.graphics.PathMeasure; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private ImageView cart; private ArrayList<Bitmap> bitmapList = new ArrayList<>(); private RelativeLayout rl; private PathMeasure mPathMeasure; /** * The coordinates of the points in the middle process of the Bezier curve */ private float[] mCurrentPosition = new float[2]; private TextView count; private int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initImg(); MyAdapter myAdapter = new MyAdapter(bitmapList); mRecyclerView.setAdapter(myAdapter); mRecyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); } private void initImg() { bitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.coin)); bitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.coin1)); bitmapList.add(BitmapFactory.decodeResource(getResources(), R.drawable.coin91)); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); cart = (ImageView) findViewById(R.id.cart); rl = (RelativeLayout) findViewById(R.id.rl); count = (TextView) findViewById(R.id.count); } class MyAdapter extends RecyclerView.Adapter<MyVH> { private ArrayList<Bitmap> bitmapList; public MyAdapter(ArrayList<Bitmap> bitmapList) { this.bitmapList = bitmapList; } @Override public MyVH onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(MainActivity.this); View itemView = inflater.inflate(R.layout.item, parent, false); MyVH myVH = new MyVH(itemView); return myVH; } @Override public void onBindViewHolder(final MyVH holder, final int position) { holder.iv.setImageBitmap(bitmapList.get(position)); holder.buy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { addCart(holder.iv); } }); } @Override public int getItemCount() { return bitmapList.size(); } } /** * ★★★★★ Add the product to the shopping cart animation effect ★★★★★ * @param iv */ private void addCart(ImageView iv) { // 1. Create the main theme for the animation---ImageView //Code creates a new ImageView with the image resource being the same as the image in the above ImageView // This image is the one used for the animation, starting from the initial position, moving along a parabolic (Bezier curve) path, and finally into the shopping cart) final ImageView goods = new ImageView(MainActivity.this); goods.setImageDrawable(iv.getDrawable()); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100); rl.addView(goods, params); // Two, calculate the animation start/Preparation for the coordinate of the end point //Get the starting point coordinate of the parent layout (used to assist in calculating the start of the animation/The coordinate of the point at the end) int[] parentLocation = new int[2]; rl.getLocationInWindow(parentLocation); //Get the coordinate of the product image (used to calculate the starting coordinate of the animation) int startLoc[] = new int[2]; iv.getLocationInWindow(startLoc); //Get the coordinate of the shopping cart image (used to calculate the coordinate after the animation ends) int endLoc[] = new int[2]; cart.getLocationInWindow(endLoc); // Three, start calculating the animation start/The ending coordinate //The starting point of the falling product: the starting point of the product-Parent layout starting point+Half of the product image float startX = startLoc[0] - parentLocation[0] + iv.getWidth() / 2; float startY = startLoc[1] - parentLocation[1] + iv.getHeight() / 2; //The final coordinate of the product after falling: the starting point of the shopping cart-Parent layout starting point+The image of the shopping cart1/5 float toX = endLoc[0] - parentLocation[0] + cart.getWidth() / 5; float toY = endLoc[1] - parentLocation[1]; // Four, calculate the interpolation coordinates of the intermediate animation (Bezier curve) (which is actually to complete the process from the starting point to the endpoint with the Bezier curve) //Start drawing the Bézier curve Path path = new Path(); //Move to the starting point (the starting point of the Bézier curve) path.moveTo(startX, startY); //Use quadratic Bézier curve: note that the larger the starting coordinate, the greater the horizontal distance of the Bézier curve will be. Generally, the following formula can be used path.quadTo((startX + toX) / 2, startY, toX, toY); //mPathMeasure is used to calculate the length of the Bezier curve and the coordinates of the intermediate interpolation of the Bezier curve, // If it is true, the path will form a closed loop mPathMeasure = new PathMeasure(path, false); //★★★Attribute animation implementation (interpolation calculation between 0 and the length of the Bezier curve to obtain the distance value of the intermediate process) ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength()); valueAnimator.setDuration(1000); // Uniform linear interpolation valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // When the interpolation calculation is going on, get each value in the middle // This value is the length of the curve in the middle process (the midpoint coordinates will be obtained based on this value below) float value = (Float) animation.getAnimatedValue(); // ★★★★★Encapsulate the current point coordinates into mCurrentPosition // boolean getPosTan(float distance, float[] pos, float[] tan) : // Pass a distance distance (0 <= distance <= getLength()), and then calculate the current distance // The coordinates of the point and the tangent, pos will automatically fill in the coordinates, this method is very important. mPathMeasure.getPosTan(value, mCurrentPosition, null);//mCurrentPosition is the coordinates of the midpoint at this time // Set the coordinates of the moving goods image (animation image) to the coordinates of the midpoint goods.setTranslationX(mCurrentPosition[0]); goods.setTranslationY(mCurrentPosition[1}); } }); // Five, start executing the animation valueAnimator.start(); // Six, handling after animation ends valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } //After the animation ends: @Override public void onAnimationEnd(Animator animation) { // Add the number of items in the shopping cart1 i++; count.setText(String.valueOf(i)); // Remove the moving imageview from the parent layout rl.removeView(goods); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); } class MyVH extends RecyclerView.ViewHolder { private ImageView iv; private TextView buy; public MyVH(View itemView) { super(itemView); iv = (ImageView) itemView.findViewById(R.id.iv); buy = (TextView) itemView.findViewById(R.id.buy); } } }
That's all for this article. Hope it helps everyone's learning and also hope everyone supports the Naiya Tutorial.
Statement: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been edited by humans, and does not assume relevant legal liabilities. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please report by email to codebox.com (replace # with @ when sending an email) and provide relevant evidence. Once verified, this site will immediately delete the infringing content.