自訂View之大風車系列demo(三),大風車demo

來源:互聯網
上載者:User

自訂View之大風車系列demo(三),大風車demo

大風車系列版本1.0到版本3.0的體驗有很大的不足:風車旋轉的弧度都是手動寫死的,不會根據手指移動的快慢而快慢。版本4.0將解決這個問題,思路如下:

1)以風車圖片的中心為座標原點簡曆一個直角座標系,捕獲手指按下事件也即是MotionEvent.ACTION_DOWN事件,記錄此時手指的座標點與直角座標系x正座標軸的夾角

2)擷取手指移動的時候當前手指座標點與直角座標系x正軸的夾角。

3)計算步驟1和步驟2的兩個夾角的差,就是手指此時移動的弧度。而不像版本3.0之前的那樣寫死了

具體代碼設計如下:提供了速度控制器類SpeedControl類,在裡面主要提供了擷取當前座標點與x正軸的夾角的方法,該類的的代碼如下:

package rotation.demo.bean;public class SpeedControl {/** 手指按下時候的弧度 **/private float down_rad;/** 手指move時當前座標的弧度 **/private float current_move_rad;/** 弧度增量,它的值等於current_move_rad - down_rad**/private float Δrad;/** 圖片的中心原點 **/private float x0, y0;public SpeedControl(float x0, float y0) {this.x0 = x0;this.y0 = y0;}/*** * 計算當前座標點與x軸的夾角所代表的弧度,弧度計算公式為 1rad = 180/Math.PI,<br> * 需要注意的是直角座標系分四個象限,每個象限的座標點與x軸的夾角計算時需要計算一下 *  * @param current_x *            當前座標點的橫座標點 * @param current_y *            當前座標點的縱座標點 * @return */public float computeRad(float current_x, float current_y) {final float Δx = current_x - x0;final float Δy = current_y - y0;double θ = 0f;// 夾角// 求夾角的正切的絕對值float tanθ = Math.abs(Δy / Δx);if (Δx > 0) {// 當座標點在1或者4象限的情況if (Δy >= 0) {// 座標點位於第一象限θ = Math.atan(tanθ);} else {// 當座標點位於第四象限θ = 2 * Math.PI - Math.atan(tanθ);}} else {// 當座標點位於2或3象限if (Δy >= 0) {// 位於第二象限θ = Math.PI - Math.atan(tanθ);} else {// 位於第三象限θ = Math.PI + Math.atan(tanθ);}}                //注意一弧度 = 180/Math.PIfloat result = (float) ((180 * θ) / Math.PI);return result;}public float getDown_rad() {return down_rad;}public void setDown_rad(float down_rad) {this.down_rad = down_rad;}public float getCurrent_move_rad() {return current_move_rad;}public void setCurrent_move_rad(float current_move_rad) {this.current_move_rad = current_move_rad;}        //該方法工Matrix.preRotate使用public float getΔrad() {return Δrad;}public void setΔrad(float δrad) {Δrad = δrad;}}

進而RotationView的代碼做了如下改變,主要體現在onTouchEvent和onDraw上:

package rotation.demo.view;import rotation.demo.bean.SpeedControl;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * verson3.0 前兩個版本都是手指離開螢幕的時候就會立即停止轉動,現在這個版本讓當手指抬起的時候,由於慣性讓風車繼續轉動一點時間。 * 思路:監聽手指抬起事件,然後重繪 *  * @author YanQiu * */public class RotationView extends View {/** 要轉動的圖片 **/private Bitmap bitMap;/** 風車每次轉動的弧度 **/private int degree = 0;/** 圖片的寬度:在這裡提供的是正方形的圖片,所以寬度和高度是一樣的 **/private int width = 0;/*** 圖片的高度:在這裡提供的是正方形的圖片,所以寬度和高度是一樣的 **/private int height = 0;/** 定義一個畫筆 **/private Paint paint = new Paint();/**手指抬起的時間**/private long upTime = 0;/**手指抬起的時候風車持續轉動的時間**/private final long stopTimeDuration = 5000;/**速度控制器**/private SpeedControl speedControl;public RotationView(Context context, AttributeSet attrs) {super(context, attrs);}public RotationView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public RotationView(Context context) {super(context);}private String tag = "";/** * 計算圖片的圓心 */public void initSize() {width = bitMap.getWidth();height = bitMap.getHeight();speedControl = new SpeedControl(width/2,height/2);postInvalidate();}public void setBitMap(Bitmap bitMap) {this.bitMap = bitMap;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);setMeasuredDimension(width, width);}@Overrideprotected void onDraw(Canvas canvas) {Matrix matrix = new Matrix();// 設定轉軸位置matrix.setTranslate((float) width / 2, (float) height / 2);// 開始轉,為手指轉過的弧度matrix.preRotate(speedControl.getΔrad());// 轉軸還原matrix.preTranslate(-(float) width / 2, -(float) height / 2);canvas.drawBitmap(bitMap, matrix, paint);super.onDraw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();switch (action) {case MotionEvent.ACTION_DOWN://擷取手指按下的座標點與x軸夾角的弧度                        final float down_rad = speedControl.computeRad(event.getX(), event.getY());speedControl.setDown_rad(down_rad);break;case MotionEvent.ACTION_MOVE:// 隨著手指的move而不斷進行重繪final float current_move_rad = speedControl.computeRad(event.getX(), event.getY());final float Δrad = current_move_rad - speedControl.getDown_rad();//計算手指滑過的弧度差speedControl.setΔrad(Δrad);//該方法在UI線程自身中使用postInvalidate();break;case MotionEvent.ACTION_UP:// 隨著手指的move而不斷進行重繪upTime = System.currentTimeMillis();post(new Runnable() {@Overridepublic void run() {long duration = System.currentTimeMillis()-upTime;if(duration ==stopTimeDuration ) {return;}else if(duration<stopTimeDuration) {post(this);}//在非UI線程中使用。 invalidate();}});break;}return true;}}
經過測試這個版本可以讓風車隨著手指移動速度的變化而變化,但是還是有個問題,就是手指抬起的時候同樣的風車會停止轉動,這個將在最後的版本來解決,詳見自訂view之大風車系列(四)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.