咖啡伴侶

          呆在上海
          posts - 163, comments - 156, trackbacks - 0, articles - 2

          android手勢效果-水果忍者 刀鋒效果/光刀效果

          Posted on 2011-09-23 11:29 oathleo 閱讀(3955) 評論(5)  編輯  收藏 所屬分類: Android
          請保留:
          http://www.aygfsteel.com/oathleo/archive/2011/09/23/android_Fruit_Ninja.html


          android手勢加上了,比如左右滑動
          但是用戶經常不能感受到是否滑動了,
          水果忍者刀鋒效果/光刀效果就相當不錯

          網上搜了下,大多是ios的實現,想想原理可能不是很復雜,就實現了個最簡單的。
          原理
          1.在背景view上再加一層view專門負責draw刀鋒
          2.刀鋒就是隨著手勢move,動態畫shape
          3.接受到事件得dispatchTouchEvent,否則下面的組件無法獲得事件了
          4.下面的組件事件等無需更改,互不耦合
          5.一個類實現,不涉及其他第三方
          6.只實現了一個最簡單的形狀,水果忍者里面實現了很多復雜形狀,可以在這個基礎上進行擴展
          效果如圖



          代碼:
          import android.content.Context;
          import android.graphics.Canvas;
          import android.graphics.Color;
          import android.graphics.Paint;
          import android.graphics.Path;
          import android.view.MotionEvent;
          import android.view.View;



          /**
           * 
           * 模仿水果忍者刀鋒效果
           * 
          @author leooath@gmail.com
           *
           
          */
          public class GestureView extends View {

              
          private Paint paint;

              
          private float startX = Float.NaN;
              
          private float startY = Float.NaN;
              
          private float endX = Float.NaN;
              
          private float endY = Float.NaN;

              
          //下層view
              private View viewer;
              
          private static final int gestureColor = Color.rgb(153153153);
              
          private static final int alpha = 220;
              
          private static final int alpha_full = 255;
              
          //刀鋒長度
              private static final int shape_length = 40;
              
          //刀鋒截短時間
              private static final int shape_cut_time = 150;
              
              
          public GestureView(Context context, View viewer) {
                  
          super(context);
                  
          this.viewer = viewer;
                  paint 
          = new Paint();
                  paint.setStyle(Paint.Style.FILL);
              }

              
          public void draw(Canvas canvas) {
                  
          super.draw(canvas);
                  
          if (!Float.isNaN(startX) && !Float.isNaN(endY)) {
                      
          float gap = ViewUtils.getGap(startX, startY, endX, endY);
                      
          float w = gap / 10;
                      
          //背景shape外側點高度
                      float h = w > 7 ? 7 : w;
                      
          //填充shape外側點高度
                      float h2 = h * 2 / 3

                      
          double length = Math.pow(Math.pow(w, 2+ Math.pow((h), 2), 0.5);
                      
          double length2 = Math.pow(Math.pow(w, 2+ Math.pow((h2), 2), 0.5);
                      
                      
          double ang1_1 = Math.atan((endY - startY) / (endX - startX));
                      
          double ang1_2 = Math.atan(h / w);
                      
          double angle1_1 = ang1_1 + ang1_2;
                      
          double angle1_2 = ang1_1 - ang1_2;
                      
                      
          double ang2_2 = Math.atan(h2 / w);
                      
          double angle2_1 = ang1_1 + ang2_2;
                      
          double angle2_2 = ang1_1 - ang2_2;
                      
          if (endX > startX) {
                          
          float xx1 = endX - (float) (length * Math.cos(angle1_1));
                          
          float yy1 = endY - (float) (length * Math.sin(angle1_1));
                          
          float xx2 = endX - (float) (length * Math.cos(angle1_2));
                          
          float yy2 = endY - (float) (length * Math.sin(angle1_2));

                          
          float xx12 = endX - (float) (length2 * Math.cos(angle2_1));
                          
          float yy12 = endY - (float) (length2 * Math.sin(angle2_1));
                          
          float xx22 = endX - (float) (length2 * Math.cos(angle2_2));
                          
          float yy22 = endY - (float) (length2 * Math.sin(angle2_2));
                          
                          Path backPath 
          = new Path();
                          backPath.moveTo(startX, startY);
                          backPath.lineTo(xx1, yy1);
                          backPath.lineTo(endX, endY);
                          backPath.lineTo(xx2, yy2);
                          backPath.close();
                          
                          Path fillPath 
          = new Path();
                          fillPath.moveTo(startX, startY);
                          fillPath.lineTo(xx12, yy12);
                          fillPath.lineTo(endX, endY);
                          fillPath.lineTo(xx22, yy22);
                          fillPath.close();

                          paint.setColor(gestureColor);
                          paint.setAlpha(alpha);
                          canvas.drawPath(backPath, paint);
                          
                          paint.setColor(Color.WHITE);
                          paint.setAlpha(alpha_full);
                          canvas.drawPath(fillPath, paint);
                      } 
          else {
                          
          float xx1 = endX + (float) (length * Math.cos(angle1_1));
                          
          float yy1 = endY + (float) (length * Math.sin(angle1_1));
                          
          float xx2 = endX + (float) (length * Math.cos(angle1_2));
                          
          float yy2 = endY + (float) (length * Math.sin(angle1_2));

                          
          float xx12 = endX + (float) (length2 * Math.cos(angle2_1));
                          
          float yy12 = endY + (float) (length2 * Math.sin(angle2_1));
                          
          float xx22 = endX + (float) (length2 * Math.cos(angle2_2));
                          
          float yy22 = endY + (float) (length2 * Math.sin(angle2_2));
                          
                          Path backPath 
          = new Path();
                          backPath.moveTo(startX, startY);
                          backPath.lineTo(xx1, yy1);
                          backPath.lineTo(endX, endY);
                          backPath.lineTo(xx2, yy2);
                          backPath.close();

                          Path fillPath 
          = new Path();
                          fillPath.moveTo(startX, startY);
                          fillPath.lineTo(xx12, yy12);
                          fillPath.lineTo(endX, endY);
                          fillPath.lineTo(xx22, yy22);
                          fillPath.close();

                          paint.setColor(gestureColor);
                          paint.setAlpha(alpha);
                          canvas.drawPath(backPath, paint);
                          
                          paint.setColor(Color.WHITE);
                          paint.setAlpha(alpha_full);
                          canvas.drawPath(fillPath, paint);
                      }
                  }
              }

              
          public boolean onTouchEvent(android.view.MotionEvent event) {
                  
          if(event.getPointerCount() == 1){
                      
          int action = event.getAction();
                      
          if (MotionEvent.ACTION_DOWN == action) {
                          startX 
          = event.getX();
                          startY 
          = event.getY();
                      } 
          else if (MotionEvent.ACTION_MOVE == action) {
                          endX 
          = event.getX();
                          endY 
          = event.getY();
                          
                          
          //刀鋒截短時間,則截短至一半
                          if ((event.getEventTime() - event.getDownTime()) > shape_cut_time) {
                              
          if(Math.abs(endX - startX) > shape_length && Math.abs(endY - startY) > shape_length){
                                  startX 
          = (float) (startX + (endX - startX) * 0.5);
                                  startY 
          = (float) (startY + (endY - startY) * 0.5);
                              }
                          }

                          invalidate();
                      } 
          else if (MotionEvent.ACTION_UP == action) {
                          startX 
          = Float.NaN;
                          startY 
          = Float.NaN;
                          endX 
          = Float.NaN;
                          endY 
          = Float.NaN;
                          invalidate();
                      }
                  }
                  
          //該view消費了event,所以下層的view必須dispatchTouchEvent才能獲得事件
                  MotionEvent newEvent = MotionEvent.obtain(event);
                  viewer.dispatchTouchEvent(newEvent);
                  
          return true;
              }

          }

          Feedback

          # re: android手勢效果-水果忍者 刀鋒效果/光刀效果  回復  更多評論   

          2011-09-25 23:23 by tbw
          不錯啊

          # re: android手勢效果-水果忍者 刀鋒效果/光刀效果  回復  更多評論   

          2011-09-28 16:45 by 優美科

          ViewUtils.getGap(startX, startY, endX, endY);
          函數呢 怎么沒有

          # re: android手勢效果-水果忍者 刀鋒效果/光刀效果  回復  更多評論   

          2011-10-13 13:44 by oathleo
          @優美科
          /**
          * 獲得兩點間距離
          */
          public static final float getGap(float x0, float y0, float x1, float y1) {
          return (float) Math.pow(Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2), 0.5);
          }

          # re: android手勢效果-水果忍者 刀鋒效果/光刀效果[未登錄]  回復  更多評論   

          2012-03-24 20:22 by tobe
          那請問怎樣在一層view上加入這層半透明的view呢?

          # re: android手勢效果-水果忍者 刀鋒效果/光刀效果  回復  更多評論   

          2012-04-07 21:17 by banxi
          請問下,我想實現水果忍者的切按鈕的效果。也就是更進一步的效果如果處理。特向您請教下!
          主站蜘蛛池模板: 凉城县| 崇州市| 彰武县| 连平县| 乐山市| 浪卡子县| 定兴县| 平阳县| 兴化市| 平罗县| 西充县| 德兴市| 大丰市| 清涧县| 东源县| 睢宁县| 湟中县| 民权县| 旬阳县| 将乐县| 工布江达县| 化隆| 冷水江市| 高阳县| 孝感市| 曲麻莱县| 漳浦县| 章丘市| 莱阳市| 上思县| 望谟县| 曲麻莱县| 晋州市| 涟水县| 铁岭市| 托克逊县| 张家口市| 晋宁县| 桂东县| 鹰潭市| 高雄市|