2013-04-24 43 views
16

我只想分享我寫的這段代碼。我嘗試搜索自定義作物活動,但大多數都會導致默認的「com.android.camera.action.CROP」,儘管存在自定義作物問題或徒手作物活動。無論如何,我只爲自己做了一件,希望它能幫助你們。自定義Android圖像作物

public class CropView extends ImageView { 

    Paint paint = new Paint(); 
    private int initial_size = 300; 
    private static Point leftTop, rightBottom, center, previous; 

    private static final int DRAG= 0; 
    private static final int LEFT= 1; 
    private static final int TOP= 2; 
    private static final int RIGHT= 3; 
    private static final int BOTTOM= 4; 

    private int imageScaledWidth,imageScaledHeight; 
    // Adding parent class constructors 
    public CropView(Context context) { 
     super(context); 
     initCropView(); 
    } 

    public CropView(Context context, AttributeSet attrs) { 
     super(context, attrs, 0); 
     initCropView(); 
    } 

    public CropView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     initCropView(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     super.onDraw(canvas); 
     if(leftTop.equals(0, 0)) 
      resetPoints(); 
     canvas.drawRect(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, paint); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     int eventaction = event.getAction(); 
     switch (eventaction) { 
      case MotionEvent.ACTION_DOWN: 
       previous.set((int)event.getX(), (int)event.getY()); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       if(isActionInsideRectangle(event.getX(), event.getY())) { 
        adjustRectangle((int)event.getX(), (int)event.getY()); 
        invalidate(); // redraw rectangle 
        previous.set((int)event.getX(), (int)event.getY()); 
       } 
       break; 
      case MotionEvent.ACTION_UP: 
       previous = new Point(); 
       break; 
     }   
     return true; 
    } 

    private void initCropView() { 
     paint.setColor(Color.YELLOW); 
     paint.setStyle(Style.STROKE); 
     paint.setStrokeWidth(5); 
     leftTop = new Point(); 
     rightBottom = new Point(); 
     center = new Point(); 
     previous = new Point(); 
    } 

    public void resetPoints() { 
     center.set(getWidth()/2, getHeight()/2); 
     leftTop.set((getWidth()-initial_size)/2,(getHeight()-initial_size)/2); 
     rightBottom.set(leftTop.x+initial_size, leftTop.y+initial_size); 
    } 

    private static boolean isActionInsideRectangle(float x, float y) { 
     int buffer = 10; 
     return (x>=(leftTop.x-buffer)&&x<=(rightBottom.x+buffer)&& y>=(leftTop.y-buffer)&&y<=(rightBottom.y+buffer))?true:false; 
    } 

    private boolean isInImageRange(PointF point) { 
     // Get image matrix values and place them in an array 
     float[] f = new float[9]; 
     getImageMatrix().getValues(f); 

     // Calculate the scaled dimensions 
     imageScaledWidth = Math.round(getDrawable().getIntrinsicWidth() * f[Matrix.MSCALE_X]); 
     imageScaledHeight = Math.round(getDrawable().getIntrinsicHeight() * f[Matrix.MSCALE_Y]); 

     return (point.x>=(center.x-(imageScaledWidth/2))&&point.x<=(center.x+(imageScaledWidth/2))&&point.y>=(center.y-(imageScaledHeight/2))&&point.y<=(center.y+(imageScaledHeight/2)))?true:false; 
    } 

    private void adjustRectangle(int x, int y) { 
     int movement; 
     switch(getAffectedSide(x,y)) { 
      case LEFT: 
       movement = x-leftTop.x; 
       if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement))) 
        leftTop.set(leftTop.x+movement,leftTop.y+movement); 
       break; 
      case TOP: 
       movement = y-leftTop.y; 
       if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movement))) 
        leftTop.set(leftTop.x+movement,leftTop.y+movement); 
       break; 
      case RIGHT: 
       movement = x-rightBottom.x; 
       if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement))) 
        rightBottom.set(rightBottom.x+movement,rightBottom.y+movement); 
       break; 
      case BOTTOM: 
       movement = y-rightBottom.y; 
       if(isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movement))) 
        rightBottom.set(rightBottom.x+movement,rightBottom.y+movement); 
       break;  
      case DRAG: 
       movement = x-previous.x; 
       int movementY = y-previous.y; 
       if(isInImageRange(new PointF(leftTop.x+movement,leftTop.y+movementY)) && isInImageRange(new PointF(rightBottom.x+movement,rightBottom.y+movementY))) { 
        leftTop.set(leftTop.x+movement,leftTop.y+movementY); 
        rightBottom.set(rightBottom.x+movement,rightBottom.y+movementY); 
       } 
       break; 
     } 
    } 

    private static int getAffectedSide(float x, float y) { 
     int buffer = 10; 
     if(x>=(leftTop.x-buffer)&&x<=(leftTop.x+buffer)) 
      return LEFT; 
     else if(y>=(leftTop.y-buffer)&&y<=(leftTop.y+buffer)) 
      return TOP; 
     else if(x>=(rightBottom.x-buffer)&&x<=(rightBottom.x+buffer)) 
      return RIGHT; 
     else if(y>=(rightBottom.y-buffer)&&y<=(rightBottom.y+buffer)) 
      return BOTTOM; 
     else 
      return DRAG; 
    } 

    public byte[] getCroppedImage() { 
     BitmapDrawable drawable = (BitmapDrawable)getDrawable(); 
     float x = leftTop.x-center.x+(drawable.getBitmap().getWidth()/2); 
     float y = leftTop.y-center.y+(drawable.getBitmap().getHeight()/2); 
     Bitmap cropped = Bitmap.createBitmap(drawable.getBitmap(),(int)x,(int)y,(int)rightBottom.x-(int)leftTop.x,(int)rightBottom.y-(int)leftTop.y); 
     ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
     cropped.compress(Bitmap.CompressFormat.PNG, 100, stream); 
     return stream.toByteArray(); 
    } 
} 

