Android位移動畫-轉圈的Button

來源:互聯網
上載者:User

以前做項目碰到過一個需求,就是有5個button,這5個button要圍繞一個點不停的轉動,而且點擊不同的button會進行相應的邏輯,比如activity的跳轉等.

就類似於gallery,但是又有所不同

有人會首先想到用位移動畫,但是android的位移動畫只是動畫,也就是說你從A點移動B點,看上去是移動過去了,但是點擊的事件觸發卻還是在A點,實際上沒有真正的

位移過去,只是欺騙眼睛罷了,但是在android2.2以後api提供了這樣的一個方法setPosition(),這個方法的好處是你可以監聽動畫,假如一段動畫完成了你可以動態

得到現在button的位置,然後set進去,這樣也可以完成操作,但是簡單的運動還行,如果是向我上門說的5個button不停的轉動,然後每個button的動畫不斷的監聽然後set

會很費事,而且2.2以下的pad或者手機就沒有辦法安裝了

 

其實如果是在ios上這樣是非常容易的,ios的位移動畫很像我們做flash一樣,定製起始點,再定製一個終點,然後建立補間動畫即可,幾行代碼就可以搞定,但是android上就不行

 

所以基於以上,我就只能是這個思路,我就實現真正的位移好了,對,就是用開發遊戲的思路實現真正的位移

 

下面我直接上代碼了,以下是舞台的代碼

我的button就相當於演員,演員要表演只能去舞台

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();}}

 

舞台中的演員:RotateImageView  這個也是我自己定義的一個類,就相當於button,你要在舞台上添加幾個演員你就new幾個好了,我沒有好的圖片,所以就拿預設的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;}}

 

這個是我的演員(button)代碼

其實細心的朋友就已經發現了我是不斷重繪每一個view的座標,實現這種轉圈的效果,所以這個demo最關鍵的就是怎麼來算出每個button下一幀的位置

如果你是想讓一個button轉圈,這個非常好實現,但是如果想讓5個button沿著同一軌跡來運動畫圈不那麼容易,至少我是費了很多時間的

因為表演的演員的職責,所以這樣的邏輯就在它自身了

xPix = RotateStage.POINTX + Math.cos(angle*ANGLENUM)*RotateStage.RADIUS;

yPix = RotateStage.POINTY + Math.sin(angle*ANGLENUM)*RotateStage.RADIUS;

angle += 1;

這裡面的RotateStage.POINTX 是我計算的螢幕中心點的位置,RotateStage.RADIUS是所繞圈的半徑大小

ANGLENUM也可以看到,實際上就是Math.PI/180

每次運動繪製angle會+1,就會相應的計算出新的座標,然後舞台調用它們各自的moveImageButton方法即可

 

還有值得注意的是舞台中的代碼:

也就是我自訂的演員的構造方法

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);

不一樣的也就是0 , 72 了,這個我沒有進行封裝,如果你們需要自己改改就可以了,為什麼是0和72呢,因為我是5個button,每一等分就是72,所以

也就是起始的角度,比如你是0度,你就在最右邊,你是72度,你就在72度角的方向上

 

我這麼說你們是不是已經很明白了?

再來說說怎麼樣觸發點擊事件吧,其實也要借鑒遊戲裡的思路了,就是計算你當前toutch的座標是否在button內,在哪一個button內

這樣做也有很多的演算法,比如Region碰撞檢測還有計算矩形的碰撞

我用的是後一種

@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);}

 

其實這樣做並不好,就是每次在點擊的時候都有點卡,但是要解決這個問題也很好辦,但是剩下的我就不說了,自己去嘗試吧

附上我項目中的一張:

 

 

另外如果誰還有更好的一些辦法請告訴我,一定感激不盡!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.