2012-09-01 20 views
7

Nella mia app Android, ho un'immagine di ritaglio. Quindi, sto programmando una visualizzazione personalizzata come la mia casella di ritaglio. Posso spostare la casella di ritaglio. Ma il mio problema è come posso trascinare il bordo della casella di ritaglio e modificare la larghezza e l'altezza di esso. Come posso farlo?Cambia la larghezza e l'altezza della vista personalizzata in Android

Attr Classe:

public class Attr { 

    public static final float CROP_BOX_START_X = 5; 
    public static final float CROP_BOX_START_Y = 5; 
    public static final float CROP_BOX_END_X = 305; 
    public static final float CROP_BOX_END_Y = 105; 

} 

CropBox Classe:

public class CropBox extends View { 

    private Paint paint = new Paint(); 


    public CropBox(Context context) { 
     super(context); 
    } 

    public CropBox(Context context, AttributeSet attributeSet) { 
     super(context, attributeSet); 
    } 


    @Override 
    public void onDraw(Canvas canvas) { 
     float[][] circleXY = { 
      {Attr.CROP_BOX_START_X, Attr.CROP_BOX_START_Y}, 
      {(Attr.CROP_BOX_START_X + Attr.CROP_BOX_END_X)/2, Attr.CROP_BOX_START_Y}, 
      {Attr.CROP_BOX_END_X, Attr.CROP_BOX_START_Y}, 
      {Attr.CROP_BOX_START_X, Attr.CROP_BOX_END_Y}, 
      {(Attr.CROP_BOX_START_X + Attr.CROP_BOX_END_X)/2, Attr.CROP_BOX_END_Y}, 
      {Attr.CROP_BOX_END_X, Attr.CROP_BOX_END_Y}, 
      {Attr.CROP_BOX_START_X, (Attr.CROP_BOX_START_Y + Attr.CROP_BOX_END_Y)/2}, 
      {Attr.CROP_BOX_END_X, (Attr.CROP_BOX_START_Y + Attr.CROP_BOX_END_Y)/2} 
     }; 
     float[][] lineXY = { 
      {Attr.CROP_BOX_START_X, Attr.CROP_BOX_START_Y, Attr.CROP_BOX_END_X, Attr.CROP_BOX_START_Y}, 
      {Attr.CROP_BOX_START_X, Attr.CROP_BOX_END_Y, Attr.CROP_BOX_END_X, Attr.CROP_BOX_END_Y}, 
      {Attr.CROP_BOX_START_X, Attr.CROP_BOX_START_Y, Attr.CROP_BOX_START_X, Attr.CROP_BOX_END_Y}, 
      {Attr.CROP_BOX_END_X, Attr.CROP_BOX_START_Y, Attr.CROP_BOX_END_X, Attr.CROP_BOX_END_Y} 
     }; 

     paint.setColor(Color.CYAN); 
     paint.setStrokeWidth(1); 

     for(int i = 0 ; i < circleXY.length ; i++) 
      canvas.drawCircle(circleXY[i][0], circleXY[i][1], 5, paint); 

     paint.setStrokeWidth(2); 

     for(int i = 0 ; i < lineXY.length ; i++) 
      canvas.drawLine(lineXY[i][0], lineXY[i][2], lineXY[i][2], lineXY[i][3], paint); 
    } 

} 

CropTestActivity Classe: Classe

public class CropTestActivity extends Activity { 

    private ImageView imageView; 
    private CropBox cropBox; 
    private RelativeLayout relativeLayout; 
    private RelativeLayout.LayoutParams layoutParams; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.crop_test_layout); 
     imageView = (ImageView)findViewById(R.id.android_image); 
     cropBox = new CropBox(this); 
     relativeLayout = (RelativeLayout)findViewById(R.id.crop_test_layout); 
     layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT); 
     imageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
      public void onGlobalLayout() { 
       imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
       layoutParams.leftMargin = imageView.getWidth()/2 - (int)((Attr.CROP_BOX_START_X + Attr.CROP_BOX_END_X)/2) + imageView.getLeft(); 
       layoutParams.topMargin = imageView.getHeight()/2 - (int)((Attr.CROP_BOX_START_Y + Attr.CROP_BOX_END_Y)/2) + imageView.getTop(); 
      } 
     }); 
     relativeLayout.addView(cropBox, layoutParams); 
     cropBox.setOnTouchListener(new Crop(imageView)); 
    } 

} 

Crop:

