2015-02-26 2 views
0

Je rencontre un problème en développant un grossissement basé sur l'emplacement tactile dans Android. Le résultat que je veux est similaire à l'ancien grossissement de la barre d'application du livre mac; l'icône sur laquelle la souris survole est la plus grande agrandie et les icônes l'entourent lentement jusqu'à leur taille d'origine.Grossissement basé sur l'emplacement tactile

J'ai inclus une image de ce qu'il devrait aimer si l'utilisateur touche une icône au centre de la barre d'icônes.

enter image description here

Actuellement, j'ai du code qui fonctionne un peu. J'utilise une équation cos pour créer le facteur d'échelle mais lorsque vous touchez près des icônes jaunes, la dernière icône verte est agrandie. De plus, l'affect en pente ne sort pas correctement. J'ai joint une photo avec des touches d'échantillons et le code. Merci pour toute aide que vous pouvez fournir. enter image description here

classe Java préformage l'échelle

public class Layout extends RelativeLayout implements View.OnTouchListener{ 
    private Camera mCamera = new Camera(); 
    private Matrix mMatrix = new Matrix(); 
    private ArrayList<Layer> layers = new ArrayList<Layer>(); 
    private final String TAG = this.getClass().getSimpleName(); 
    private int xTouch = 0; 
    private int yTouch = 0; 
    private boolean isUserInput = false; 

    private int childHeight = 1; 
    private Context context; 

    public TrackerLayout(Context context) { 
     super(context); 
     setupView(context); 
    } 

    public TrackerLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setupView(context); 
    } 

    public TrackerLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     setupView(context); 
    } 

    private void setupView(Context context){ 
     this.context = context; 
     setOnTouchListener(this); 
     setWillNotDraw(false);   
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (layers.size() != getChildCount()) { 
      getChildrenViews(); 
     } 
     //getChild's order 
     sortChildrenByDist(); 
     super.onDraw(canvas); 

    } 
    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     childHeight = h/8; 
     super.onSizeChanged(w, h, oldw, oldh); 
    } 

    @Override 
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 
     if(isUserInput && yTouch >= 0) { 
      Bitmap bitmap = child.getDrawingCache(); 

      if (bitmap == null) { 
       child.setDrawingCacheEnabled(true); 
       child.buildDrawingCache(); 
       bitmap = child.getDrawingCache(); 
      } 

      //Get a reference for the child layer that's being modified 
      Layer layer = null; 
      for (Layer tempLayer : layers) { 
       if (tempLayer.child.getId() == child.getId()) { 
        layer = tempLayer; 
        break; 
       } 
      } 

      canvas.save(); 
      if(layer.coordinates.scale < 1){ 
       layer.coordinates.scale = 1; 
      } 
      canvas.scale(layer.coordinates.scale, layer.coordinates.scale, layer.coordinates.pivotX, layer.coordinates.pivotY); 

      Paint paint = new Paint(); 
      paint.setAntiAlias(true); 
      paint.setFilterBitmap(true); 

      if (mCamera == null) { 
       mCamera = new Camera(); 
      } 

      mCamera.save(); 
      mCamera.rotateY(layer.coordinates.rotation); 

      if (mMatrix == null) { 
       mMatrix = new Matrix(); 
      } 

      mCamera.getMatrix(mMatrix); 
      mCamera.restore(); 

      mMatrix.preTranslate(-layer.coordinates.centerX, -layer.coordinates.centerY); 
      mMatrix.postScale(layer.coordinates.scale, layer.coordinates.scale); 
      mMatrix.postTranslate(layer.coordinates.pivotX, layer.coordinates.pivotY); 
      canvas.drawBitmap(bitmap, layer.coordinates.left, layer.coordinates.top, paint); 

      canvas.restore(); 
      return false; 
     } 
     return super.drawChild(canvas, child, drawingTime); 

    } 

    private void getChildrenViews() { 
     int childrenCount = this.getChildCount(); 

     for (int i = 0; i < childrenCount; i++) { 
      if (getChildAt(i) instanceof ImageView) { 
       Layer layer = new Layer(); 
       ImageView child = (ImageView) getChildAt(i); 
       int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources().getDisplayMetrics()); 
       RelativeLayout.LayoutParams params = (LayoutParams) child.getLayoutParams(); 
       params.height = childHeight; 
       child.setLayoutParams(params); 
       layer.child = (child); 

       layers.add(layer); 
      } 
     } 
    } 

    private void sortChildrenByDist() { 
     ArrayList<Layer> negDistLayers = new ArrayList<Layer>(); 
     ArrayList<Layer> postDistLayers = new ArrayList<Layer>(); 


     for (Layer layer : layers) { 
      layer.coordinates = calculateCoordinates(layer.child); 
      if(layer.coordinates.distFromCenter >= 0){ 
       postDistLayers.add(layer); 
      }else{ 
       negDistLayers.add(layer); 
      } 
     } 

     Collections.sort(negDistLayers); 
     Collections.sort(postDistLayers); 

     layers.clear(); 
     layers.addAll(postDistLayers); 
     layers.addAll(negDistLayers); 

     drawOrderedLayers(); 
    } 

    private synchronized void drawOrderedLayers() { 
     for (int i = (layers.size() - 1); i > -1; i--) { 
      this.bringChildToFront(layers.get(i).child); 

     } 
    } 

    /** 
    * This method calculates the coordinates used to create the rotates, camera, and scaling on each child view 
    * 
    * @param child - the view the coordinates will be calculated from 
    * @return 
    */ 

    private Coordinates calculateCoordinates(View child) { 
     Coordinates coordinates = new Coordinates(); 

     coordinates.left = child.getLeft(); 
     coordinates.top = child.getTop(); 

     coordinates.centerX = child.getWidth()/2; 
     coordinates.centerY = child.getHeight()/2; 

     coordinates.pivotX = coordinates.left + coordinates.centerX; 
     coordinates.pivotY = coordinates.top + coordinates.centerY; 

     coordinates.userYInput = yTouch; 
     coordinates.distFromCenter = (yTouch == 0) ? coordinates.pivotY : ((coordinates.pivotY - coordinates.userYInput)/coordinates.userYInput); 


     double cosValue = (Math.cos(coordinates.distFromCenter)); 
     coordinates.scale = (float) (2 * cosValue); 

     coordinates.rotation = coordinates.distFromCenter; 
     return coordinates; 

    }  

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     final int action = event.getAction(); 
     Log.i(TAG, " on touch detected"); 
     switch (action & MotionEvent.ACTION_MASK) { 

      case MotionEvent.ACTION_DOWN: { 
       xTouch = (int) event.getX(); 
       yTouch = (int) event.getY(); 
       isUserInput = true; 
       return true; 
      } 

      case MotionEvent.ACTION_MOVE: { 

       xTouch = (int) event.getX(); 
       yTouch = (int) event.getY(); 
       isUserInput = true; 
       return true; 
      } 

      default: 
       isUserInput = false; 
       return false; 
     } 

    } 

    private class Coordinates { 
     int left; 
     int top; 
     int centerX; 
     int centerY; 
     float pivotX; 
     float pivotY; 
     float userYInput; 
     float distFromCenter; 
     float scale; 
     float rotation; 

    } 

    //This class will hold a reference to the child and it's coordinates to 
    //help imitate layers 
    private class Layer implements Comparable<Layer> { 
     View child; 
     Coordinates coordinates; 

     //All values need to be sort towards) so there's an if case to determine if the input is 
     //comparing the list of positive values or negative values 
     public int compareTo(Layer compareItem) { 
      if(coordinates.distFromCenter >= 0) { 
       return Float.compare(coordinates.distFromCenter, compareItem.coordinates.distFromCenter); 
      }else{ 
       return Float.compare(compareItem.coordinates.distFromCenter, coordinates.distFromCenter); 
      } 
     } 

    } 

} 

