如何通过Canvas DrawBitmap绘制位图的一部分

13

我有一个
source condition:

  1. FrameLayout(用红色标记)
  2. 源ImageView(黑色)
  3. 带有OnTouchListener的对象(橙色)

通过带有OnTouchListener的对象,我想显示在图片视图(源ImageView)上填充的位图部分。

所以这不是问题,我像这样做:
Bitmap bt = Bitmap.createBitmap(sourceBitmap,event.getX(),event.getY(),250,250);

其中:

  1. sourceBitmap - 是添加到源ImageView的图像
  2. event.getX() / event.getY()是我开始绘制位图部分的坐标
  3. 250,250 - 是位图(部分)的大小。

结果是:

result of first case

那么当我的带触摸监听器的对象到达边界时(我为橙色对象创建了这种可能性,可以使用Object.width()/2越界),问题就出现了。

所以在这种情况下:
case #2
我该如何实现这个结果:
excepted result of case #2
其中部分的结果将是:

  1. 位图的一部分
  2. 第二部分是FrameLayout背景的颜色。

我目前尝试过的是:

public boolean onTouch(View view, MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:

            //i want to draw bigger portion then corrds
            int CurrentX = (int)view.getX() - (view.getWidth());
            int CurrentY = (int)view.getY() - (view.getHeight());

            //case,when object is going out of border
            if(CurrentX <= 0)
            {
                Paint paint = new Paint();
                paint.setStyle( Style.FILL  );
                paint.setColor( Color.RED );

                mBitmap = Bitmap.CreateBitmap(sourceBitmap,(int)view.getX() + Math.abs(CurrentX),(int)view.getY(),250,250);
                Canvas canvas = new Canvas(mBitmap);
                canvas.drawBitmap(mBitmap,new Rect((int)view.getX()+Math.abs(CurrentX), (int)view.getY(),250-Math.abs(CurrentX),250),new RectF(Math.abs(CurrentX), 0, 250,250),paint);
            }
            break;
    }

    return true;
}
}

有什么建议吗?谢谢!


1
关于您的“如何通过Canvas DrawBitmap绘制位图部分”的问题,请参见:Canvas#drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint)-“绘制指定的位图,自动缩放/平移以填充目标矩形。如果源矩形不为空,则指定要绘制的位图子集。” - pskink
@pskink,我尝试了但没有成功。不明白为什么。 - XTL
@pskink 这正是我所需要的 http://stackoverflow.com/questions/31405082/when-touch-an-imageview-i-need-to-display-the-touched-area-in-another-imageview 。我尝试了不同的DrawBitmap变体,但是不知道为什么会得到糟糕的结果。 - XTL
那你尝试了什么?你的代码是什么? - pskink
你能分享一下可用的代码给我吗?@XTL。我已经尝试过了,但是出现了错误,像这样“java.lang.IllegalArgumentException: y + height must be <= bitmap.height()”。 - gautam
显示剩余4条评论
2个回答

10

我自己解决了!
虽然过程复杂,但结果相当不错。
这里我们开始:
对于我的情况(当带有OnTouchListener对象的对象可以超出X和Y轴的边界时),我制定了后置条件(某种规则)。


条件

宽度 = 我想要显示结果的imageView的宽度。
高度 = 我想要显示结果的imageView的高度;

左侧

  1. X_Coord < 0 && Y_Coord - Height / 2 < 0 && Y_Coord < Bitmap.Height
    这是我们的顶部区域
  2. X_Coord < 0 && Y_Coord - Height / 2 > 0 && Y_Coord < Bitmap.Height
    这是我们的中间区域
  3. X_Coord < 0 && Y_Coord - Height / 2 > 0 && Y_Coord > Bitmap.Height
    这是我们的底部区域