public class Crop implements OnTouchListener { 

    private static final int NONE = 0; 
    private static final int BOX_DRAG = 1; 
    private static final int BORDER_DRAG = 2; 

    private int mode = NONE; 

    private float cropBoxStartX = Attr.CROP_BOX_START_X; 
    private float cropBoxStartY = Attr.CROP_BOX_START_Y; 
    private float cropBoxEndX = Attr.CROP_BOX_END_X; 
    private float cropBoxEndY = Attr.CROP_BOX_END_Y; 

    private ImageView imageView; 

    private PointF start = new PointF(); 


    public Crop(ImageView imageView) { 
     this.imageView = imageView; 
    } 


    public boolean onTouch(View view, MotionEvent event) { 
     RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); 

     switch(event.getAction() & MotionEvent.ACTION_MASK) { 

      case MotionEvent.ACTION_DOWN: 
       start.set(event.getX(), event.getY()); 
       if(event.getX() > cropBoxStartX && event.getX() < cropBoxEndX && event.getY() > cropBoxStartY && event.getY() < cropBoxEndY) 
        mode = BOX_DRAG; 
       else if(event.getX() == cropBoxStartX || event.getX() == cropBoxEndX || event.getY() == cropBoxStartY || event.getY() == cropBoxEndY) 
        mode = BORDER_DRAG; 
       else 
        mode = NONE; 
       break; 

      case MotionEvent.ACTION_UP: 
       mode = NONE; 
       break; 

      case MotionEvent.ACTION_MOVE: 
       if(mode == BOX_DRAG) { 
        layoutParams.leftMargin = (int)event.getX() - (int)start.x + view.getLeft(); 
        layoutParams.topMargin = (int)event.getY() - (int)start.y + view.getTop(); 
        while(layoutParams.topMargin + 5 < imageView.getTop()) 
         layoutParams.topMargin++; 
        while(layoutParams.leftMargin + (cropBoxEndX - cropBoxStartX + 5) > imageView.getRight()) 
         layoutParams.leftMargin--; 
        while(layoutParams.topMargin + (cropBoxEndY - cropBoxStartY + 5) > imageView.getBottom()) 
         layoutParams.topMargin--; 
        while(layoutParams.leftMargin + 5 < imageView.getLeft()) 
         layoutParams.leftMargin++; 
       } 
       else if(mode == BORDER_DRAG) { 
       } 
       break; 
     } 
     view.setLayoutParams(layoutParams); 
     return true; 
    } 

} 
XML

Disposizione:

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/crop_test_layout" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 

    <ImageView 
     android:id="@+id/android_image" 
     android:src="@drawable/android" 
     android:layout_width="fill_parent" 
     android:layout_height="300dp" 
     android:layout_marginTop="10dp" 
     android:layout_marginRight="10dp" 
     android:layout_marginBottom="10dp" 
     android:layout_marginLeft="10dp" 
     android:layout_gravity="center" 
     android:scaleType="fitXY" 
     android:contentDescription="@string/android_image_description" > 
    </ImageView> 

</RelativeLayout> 

Prima Ridimensiona:

enter image description here

Dopo ridimensionamento:

enter image description here

Grazie per il vostro aiuto.

+0

Perché hai dichiarato i tuoi attributi come "finale". Se vuoi cambiarli, non dovresti dichiararlo come non definitivo? –

+0

Sì, hai ragione. Devo dichiararli non definitivi. Ma non so come posso ridimensionarli. –

risposta

2

In seguito è la soluzione,

Modificato onCreate da Activity

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.crop_test_layout); 
    imageView = (ImageView)findViewById(R.id.android_image); 
    cropBox = new CropBox(this, imageView); 
    relativeLayout = (RelativeLayout)findViewById(R.id.crop_test_layout); 
    relativeLayout.addView(cropBox); 
} 

Modificato classe CropBox:

public class CropBox extends View { 

    private static final int CROP_BOX_START_X = 5; 
    private static final int CROP_BOX_START_Y = 5; 
    private static final int CROP_BOX_END_X = 305; 
    private static final int CROP_BOX_END_Y = 105; 

    private static final int DRAG_SQUARE = 75; 

    public ImageView mImageView; 
    boolean mIsFirstClick = false; 

    private Paint paint = new Paint(); 
    private Rect mRect; 

