咖啡伴侶

          呆在上海
          posts - 163, comments - 156, trackbacks - 0, articles - 2
          請(qǐng)保留:
          http://www.aygfsteel.com/oathleo/archive/2011/09/23/android_Fruit_Ninja.html


          android手勢(shì)加上了,比如左右滑動(dòng)
          但是用戶經(jīng)常不能感受到是否滑動(dòng)了,
          水果忍者刀鋒效果/光刀效果就相當(dāng)不錯(cuò)

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



          代碼:
          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;
              
          //刀鋒截短時(shí)間
              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外側(cè)點(diǎn)高度
                      float h = w > 7 ? 7 : w;
                      
          //填充shape外側(cè)點(diǎn)高度
                      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();
                          
                          
          //刀鋒截短時(shí)間,則截短至一半
                          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消費(fèi)了event,所以下層的view必須dispatchTouchEvent才能獲得事件
                  MotionEvent newEvent = MotionEvent.obtain(event);
                  viewer.dispatchTouchEvent(newEvent);
                  
          return true;
              }

          }

          Feedback

          # re: android手勢(shì)效果-水果忍者 刀鋒效果/光刀效果  回復(fù)  更多評(píng)論   

          2011-09-25 23:23 by tbw
          不錯(cuò)啊

          # re: android手勢(shì)效果-水果忍者 刀鋒效果/光刀效果  回復(fù)  更多評(píng)論   

          2011-09-28 16:45 by 優(yōu)美科

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

          # re: android手勢(shì)效果-水果忍者 刀鋒效果/光刀效果  回復(fù)  更多評(píng)論   

          2011-10-13 13:44 by oathleo
          @優(yōu)美科
          /**
          * 獲得兩點(diǎn)間距離
          */
          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手勢(shì)效果-水果忍者 刀鋒效果/光刀效果[未登錄]  回復(fù)  更多評(píng)論   

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

          # re: android手勢(shì)效果-水果忍者 刀鋒效果/光刀效果  回復(fù)  更多評(píng)論   

          2012-04-07 21:17 by banxi
          請(qǐng)問下,我想實(shí)現(xiàn)水果忍者的切按鈕的效果。也就是更進(jìn)一步的效果如果處理。特向您請(qǐng)教下!
          主站蜘蛛池模板: 岳池县| 抚松县| 阳东县| 富平县| 鄂州市| 营口市| 南汇区| 辉县市| 文安县| 阳朔县| 包头市| 江山市| 乳山市| 青州市| 航空| 禹城市| 化隆| 中卫市| 若尔盖县| 盐亭县| 罗山县| 丰顺县| 延庆县| 廊坊市| 额敏县| 日喀则市| 油尖旺区| 阜新| 龙胜| 原阳县| 张家川| 玉山县| 朝阳市| 民和| 菏泽市| 汝城县| 双辽市| 荥经县| 岑巩县| 缙云县| 昌乐县|