2012-09-01 32 views
7

En mi aplicación de Android, tengo una imagen de recorte. Entonces, estoy programando una vista personalizada como mi cuadro de recorte. Puedo mover el cuadro de recorte. Pero mi problema es cómo puedo arrastrar el borde del cuadro de recorte y cambiar su ancho y alto. ¿Cómo puedo hacerlo?Cambiar el ancho y la altura de vista personalizada en Android

Attr Clase:

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 Clase:

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 Clase: Clase

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)); 
    } 

} 

Cultivo:

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; 
    } 

} 

diseño xml:

<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> 

Antes de cambio de tamaño:

enter image description here

Después de cambio de tamaño:

enter image description here

Gracias por su ayuda.

+0

¿Por qué declaraste tus atributos como 'final'. Si desea cambiarlos, ¿no debería declarar que no es definitivo? –

+0

Sí, tienes razón. Debo declarar que no son definitivas. Pero no sé cómo puedo redimensionarlos. –

Respuesta

2

A continuación se presenta la solución,

Modified onCreate de la Actividad

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); 
} 

Modificado clase 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; 
     } 
    } 
} 

Algunos puntos que me gustaría mencionar.

  • combinada Attr y cultivos en CropBox
  • No hay necesidad de crear un rectángulo de líneas. Puede usar Rect.
  • Nunca inicializar una matriz/objeto en el método Draw
  • ha añadido una función: si el doble tocado rectángulo vuelve a su posición original
  • que podría haber algunos tirones sobre la restricción de la rect en imageview. Estoy seguro de que puede arreglar los ... :)

Aparte de esto no es otra forma interesante utilizando la escala de lona Image in Canvas with touch events utilizar esa clase en lugar de CropBox y probarlo.

Espero que ayude ..

+0

Muchas gracias por su ayuda: D –

+0

mover bordes funciona realmente bien, pero ¿cómo puedo recortar la imagen? Necesito guardarlo en el almacenamiento. – Ragaisis

Cuestiones relacionadas