我做的是,我擴展了ImageView並添加了裁剪權力。這很容易使用。一旦這個類被保存了,就在這樣的佈局中使用它。

<"your package name".CropView 
     android:id="@+id/image_preview" 
     android:layout_width="fill_parent" 
     android:layout_height="match_parent" /> 

那就是它!希望能幫助到你!如果您遇到任何問題,請隨時thehippo問:)

+0

我使用了上面的代碼,但裁剪後的圖像沒有正確顯示,它變得越來越窄。 – Santosh 2013-07-10 06:58:20

+0

同樣的問題,它不會裁剪矩形邊界內的圖像。它放大了一些方法。我試過@TheHippo的答案仍然是同樣的問題。 – Hasham 2013-12-24 10:15:04

+0

但被我應該把這個代碼 < 「你的包名」 .CropView 機器人:ID = 「@ + ID/image_preview」 的android:layout_width = 「FILL_PARENT」 機器人:layout_height = 「match_parent」/> – Matthew 2014-02-12 14:43:12

回答

2

你應該嘗試:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.crop_layout); 


    myCropView = new CropView(this); 

    Uri imageUri = getIntent().getExtras().getParcelable("path"); 

    b = (BitmapDrawable) BitmapDrawable.createFromPath(imageUri.getPath()); 

    myCropView.setImageURI(imageUri); 
} 

(從編輯帶到你的問題。)

+2

什麼使用'b =(BitmapDrawable)BitmapDrawable.createFromPath(imageUri.getPath());'?? – xmen 2013-06-27 11:55:46

+0

@theHippo我如何使用我的活動 – Matthew 2014-02-12 13:58:01

0

感謝...但我已經解決了佈局

Uri imageUri = getIntent().getExtras().getParcelable("path"); 
    b = (BitmapDrawable) BitmapDrawable.createFromPath(getRealPathFromURI(imageUri)); 
    myCropView = (CropView) findViewById(R.id.image_preview); 
    myCropView.setBackground(b); 

找到看法,但現在我不能處理觸摸事件。矩形留下來,即使我觸摸屏幕...

編輯:好的,我已經使它的工作。但是現在,矩形只在較小的區域內移動,而不是在整個圖像中移動。我想有什麼東西錯在這裏

private boolean isInImageRange(PointF point) { 
    // Get image matrix values and place them in an array 
    float[] f = new float[9]; 
    getImageMatrix().getValues(f); 

    // Calculate the scaled dimensions 
    imageScaledWidth = Math.round(getBackground().getIntrinsicWidth() * f[Matrix.MSCALE_X]); 
    imageScaledHeight = Math.round(getBackground().getIntrinsicHeight() * f[Matrix.MSCALE_Y]); 

    return (point.x>=(center.x-(imageScaledWidth/2))&&point.x<=(center.x+(imageScaledWidth/2))&&point.y>=(center.y-(imageScaledHeight/2))&&point.y<=(center.y+(imageScaledHeight/2)))?true:false; 
} 

我已經做了一些改變,以使工作代碼:),而不是getDrawable

的getBackground(

編輯2:OK Ive得到了它,我在做這個錯誤的方法。你的代碼很好。要設置圖像我使用view.seBackground()...而不是view.setImageDrawable()。現在一切正常。也許我會只檢查是否有可能創建一個觸發矩形的比例較大面積

+0

hi @ Vahn84!對不起,我讓你感到困惑與代碼。你是如何解決你的問題的?我迷失在線程中。還要感謝@TheHippo for the我認爲他的回答是設置圖像的最佳方式 – 2013-05-24 14:40:49

+1

任何能讓它工作的人都可以編輯最後的代碼和上面的方式 – Hasham 2013-12-24 10:56:17

+0

Hi!代碼發表由TheHippo作品!這是我以錯誤的方式做的! – Vahn84 2014-02-18 10:04:11

0

我發現一個支持這個庫:SimpleCropView從https://android-arsenal.com/details/1/2366。一般來說,我不會推薦它,它的性能遠不是原生的android裁剪應用程序。

我一直在使用它試圖和我的想法是:

  • 在你的應用程序來實現真正簡單,我花了大約5分鐘就可以裁剪和旋轉的功能與我現有的應用程序工作

  • 作物區域的重新調整速度非常緩慢,我不希望我的用戶看到它。

UPDATE: 其實,我已經找到一個很好的解決方案,在Github上jdamcd/Android的作物:https://github.com/jdamcd/android-crop 摘要:

  • 很簡單,在你的應用程序使用

  • 快速,因爲它使用的是本地圖庫應用程序的代碼

  • 可自定義,如果您想要花一些時間玩它。默認情況下,它爲您提供了裁剪的地方。如果你想把它整合到你自己的活動中,它將需要一些時間。 (對於我的項目,我希望整合它,並且將來會做,但現在單獨的活動就足夠了)。

希望這能提供一些見解!