android - 如何限制android中图像的最小可裁剪尺寸

标签 android image android-layout android-intent crop

关于如何裁剪从 Gallery 或 Camera 中获取的图像,有很多讨论。一个非常简单的,没有多少人喜欢,包括以下 fragment

intent.putExtra("crop", "true");
intent.putExtra("aspectX", 617);
intent.putExtra("aspectY", 619);

(无论如何,该 fragment 是不完整的。继续......)

请注意我在代码 fragment 中如何使用两个大质数。我在这里希望限制最小裁剪尺寸。然而,617X619 似乎没有效果;这对我来说基本上意味着无论使用什么算法都具有类似于

的功能
double scale =  (double) aspectY/aspectX;

然后用于将 xDimen 与 yDimen 进行匹配。

但在我举手放弃之前,我注意到 instagram 已经成功地限制了 cropper 的最小尺寸。有谁知道我如何做到这一点?基本上,如果您使用 instagram,您会注意到您无法裁剪图像的“太小”部分。我该如何决定这些维度?

基本上就好像instagram在做

  double scale =  (double) aspectY/aspectX;
  //....
  if(someInputX > aspectX){
    xDimen = someInputX;
    yDimen = scale* xDimen;
  }else{
    //do not crop any further
  }

我一直在查看一些裁剪库,看看是否可以弄清楚如何修复最小尺寸,但我似乎无法弄清楚。例如,我一直在研究 http://commonsware.com/blog/2013/01/23/no-android-does-not-have-crop-intent.html 链接的 git 项目。

最佳答案

Instagram 已经构建了自己的裁剪工具。如果您准备好构建裁剪工具,您可以控制任何东西。而且,构建一个简单的裁剪工具并不难。如果您对 MotionEventBitmap 的工作原理有很好的理解,那么 1 小时就够了。

示例代码:取自 here

public class MainActivity extends Activity {
private ImageView imageView;
private ViewManager viewManager;
private Matrix matrix;
private int size;
private final int outputSize = 100;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Display display = getWindowManager().getDefaultDisplay();
    int width = display.getWidth();
    int height = display.getHeight();
    size = width < height ? width : height;
    size -= 50;

    imageView = (ImageView) findViewById(R.id.imageViewCrop);
    imageView.getLayoutParams().width = size;
    imageView.getLayoutParams().height = size;
    viewManager = (ViewManager) imageView.getParent();

    if (getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) {
        createZoomControls();
    }

    imageView.setOnTouchListener(new OnTouchListener() {
        float initX;
        float initY;
        float midX;
        float midY;
        float scale;
        float initDistance;
        float currentDistance;
        boolean isMultitouch = false;

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                initX = event.getX();
                initY = event.getY();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                isMultitouch = true;
                initDistance = (float) Math.sqrt(Math.pow(
                        initX - event.getX(1), 2)
                        + Math.pow(initY - event.getY(1), 2));
                break;
            case MotionEvent.ACTION_MOVE:
                if (isMultitouch) {
                    matrix = imageView.getImageMatrix();
                    currentDistance = (float) Math.sqrt(Math.pow(initX
                            - event.getX(1), 2)
                            + Math.pow(initY - event.getY(1), 2));
                    scale = 1 + 0.001f * (currentDistance - initDistance);
                    midX = 0.5f * (initX + event.getX(1));
                    midY = 0.5f * (initY + event.getY(1));
                    matrix.postScale(scale, scale, midX, midY);
                    imageView.setImageMatrix(matrix);
                    imageView.invalidate();
                } else {
                    imageView.scrollBy((int) (initX - event.getX()),
                            (int) (initY - event.getY()));
                    initX = event.getX();
                    initY = event.getY();
                }
                break;
            case MotionEvent.ACTION_UP:
                isMultitouch = false;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                isMultitouch = false;
                break;
            }
            return true;
        }
    });
}

public void createZoomControls() {
    ZoomButtonsController zoomButtonsController = new ZoomButtonsController(
            imageView);
    zoomButtonsController.setVisible(true);
    zoomButtonsController.setAutoDismissed(false);
    zoomButtonsController.setOnZoomListener(new OnZoomListener() {

        public void onZoom(boolean zoomIn) {
            matrix = imageView.getImageMatrix();
            if (zoomIn) {
                matrix.postScale(1.05f, 1.05f, 0.5f * size, 0.5f * size);
                imageView.setImageMatrix(matrix);
            } else {
                matrix.postScale(0.95f, 0.95f, 0.5f * size, 0.5f * size);
                imageView.setImageMatrix(matrix);
            }
            imageView.invalidate();
        }

        public void onVisibilityChanged(boolean visible) {
        }
    });
    RelativeLayout.LayoutParams zoomLayoutParams = new RelativeLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    zoomLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
    zoomLayoutParams.addRule(RelativeLayout.BELOW, R.id.imageViewCrop);
    viewManager.addView(zoomButtonsController.getContainer(),
            zoomLayoutParams);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    Toast.makeText(this, R.string.info, 5).show();
    return super.onMenuItemSelected(featureId, item);
}

public void buttonPickClick(View view) {
    Intent intent = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (resultCode) {
    case RESULT_OK:
        Uri targetUri = data.getData();
        imageView.setScaleType(ScaleType.CENTER_INSIDE);
        imageView.scrollTo(0, 0);
        imageView.setImageURI(targetUri);
        imageView.setScaleType(ScaleType.MATRIX);
        break;
    }
}

public void buttonCropClick(View view) throws IOException {
    imageView.setDrawingCacheEnabled(true);
    imageView.buildDrawingCache(true);
    File imageFile = new File(Environment.getExternalStorageDirectory(),
            "Pictures/" + UUID.randomUUID().toString() + ".jpg");
    FileOutputStream fileOutputStream = new FileOutputStream(imageFile);
    Bitmap.createScaledBitmap(imageView.getDrawingCache(true), outputSize,
            outputSize, false).compress(CompressFormat.JPEG, 100,
            fileOutputStream);
    fileOutputStream.close();
    imageView.setDrawingCacheEnabled(false);
}
}

处理高分辨率图像时要小心 http://developer.android.com/training/displaying-bitmaps/index.html

关于android - 如何限制android中图像的最小可裁剪尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24024472/

相关文章:

ios - 是否真的有必要为 iOS 应用程序提供所有不同的应用程序图标大小?

javascript - bxSlider onAfterSlide 回调

c# - 亚马逊 MWS API :Retrieve multiple Images uploaded by Seller c#

android - getMeasuredWidth 返回完全错误的值

java - 以编程方式将 TextView 添加到 LinearLayout 时不出现

Android 无法将 "id"发送到此 php

android - 如何使用列表中的自定义按钮将用户重定向到另一个 Activity

android - 如何以编程方式在 Android 上发出点击事件

android - 没有启用 "Auto-Rotate Screen"就不能使用反向纵向

android - 使用 LinearLayout 代替 FrameLayout 可以吗?