右侧

  1. X_Coord > Bitmap.Height && Y_Coord - Height / 2 > 0 && Y_Coord < Bitmap.Height
    这是我们的中间区域
  2. X_Coord > Bitmap.Height && Y_Coord - Height / 2 < 0 && Y_Coord < Bitmap.Height
    这是我们的顶部区域
  3. X_Coord > Bitmap.Height && Y_Coord - Height / 2 > 0 && Y_Coord > Bitmap.Height
    这是我们的底部区域

标准(中间区域,不往左或右移动)

  1. X_Coord - Width / 2 > 0 && X_Coord < Bitmap.Width && Y_Coord - Height / 2 < 0 && Y_Coord < Bitmap.Height
    这是我们的顶部区域
  2. X_Coord - Width / 2 > 0 && X_Coord < Bitmap.Width
    public boolean onTouch(View view, MotionEvent event) {
    
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
    
            int Width = ResultImgView.getWidth();
            int Height = ResultImgView.getHeight();
            //paint for our Red background
            Paint paint = new Paint();
            paint.setStyle( Style.FILL  );
            paint.setColor( Color.RED );
            Bitmap mBitmap = null;
            Canvas canvas = null;
    
            //Our Condition 
            if(view.getX() - Width / 2 >= SourceBitmap.getWidth() 
                && view.getY() - Height / 2 > 0 && view.getY() + Height / 2 <  SourceBitmap.getHeight())
            {
                //Nice,we entered here. Seems that we're now located at RightSide at Middle position
                //So let's draw part of bitmap.
                //our margin for X coords
                int Difference = (int)((view.getX() - Width / 2 ) - SourceBitmap.getWidth();
                //dont forget to put margin
                //BTW we're now took portion of bitmap
                mBitmap = Bitmap.createBitmap(SourceBitmap, ((int)view.getX() - Width / 2) - Difference, (int)view.getY() - Height / 2, Width,Height);
                canvas = new Canvas(mBitmap);
                //draw rect
                canvas.drawRect(0,0,mBitmap.getWidth(),mBitmap.getHeight(),paint);
                //draw portion of bitmap
                canvas.drawBitmap(mBitmap,new Rect(Difference, 0,mBitmap.getWidth(),mBitmap.getHeight()),new Rect(0,0,mBitmap.getWidth() - Difference,mBitmap.getHeight()),null);
                //and that's all!
            }
    
            //do the same for other  condition....etc
            break;
    }
    
    
    
       return true;
    }
    

    享受!


如果您想将 Android 框架 UI 组件(自定义或内置)的某些部分放入位图中,可以使用其 onDraw 方法与目标画布。视图将从点 (0, 0) 开始绘制,因此设置正确的转换即可获取任何 UI 部分。 - weaknespase
@VallyN,我解决了我的问题。现在我将发布我的解决方案。 - XTL
仅从我的角度来看,保持对内部视图对象的引用,如果你想要的一切只是屏幕上显示的一部分,那么这是一个后期出现问题的可靠方法。为什么不允许组件代码自己绘制所有内容呢? - weaknespase
@VallyN 感谢您的回复。我尝试创建自定义视图并在OnDraw方法中绘制图像的一部分,但这不是很方便。因此,通过架构和我想要显示位图的部分,我用另一种方式解决了这个问题。 - XTL

0

如果你的sourceBitmap只是设置到ImageView中的位图,那么结果是可预测的。为了实现你的目标,你需要:

  1. 橙色正方形在FrameLayout坐标系中的坐标。看起来你已经有了正确的坐标。
  2. 作为sourceBitmap,你必须使用由FrameLayout.draw方法创建的Bitmap。注意,你的橙色正方形不能是FrameLayout的子元素。

如果你把所有的代码都发布到某个地方,我可以检查一下。


我为每个对象(橙色正方形)附加了它自己的监听器(而不是在自定义帧布局中),这些对象(橙色正方形 - 是添加到帧布局中的ImageView)即为子项。PS:代码太多,无法在此处发布。我几乎解决了我的问题,但是DrawCanvas方法的行为很奇怪。 - XTL

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