2012-09-01 18 views
7

W mojej aplikacji na Androida mam obraz kadrowania. Tak więc programuję widok niestandardowy jako moje pole przycinania. Mogę przesunąć pole przycinania. Ale moim problemem jest to, w jaki sposób mogę przeciągnąć granicę pola przycinania i zmienić jego szerokość i wysokość. Jak mogę to zrobić?Zmień niestandardowy widok Szerokość i wysokość w systemie Android

Attr Klasa:

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

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

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

} 

Układ 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> 

Przed Resize:

enter image description here

Po Resize:

enter image description here

Dzięki za pomoc.

+0

Dlaczego zadeklarowałeś swoje atrybuty jako 'final'. Jeśli chcesz je zmienić, czy nie powinieneś deklarować, że nie są ostateczne? –

+0

Tak, masz rację. Muszę oświadczyć, że nie są ostateczne. Ale nie wiem, jak mogę je zmienić. –

Odpowiedz

2

Po to rozwiązanie,

Modified onCreate z działalności

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

Modified klasę 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; 
     } 
    } 
} 

Niektóre punkty chciałbym wspomnieć.

  • Połączony Attr i Crop w CropBox
  • Nie ma potrzeby tworzenia prostokąt z liniami. Możesz użyć Rect.
  • Nigdy zainicjować tablicę/przedmiot w metodzie Draw
  • dodał cechę: jeśli dwukrotnie poruszył prostokąta powraca do pierwotnego położenia
  • nie mogą być pewne zaczepy o ograniczenie rect w ImageView. Jestem pewien, że można naprawić te ... :)

Inne niż to jest inny ciekawy sposób stosując skalowanie płótnie Image in Canvas with touch events Użyj tej klasy zamiast CropBox i spróbować.

Mam nadzieję, że pomaga ..

+0

Bardzo dziękuję za pomoc: D –

+0

przenoszenie granic działa naprawdę świetnie, ale jak mogę przyciąć obraz? Muszę zapisać go w pamięci. – Ragaisis

Powiązane problemy