2013-04-24 25 views
16

Sadece yazdığım bu kod parçasını paylaşmak istiyorum. Özel bir ürün etkinliği aramayı denedim, ancak bunların çoğu, özel ürün veya serbest ürün etkinliğine rağmen varsayılan "com.android.camera.action.CROP" adresine yönlendiriyor. Her neyse, kendim için bir tane yaptım ve umarım bu size yardımcı olacaktır.Özel Android Image Crop

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

Yaptığım şey, ImageView'ı genişletip, Kırpma güçlerini ekledim. Kullanımı oldukça kolaydır. Sınıf kaydedildikten sonra, sadece bu şekilde düzende kullanın.

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

Thats it! Umarım yardımcı olur! Eğer herhangi bir sorunla karşılaşırsanız, thehippo :)

+0

Yukarıdaki kodu kullandım, ancak kırpılan görüntü doğru şekilde alınmıyor, yakınlaştırılıyor. – Santosh

+0

Aynı sorun, resmi dikdörtgenin sınırları içinde kırpmaz. Bazılarını nasıl yakınlaştırır. @Hippo cevap hala aynı sorunu denedim. – Hasham

+0

ama bu kodu <: id = "@ + id/image_preview" android: layout_width = "fill_parent" android layout_height = "match_parent"/"paket adı" .CropView android> koymak gerekir edildi Bu özel kırpıcıyı nasıl bir görüntü görüntüsü ile uyguladığınıza benziyorsunuz. ImageView'ı genişleten özel bir kırpıcı bulamıyorsunuz. Bununla birlikte, bir şey var, kırpma dikdörtgen ölçeğini daha kolay hale getirmenin bir yolunu buldunuz mu? – Matthew

cevap

2

Sen denemelisiniz:

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

(Sorunuza düzenleme Alındığı.)

+2

'b = (BitmapDrawable) BitmapDrawable.createFromPath (imageUri.getPath());' ın kullanımı nedir? – xmen

+0

@theHippo Etkinliğimde nasıl kullanabilirim? – Matthew

0

sayesinde sormaya çekinmeyin ... ama düzen

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

tarafından görünümü bulma çözdük ama şimdi dokunma olayını işleyemez lütfen . Dikdörtgen hala ekrana dokunduğumda bile kalsın ...

DÜZENLEME: tamam, işe yaradı. Ama şimdi, dikdörtgen tüm görüntüde değil, sadece daha küçük bir alan içinde hareket eder. Ben iş kodu yapmak için küçük bir değişiklik yaptık

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

burada yanlış bir şeyler olduğunu varsayalım: yerine getDrawable

ait getBackground()

DÜZENLEME 2: Tamam ive, i bu yaptığını gördü yanlış yol. Kodun iyi. Görüntüyü ayarlamak için view.setImageDrawable() yerine view.seBackground() ... kullanıyordum. Şimdi her şey çalışıyor. o dikdörtgenin ölçeklendirme ateşler daha büyük bir alanı oluşturmak mümkündür Belki ben sadece kontrol edecek

+0

hi @ Vahn84! Üzgünüm kodu ile karıştı var. Sorunu nasıl düzelttin? Konu içinde kayboldu. Ayrıca @TheHippo için teşekkürler Bence cevabını görüntüyü yerleştirmenin en iyi yolu olduğunu düşünüyorum –

+1

Bunu çalıştıran herkes üzerinde son kodu ve yolu düzenleyebilir mi? – Hasham

+0

Hi! Code TheHippo tarafından yayınlandı Eserleri! Yanlış şekilde yapıyordum! – Vahn84

0

I Bunu destekleyen bir kütüphane buldu: SimpleCropView, https://android-arsenal.com/details/1/2366. Genel olarak, bunu tavsiye etmem, performansı yerli android kırpma uygulamaları uzaktır.

bunu kullanarak denedim ve düşüncelerim şunlardır:

  • uygulamanızda uygulamak Gerçekten basit

    , kırpma ve döndürme işlevi Mevcut uygulama ile çalışan almak için yaklaşık 5 dakika götürdü

  • Kırpma alanının yeniden boyutlandırılması çok yavaş, kullanıcının görmesini istemem.

GÜNCELLEME: Aslında buldum Github jdamcd/android-ürün olarak gerçekten iyi bir çözüm: https://github.com/jdamcd/android-crop Özet:

  • Çok basit

    uygulamanızda kullanmak

  • istersen bu

  • Özelleştirilebilir yerli galeri uygulamasından kodu kullandığından,

  • Hızlı onunla oynamak için biraz zaman harcamak. Varsayılan olarak, kırpma işlemini gerçekleştirdiğiniz bir Etkinlik sağlar. Eğer kendi aktivitenize entegre etmek istiyorsanız biraz zaman alacaktır. (Projem için onu entegre etmeyi çok isterdim ve gelecekte yapacağım, ancak şimdilik ayrı bir etkinlik yeterlidir).

Bu biraz bilgi sağlar.