安卓 - 拖拽和裁剪问题

8
我正在尝试对一个位于ImageView中的图片进行简单的照片处理,该视图在平均情况下具有200dp的高度,并与其父视图的宽度匹配。
我已经实现了一个自定义的onTouchListener类,它创建了一个matrix并在ImageView内移动图像。 拖动:
case MotionEvent.ACTION_MOVE:
     if (mode == DRAG) {
        matrix.set(savedMatrix);
        matrix.postTranslate(v.getX(), event.getY() - start.y);
     }
     break;

这个功能完美地工作,它只在y轴上拖动图像。但是当用户释放时,我希望图像会裁剪到可见的ImageView区域的边界。

裁剪

case MotionEvent.ACTION_UP:
     if (mode == DRAG) {
        Bitmap bitmap = drawableToBitmap(view.getDrawable());
        Bitmap result = Bitmap.createBitmap(bitmap,view.getLeft(), view.getTop(), view.getWidth(), view.getHeight());
        view.setImageBitmap(result);
      }
      break;

这个代码裁剪了图片到正确的大小,但仅限于从ImageView的背景顶部而不是可见边界。通过调用Bitmap类函数createBitmap(int x, int y, int width, int height),我唯一的假设就是view.getTop()使它从顶部开始。

因此,我的问题是:如何计算可见视图边界和背景/矩阵边界之间的差异?

The dark blue area is the ImageView

注意: 图片显示一个位于Activity顶部的图片(蓝色),青色区域只是ImageView的背景透明边界而不是Activity本身的边界。

我想强调的是,我不希望使用任何第三方库来实现这个功能。

如果需要,我可以提供更多的代码。

更新:

完整的onTouch方法:

@Override
public boolean onTouch(View v, MotionEvent event) {
    ImageView view = (ImageView) v;
    // Dump touch event to log
    dumpEvent(event);

    // Handle touch events here...
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            start.set(v.getX(), event.getY());
            mode = DRAG;
            originalY.y = (int) event.getY();
            break;
        case MotionEvent.ACTION_UP:
             if (mode == DRAG) {
        Bitmap bitmap = drawableToBitmap(view.getDrawable());
        Bitmap result = Bitmap.createBitmap(bitmap,view.getLeft(), view.getTop(), view.getWidth(), view.getHeight());
        view.setImageBitmap(result);
      }
      break;
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                matrix.set(savedMatrix);
                matrix.postTranslate(v.getX(), event.getY() - start.y);
            }
            break;
    }
    view.setImageMatrix(matrix);
    return true; // indicate event was handled
}

在你的屏幕截图中,你设置了任何位图作为整个屏幕的背景,或者你设置了任何高度?我知道你已经放置了200dp,但我认为它是可见图像的区域,在按钮点击时应该进行裁剪。因此,如果你提供实际图像的屏幕信息给我,我一定会帮助你。 - Chetan Joshi
ImageView 中的图像将被裁剪到屏幕宽度,并保持基于此裁剪的高度比例(正常比例裁剪),然后用户可以拖动原始图像提供的高度空间。它可以是任何图像(最小适合屏幕宽度即可)。这种情况下唯一固定的是 ImageView 的高度,矩阵大小是动态的,这意味着矩阵顶部与 ImageView 顶部之间的距离也是动态的。 - Bradley Wilson
2个回答

0
代码缺少一些上下文,但我假设当用户开始拖动时,您会创建新的“savedMatrix”和“start”点,并在每次onTouchListener被调用时更新它们,否则我根本不理解您的代码是如何工作的。
如果是这样,那么这意味着您实际上已经在“savedMatrix”中拥有所需的转换,为什么不直接从那里获取呢?我认为您需要的是类似于以下内容的东西。
int top = savedMatrix.getValues()[Matrix.MTRANS_Y]

我还没有检查过它,也不太了解Matrix的内部结构,所以你可能需要反转top的符号。

顺便提一下:在matrix.postTranslate(v.getX(), event.getY() - start.y);中为什么要传递v.getX()并不清楚。可能只是因为在你的情况下v.getX()始终为0而已。


0

为了计算Activity的根高度,我们可以使用

int height = this.getWindow().getDecorView().getHeight();

或者您可以使用显示度量。

DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;

或者添加一个全局布局监听器

ViewTreeObserver vtObserver = view.getViewTreeObserver();
vtObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
    // check if the view's height and/or width > 0
    // don't forget to remove the listener when done using removeOnGlobalLayoutListener
}

});


请重新阅读问题。我正在寻找可见ImageView区域(蓝色)之间的边界(以及该可见区域顶部到背景/矩阵边界(青色)的边界值)。在ImageView下面的Activity中将有大量小部件,因此获取Activity的高度是多余的。 - Bradley Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接