Reputation: 1478
Currently I'm trying to develop an app, where user will be able to zoom in on images. But instead of pinch zoom, I need to make lens effect, which means that when user clicks on image and holds his finger on it for some time, right over it appears circle with zoomed in image. It looks like this:
I have looked at answers and links provided below and got it like this, but it's not working:
public class MainActivity extends Activity implements OnTouchListener{
ImageView takenPhoto;
static PointF zoomPos;
Paint shaderPaint;
BitmapShader mShader;
BitmapShader shader;
Bitmap bmp;
Bitmap mutableBitmap;
static Matrix matrix;
Canvas canvas;
static Paint mPaint;
static boolean zooming;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File file = new File(Environment.getExternalStorageDirectory() + "/Pictures/boxes.jpg");
String fileString = file.getPath();
takenPhoto = (ImageView) findViewById(R.id.imageView1);
bmp = BitmapFactory.decodeFile(fileString);
mutableBitmap = bmp.copy(Bitmap.Config.ARGB_8888, true);
takenPhoto.setImageBitmap(mutableBitmap);
matrix = new Matrix();
mShader = new BitmapShader(mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mShader);
takenPhoto.setOnTouchListener(this);
}
private static class ZoomView extends View {
public ZoomView(Context context) {
super(context);
}
public boolean onTouch(View view, MotionEvent event) {
int action = event.getAction();
zoomPos.x = event.getX();
zoomPos.y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = true;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
zooming = false;
this.invalidate();
break;
default:
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (zooming) {
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
mPaint.getShader().setLocalMatrix(matrix);
canvas.drawCircle(zoomPos.x, zoomPos.y, 100, mPaint);
}
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return true;
}
}
Upvotes: 4
Views: 2028
Reputation: 1478
After quite a few days of trying to solve this particular issue, I, thanks to those answers above and other sources, was able to write full working code.
To save time for all of you guys here it is. Copy-paste and edit it a bit to fit your goals.
First of all you need to edit your main activity - we're going to use custom ImageView
<your.package.name.ZoomView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Then we'll edit MainActivity.java. Use ZoomView just like ImageView
ImageView takenPhoto;
takenPhoto = (ZoomView) findViewById(R.id.imageView1);
After, create ZoomView class and paste this:
public class ZoomView extends ImageView {
PointF zoomPos;
boolean zooming;
Matrix matrix;
BitmapShader mShader;
Paint mPaint;
public ZoomView(Context context) {
super(context);
}
public ZoomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ZoomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
zoomPos = new PointF();
zoomPos.x = event.getX();
zoomPos.y = event.getY();
matrix = new Matrix();
mShader = new BitmapShader(MainActivity.mutableBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setShader(mShader);
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
zooming = true;
this.invalidate();
break;
case MotionEvent.ACTION_UP:
zooming = false;
this.invalidate();
break;
case MotionEvent.ACTION_CANCEL:
zooming = false;
this.invalidate();
break;
default:
break;
}
return true;
}
@Override
protected void onDraw(@NonNull Canvas canvas) {
super.onDraw(canvas);
if (zooming) {
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
mPaint.getShader().setLocalMatrix(matrix);
canvas.drawCircle(zoomPos.x, zoomPos.y, 100, mPaint);
}
}
}
Now you should have working magnifying effect.
Upvotes: 2
Reputation: 5684
One possible solution is grabbing the Canvas object from the view where your image in displayed. You will need to update the Canvas using various motion events.
Within handling these events, use functionality to draw only a portion of the image. The method listed is a part of the Canvas object. As far as parameters:
Bitmap bitmap //The image to zoom on
Rectangle src //A rectangle defining the portion of the image to zoom in on
Rectangle dest //A rectangle defining where in the View to draw the zoomed portion of your image.
//If the size of the rectangles is mismatched, it will zoom.
Paint paint //The paint object necessary for drawing.
Leave a comment if you have any questions. Happy coding!
Upvotes: 0
Reputation: 915
Well my guess would be :
1- You have to use a touch listener on the imageview
2- You have to have a canvas (where you draw the zoomed bitmap)
If you also want you could implement onDragListener to update the circular zoomed image while you drag your finger across the image.
I would say take a look at this link : Android - How to circular zoom/magnify part of image?
Upvotes: 2