Android offset animation-circled button

Source: Internet
Author: User
Tags gety

In the past, there was a requirement that there were five buttons. These five buttons should be rotated around a single point, and the corresponding logic will be implemented by clicking different buttons, for example, activity jump.

It is similar to gallery, but it is different.

Some people will first think of using an offset animation, but Android's offset animation is only an animation. That is to say, you move point B from point A. It seems to have moved, but the click event is triggered at point, actually there is no real

The offset of the past is just a deception, but after Android, the API provides such a method setposition (). The advantage of this method is that you can listen to animations, if an animation is completed, you can dynamically

Get the current button position, and set it in. This can also complete the operation, but the simple movement is okay. If the five buttons mentioned to me keep turning, then, the animation of each button is constantly monitored and set

It will be very troublesome, and there is no way to install pad or mobile phone numbers below 2.2

 

In fact, it is very easy to do this on iOS. the IOS offset animation is similar to flash. You can customize the starting point and end point, and then create a compensation animation, only a few lines of code can be done, but not on Android.

 

So based on the above, I can only use this idea, and I will achieve a real offset, right, that is, using the idea of game development to achieve a real offset.

 

Now I am using the code directly. Here is the code for the stage.

My button is equivalent to an actor. actors can only go to the stage to perform performances.

package com.yp.rotatebutton;import android.app.Activity;import android.content.Context;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.util.DisplayMetrics;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.WindowManager;public class RotateStage extends SurfaceView implements SurfaceHolder.Callback,Runnable {public static final String TAG= "RotateStage";private Context context ;private SurfaceHolder holder ;private Thread mThread ;private Canvas mCanvas;private boolean isMovie = false;private RotateImageView mOneImageView ,mTwoImageView, mThreeImageView,mFourthImageView,mFiveImageView;public static double POINTX = DisplayMetrics.DENSITY_LOW ;public static double POINTY = DisplayMetrics.DENSITY_HIGH ;public static final  double RADIUS = 100;public RotateStage(Context context) {super(context);this.context = context;this.holder = this.getHolder();this.holder.addCallback(this);DisplayMetrics dm = new DisplayMetrics();((Activity) this.context).getWindowManager().getDefaultDisplay().getMetrics(dm);POINTX = dm.widthPixels / 2 -  BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher).getWidth() / 2;POINTY = dm.heightPixels / 2 - BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher).getHeight() / 2 ;Init();}private void Init(){mOneImageView = new RotateImageView(this.context,R.drawable.ic_launcher, POINTX+ Math.cos(0 * RotateImageView.ANGLENUM) * RADIUS,POINTY + Math.sin(0 * RotateImageView.ANGLENUM) * RADIUS, 0);mTwoImageView = new RotateImageView(this.context,R.drawable.ic_launcher, POINTX+ Math.cos(72 * RotateImageView.ANGLENUM) * RADIUS,POINTY + Math.sin(72 * RotateImageView.ANGLENUM) * RADIUS, 72);mThreeImageView = new RotateImageView(this.context,R.drawable.ic_launcher, POINTX+ Math.cos(144 * RotateImageView.ANGLENUM) * RADIUS,POINTY + Math.sin(144 * RotateImageView.ANGLENUM) * RADIUS, 144);mFourthImageView = new RotateImageView(this.context,R.drawable.ic_launcher, POINTX+ Math.cos(216 * RotateImageView.ANGLENUM) * RADIUS,POINTY + Math.sin(216 * RotateImageView.ANGLENUM) * RADIUS, 216);mFiveImageView = new RotateImageView(this.context,R.drawable.ic_launcher, POINTX+ Math.cos(288 * RotateImageView.ANGLENUM) * RADIUS,POINTY + Math.sin(288 * RotateImageView.ANGLENUM) * RADIUS, 288);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stubmThread = new Thread(this);mThread.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {isMovie = true ;}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stubisMovie = false;}@Overridepublic void run() {while (isMovie) {long start = System.currentTimeMillis();draw();logic();long end = System.currentTimeMillis();if (end - start < 5) {try {Thread.sleep (5 - (end - start)) ;//Thread.sleep(5);} catch (InterruptedException e) {Log.v(TAG, "run thread sleep error : " + e.toString());}}}}public void draw(){try{mCanvas = holder.lockCanvas() ;mCanvas.drawColor(Color.RED);mCanvas.drawBitmap(mOneImageView.getmBgBitmap(), (float)mOneImageView.getxPix(), (float)mOneImageView.getyPix(), null);mCanvas.drawBitmap(mTwoImageView.getmBgBitmap(), (float)mTwoImageView.getxPix(), (float)mTwoImageView.getyPix(), null);mCanvas.drawBitmap(mThreeImageView.getmBgBitmap(), (float)mThreeImageView.getxPix(), (float)mThreeImageView.getyPix(), null);mCanvas.drawBitmap(mFourthImageView.getmBgBitmap(), (float)mFourthImageView.getxPix(), (float)mFourthImageView.getyPix(), null);mCanvas.drawBitmap(mFiveImageView.getmBgBitmap(), (float)mFiveImageView.getxPix(), (float)mFiveImageView.getyPix(), null);}catch (Exception e) {Log.v(TAG, "draw error: " + e.toString());}finally{if (mCanvas != null) holder.unlockCanvasAndPost(mCanvas) ;}}private void logic() {mOneImageView.moveImageButton();mTwoImageView.moveImageButton();mThreeImageView.moveImageButton();mFourthImageView.moveImageButton();mFiveImageView.moveImageButton();}}

 

Actors in the stage: rotateimageview, which is also a class defined by myself, is equivalent to a button. If you want to add a few actors on the stage, you can just add a few new ones. I don't have any good pictures, so take the default icon.

 

package com.yp.rotatebutton;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.util.Log;/** *  * @author peng_yu * */public class RotateImageView {public static final String TAG = "RotateImageView";public static final double ANGLENUM = Math.PI/180;private Bitmap mBgBitmap;private double angle ;private double xPix;private double yPix;public RotateImageView() {super();}public RotateImageView(Context content,int bgId,double XPix,double Ypix,double angle) {BitmapFactory.Options opts = new BitmapFactory.Options();opts.inJustDecodeBounds = true;mBgBitmap = BitmapFactory.decodeResource(content.getResources(),bgId);this.xPix = XPix;this.yPix = Ypix;this.angle = angle;}public double getAngle() {return angle;}public void setAngle(double angle) {this.angle = angle;}public int getHeight() {return mBgBitmap.getHeight();}public int getWidth() {return mBgBitmap.getWidth();}public double getxPix() {return xPix;}public void setxPix(double xPix) {this.xPix = xPix;}public double getyPix() {return yPix;}public void setyPix(double yPix) {this.yPix = yPix;}public Bitmap getmBgBitmap() {return mBgBitmap;}public void setmBgBitmap(Bitmap mBgBitmap) {this.mBgBitmap = mBgBitmap;}public void moveImageButton(){if(angle > 360){angle = 0;}xPix = RotateStage.POINTX + Math.cos(angle*ANGLENUM)*RotateStage.RADIUS;yPix = RotateStage.POINTY + Math.sin(angle*ANGLENUM)*RotateStage.RADIUS;angle += 1;}}

 

This is my actor (button) code.

As a matter of fact, careful friends have discovered that I have repeatedly re-painted the coordinates of each view to achieve this kind of circle effect, so the most important thing in this demo is how to calculate the next frame position of each button.

If you want to compress a button, this is a good implementation, but it is not easy to make the five buttons move along the same track, at least I have spent a lot of time.

This logic lies in the role of the performer.

Xpix = rotatestage. pointx + math. Cos (angle * anglenum) * rotatestage. radius;

Ypix = rotatestage. Pointy + math. Sin (angle * anglenum) * rotatestage. radius;

Angle + = 1;

Here, rotatestage. pointx is the center point of the screen I calculated, and rotatestage. radius is the radius of the circle.

Anglenum is actually math. PI/180.

Each time angle is drawn by motion, the angle will + 1, and a new coordinate will be calculated accordingly, and then the stage will call their respective moveimagebutton methods.

 

It is worth noting that the code in the stage is:

That is, the construction method of the custom actor.

Moneimageview = new rotateimageview (this. context,
R. drawable. ic_launcher, pointx

+ Math. Cos (0 * rotateimageview. anglenum) * radius,

Pointy + math. Sin (0 * rotateimageview. anglenum) * radius, 0 );

Mtwoimageview = new rotateimageview (this. context,

R. drawable. ic_launcher, pointx

+ Math. Cos (72 * rotateimageview. anglenum) * radius,

Pointy + math. Sin (72 * rotateimageview. anglenum) * radius, 72 );

The difference is 0, 72. I didn't encapsulate it. If you need to modify it yourself, why 0 and 72? Because I have five buttons, the first-level score is 72, so

That is, the starting angle. For example, if you are 0 degrees, you are on the rightmost side, you are 72 degrees, and you are in the direction of 72 degrees.

 

Do you already understand this?

Let's talk about how to trigger the click event. In fact, we also need to learn from the idea in the game, that is, to calculate whether your current toutch coordinates are in the button and in which button

There are also many algorithms, such as region Collision Detection and calculation of rectangular collision.

I used the last one.

@Overridepublic boolean onTouchEvent(MotionEvent event) {if(event.getX() > mOneImageView.getxPix() && event.getX() < mOneImageView.getxPix() + mOneImageView.getWidth()  && event.getY() > mOneImageView.getyPix() && event.getY() < mOneImageView.getyPix() + mOneImageView.getHeight()){Toast.makeText(this.context,"mOneImageView", 1).show();return false;}if(event.getX() > mTwoImageView.getxPix() && event.getX() < mTwoImageView.getxPix() + mTwoImageView.getWidth()&& event.getY() > mTwoImageView.getyPix() && event.getY() < mTwoImageView.getyPix() + mTwoImageView.getHeight()){Toast.makeText(this.context,"mTwoImageView", 1).show();return false;}if(event.getX() > mThreeImageView.getxPix() && event.getX() < mThreeImageView.getxPix() + mThreeImageView.getWidth()&& event.getY() > mThreeImageView.getyPix() && event.getY() < mThreeImageView.getyPix() + mThreeImageView.getHeight()){Toast.makeText(this.context,"mThreeImageView", 1).show();return false;}if(event.getX() > mFourthImageView.getxPix() && event.getX() < mFourthImageView.getxPix() + mFourthImageView.getWidth()&& event.getY() > mFourthImageView.getyPix() && event.getY() < mFourthImageView.getyPix() + mFourthImageView.getHeight()){Toast.makeText(this.context,"mFourthImageView", 1).show();return false;}if(event.getX() > mFiveImageView.getxPix() && event.getX() < mFiveImageView.getxPix() + mFiveImageView.getWidth()&& event.getY() > mFiveImageView.getyPix() && event.getY() < mFiveImageView.getyPix() + mFiveImageView.getHeight()){Toast.makeText(this.context,"mFiveImageView", 1).show();return false;}return super.onTouchEvent(event);}

 

In fact, this is not good, that is, there is a point card every time you click, but it is also easy to solve this problem, but I will not talk about the rest, please try it yourself

Attach one of my projects:

 

 

In addition, if anyone has better solutions, please let me know. I am very grateful!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.