    public CropBox(Context context, ImageView aBaseView) { 
     super(context); 
     mImageView = aBaseView; 
     mRect = new Rect(CROP_BOX_START_X, CROP_BOX_START_Y, CROP_BOX_END_X, CROP_BOX_END_Y); 
     setOnTouchListener(new Crop()); 
    } 

    public CropBox(Context context, AttributeSet attributeSet) { 
     super(context, attributeSet); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 

     paint.setStrokeWidth(2); 

     paint.setColor(Color.CYAN); 
     paint.setStyle(Paint.Style.STROKE); 

     canvas.drawRect(mRect, paint); 

     canvas.drawLine(mRect.right-DRAG_SQUARE, mRect.bottom-DRAG_SQUARE, 
       mRect.right, mRect.bottom-DRAG_SQUARE, paint); 

     canvas.drawLine(mRect.right-DRAG_SQUARE, mRect.bottom-DRAG_SQUARE, 
       mRect.right-DRAG_SQUARE, mRect.bottom, paint); 
    } 

    class Crop implements OnTouchListener { 

     private static final int NONE = 0; 
     private static final int BOX_DRAG = 1; 
     private static final int BORDER_DRAG = 2; 

     private int mode = NONE; 

     private PointF start = new PointF(); 

     public boolean onTouch(View view, MotionEvent event) { 
      RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)view.getLayoutParams(); 

      switch(event.getAction() & MotionEvent.ACTION_MASK) { 

       case MotionEvent.ACTION_DOWN: 
        start.set(event.getX(), event.getY()); 

        if((event.getX() <= mRect.right && event.getX() >=(mRect.right - DRAG_SQUARE)) 
          && (event.getY() >= mRect.top && event.getY() >=(mRect.bottom - DRAG_SQUARE))){ 
         mode = BORDER_DRAG; 
         mIsFirstClick = false; 
        } 
        else if(mRect.contains((int)event.getX(), (int)event.getY())) { 
         mode = BOX_DRAG; 
         if (mIsFirstClick){ 
          mRect = new Rect(CROP_BOX_START_X, CROP_BOX_START_Y, 
            CROP_BOX_END_X, CROP_BOX_END_Y); 
          mIsFirstClick = false; 
         } else { 
          mIsFirstClick = true; 
         } 
        } 
        else{ 
         mode = NONE; 
         mIsFirstClick = true; 
        } 
        break; 

       case MotionEvent.ACTION_UP: 
        mode = NONE; 
        break; 

       case MotionEvent.ACTION_MOVE: 
        mIsFirstClick = false; 
        if(mode == BOX_DRAG) { 
         layoutParams.leftMargin = (int)event.getX() - (int)start.x + view.getLeft(); 
         layoutParams.topMargin = (int)event.getY() - (int)start.y + view.getTop(); 
        } 
        else if(mode == BORDER_DRAG) { 
         if (event.getX() > view.getLeft() && event.getY() > view.getTop()){ 
          mRect.right = (int) event.getX(); 
          mRect.bottom = (int) event.getY(); 
         } 
        } 
        while(layoutParams.topMargin + 5 < mImageView.getTop()) 
         layoutParams.topMargin++; 
        while(layoutParams.leftMargin + mRect.right > mImageView.getRight()) 
         layoutParams.leftMargin--; 
        while(layoutParams.topMargin + mRect.bottom > mImageView.getBottom()) 
         layoutParams.topMargin--; 
        while(layoutParams.leftMargin + 5 < mImageView.getLeft()) 
         layoutParams.leftMargin++; 
        break; 
      } 
      view.setLayoutParams(layoutParams); 
      invalidate(); 
      return true; 
     } 
    } 
} 

Alcuni punti mi piacerebbe parlare.

  • unita Attr e raccolto in CropBox
  • Non c'è bisogno di creare un rettangolo dalle linee. È possibile utilizzare Rect.
  • Mai inizializzare un array/oggetto in metodo Draw
  • Aggiunta una funzione: se doppia toccato il rettangolo si ritorna alla posizione originale
  • ci potrebbe essere qualche intoppi circa la limitazione del rect in ImageView. Sono sicuro che si può risolvere quelli ... :)

Oltre a questo c'è un altro modo interessante con il ridimensionamento di tela Image in Canvas with touch events Utilizzare quella classe, invece di CropBox e provarlo.

Spero che sia utile ..

+0

Grazie mille per il tuo aiuto: D –

+0

i bordi mobili funzionano davvero alla grande, ma come posso ritagliare l'immagine? Devo salvarlo nella memoria. – Ragaisis

Problemi correlati