可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to Scale, Move, Resize Image. I would like to surround the image with Indicators which guide user what operation these indicators perform i.e. Moving, Rotating, Scaling.
I've tried
- Scaling - but it only crops down. No chance to increase length and height of image.
- Rotate - achieved but via inserting manual degrees. That's not a good option in here.
- Moving - as I'm achieving drag on Api < 11. So little bit of difficult. Still no hope in here.
Is there any library which can do me simple image edit [Move, Scale, Rotate]?
回答1:
You can use Matrix transaformation to achieve rotating, scaling, and moving....I hope this will help you....
for rotating
Matrix matrix = new Matrix();
matrix.postRotate(90);
for scaling
matrix.postScale(scaleWidth, scaleHeight);
create new bitmap without changing the original one...like this
Bitmap bmp2 = Bitmap.createBitmap(bmp1, 0, 0, pow2, pow2, matrix, true);
回答2:
Using Library : StickerView
Its a 3rd Party Library which gives exactly what i was looking for.
WorkAround :
Still these answer is half of what I've asked for in OP. Means It ain't surronded by some specific Indicator. I'm still searching how to wrap ImageView
with indicators and use them for Translate & Resize.
Initilization of Variables inside Activity
important for Translate & Resize ImageView
public static final int DRAG = 1;
public static final int NONE = 0;
private static final String TAG = "Touch";
public static final int ZOOM = 2;
public static PointF mid = new PointF();
public static int mode = 0;
float d = 0.0F;
Matrix savedMatrix = new Matrix();
Matrix matrix = new Matrix();
PointF start = new PointF();
Setting ImageView
to scaleType - Matrix
iv = new ImageView(this);
iv.setPadding(10, 10, 25, 25);
iv.setScaleType(ImageView.ScaleType.MATRIX);
iv.setOnTouchListener(t);
Adding onTouch Listener to ImageView
which uses
- 1 Finger for Translate - Drag
2 Finger for Zoom - Resize {Pinch To Zoom}
View.OnTouchListener t = new View.OnTouchListener()
{
public boolean onTouch(View paramView, MotionEvent event)
{
ImageView view = (ImageView)paramView;
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG" );
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM" );
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
}
else if (mode == ZOOM) {
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE" );
break;
}
view.setImageMatrix(matrix);
return true;
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
};
回答3:
Just check out this image cropping reference :
http://www.londatiga.net/featured-articles/how-to-select-and-crop-image-on-android/
For image rotation, just refer to this example; this sample code represents the rotation of image dynamically:
http://android-er.blogspot.in/2010/07/rotate-bitmap-image-using-matrix.html
This link is also useful for image crop, rotate and scale:
https://github.com/Yalantis/uCrop
回答4:
I recently tried the same thing but ended up using a library since it covered a lot more edge cases. This is a great, and pretty widely used library:
http://code.google.com/p/android-multitouch-controller/
回答5:
I think I can help you with the rotation part. I recently made an android wheel menu library. It tracks user's hand motion and rotates the imageview accordingly. You can check out the source to see how I did it here:
https://github.com/anupcowkur/Android-Wheel-Menu
回答6:
You can https://github.com/siddhpuraamitr/MultitouchWithDynamicAddandRemove try this code in your project
回答7:
I know this is not an answer but it's worth mentioning.
Take a look at this project. I intend to put it on GitHub but it is not done yet (at all).
There is a button to rotate the image. I am still working on the "save". Many of the classes are taken from the Android source thanks to Lorenzo Villani's project
Add to your project's manifest:
<activity
android:name="mobi.sherif.camera.CropImage"
android:hardwareAccelerated="false"
android:screenOrientation="portrait" >
Call the activity using:
Intent intent = new Intent(mContext, CropImage.class);
intent.setData(uri);
startActivityForResult(intent, S.request.cropimage);
回答8:
Bitmap rotation
Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());
Image Scaling Scaling
AssetManager assetManager = context.getAssets();
InputStream imageIn;
String imgPath = "test.png";
Bitmap image;
try {
imageIn = assetManager.open(imgPath, AssetManager.ACCESS_BUFFER);
image = BitmapFactory.decodeStream(imageIn);
} catch (IOException e) {
}
//TODO: calculate width and height to fill or fit screen
image = Bitmap.createScaledBitmap(image, width, height, true);
Image moving Image in Canvas with touch events
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
public class ImgView extends View {
private static final int INVALID_POINTER_ID = -1;
private Drawable mImage;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public ImgView(Context context) {
this(context, null, 0);
mImage = getResources().getDrawable(R.drawable.imagename);
mImage.setBounds(0, 0, mImage.getIntrinsicWidth(), mImage.getIntrinsicHeight());
}
public ImgView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ImgView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
Log.d("DEBUG", "X: "+mPosX+" Y: "+mPosY);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
mImage.draw(canvas);
canvas.restore();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
invalidate();
return true;
}
}
}