xml layout

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@color/background_color"> 

    <com.layouts.Layout 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_alignParentEnd="true" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:layout_alignParentStart="true" 
     android:layout_alignParentTop=“true” 
     android:orientation="vertical"> 


     <ImageView 
      android:id="@+id/icon_level_1" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:layout_alignParentRight="true" 
      android:background="#FFF66C" 
      android:layout_alignParentTop="true"/> 

     <ImageView 
      android:id="@+id/icon_level_2" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#E7EE6C" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/ticon_level_1"/> 

     <ImageView 
      android:id="@+id/icon_level_3" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#CCE46D" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_2"/> 

     <ImageView 
      android:id="@+id/icon_level_4" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#B2E07B" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_3"/> 

     <ImageView 
      android:id="@+id/icon_level_5" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#8BDB91" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_4"/> 

     <ImageView 
      android:id="@+id/icon_level_6" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#65BE91" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_5"/> 

     <ImageView 
      android:id="@+id/icon_level_7" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#4E8F77" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_6"/> 

     <ImageView 
      android:id="@+id/icon_level_8" 
      android:layout_width="40dp" 
      android:layout_height="40dp" 
      android:layout_gravity="right" 
      android:background="#3A655F" 
      android:layout_alignParentRight="true" 
      android:layout_below="@+id/icon_level_7"/> 

    </com.layouts.Layout> 

Répondre

0

Mon correctif pour c'était une équation beaucoup plus simple.
J'ai utilisé le pivot central de chaque carré pour obtenir leur distance par rapport au centre, puis j'ai divisé la distance du centre par la hauteur de la disposition.

distFromCenter = (yTouch == 0) ? pivotY : Math.abs((pivotY - userYInput)); 
scale = (distFromCenter/layoutHieght); 
scale = scale == 0 ? 2 : 2 - scale. 

La proximité du centre, plus l'échelle, autrement son réduit, mais ne descend en dessous de 1.