Using Seek Bar to zoom android Canvas - java

this is my first question in stackoverflow. any help would be very much appreciated.
I am trying zoom a canvas using a seek bar, so depend on the progress of the seekbar, the canvas will zoom in and zoom out.
here is my code in the main activity:
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "Seekbar Value : " + progress, Toast.LENGTH_SHORT).show();
CPaintView paint = (CPaintView) this.findViewById(R.id.cPaintView1);
paint.zoomX = (float)progress;
paint.zoomY = (float)progress;
paint.invalidate();
}
then it will pass the progress value to the CPaintView class which contain the canvas:
public class CPaintView extends View implements OnTouchListener {
final Paint paint = new Paint();
int color = Color.parseColor("#FF0000");
Bitmap offScreenBitmap;
Canvas offScreenCanvas;
final int CIRCLE = 0;
final int TRIANGLE = 1;
final int SQUARE = 2;
int shape = CIRCLE;
private int mActivePointerId;
float zoomX = 0;
float zoomY = 0;
public CPaintView(Context context) {
super(context);
setup();
}
public CPaintView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
public CPaintView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public void setup()
{
setOnTouchListener(this); // define event listener and start intercepting events
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// draw the off screen bitmap
if(zoomX > 0)
{
canvas.save();
canvas.scale(zoomX, zoomY);
canvas.drawBitmap(offScreenBitmap, 0, 0, paint);
canvas.restore();
}
else
canvas.drawBitmap(offScreenBitmap, 0, 0, paint);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// get the x,y coordinates of the MotionEvent.ACTION_MOVE event
int pointerIndex = 0;
for(int i = 0; i < event.getPointerCount(); i++)
{
mActivePointerId = event.getPointerId(i);
pointerIndex = event.findPointerIndex(mActivePointerId);
float x = event.getX(pointerIndex);
float y = event.getY(pointerIndex);
float y1 = y + 20;
float x2 = x + 20;
float y2 = y1 - 10;
paint.setColor(color);
float verts[] = {x, y, x, y1, x2, y2};
int[] vertsColors = {color, color, color, color, color, color};
switch(shape)
{
case CIRCLE:
offScreenCanvas.drawCircle(x, y, 10, paint); break;// draw a red circle at the x,y coordinates specified by the user
case TRIANGLE:
offScreenCanvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, vertsColors, 0, null, 0, 0, paint);break;
case SQUARE:
offScreenCanvas.drawRect(x-10, y-10, x+10, y+10, paint); break;
}
invalidate();
}
return true;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// create / re-create the off screen bitmap to capture the state of our drawing
// this operation will reset the user's drawing
offScreenBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
offScreenCanvas = new Canvas(offScreenBitmap);
}
}
I am having problem with the onDraw method. The problem is, when I increase the seekbar progress, the whole canvas disappear and I try to draw on it, it seems like it doesn't draw. But when I decrease the seekbar progress back to 0, all the drawing comes back and I can see it again, including the drawing that seems like not working.
I am sorry for my bad english.
Thank you very much.

Your problem is conceptual with how scale works. Scaling at 0,0 is undefined. Scaling at 1f,1f is the default. The scaling isn't working much at all,
if(zoomX > 0)
{
canvas.save();
canvas.scale(zoomX, zoomY);
canvas.drawBitmap(offScreenBitmap, 0, 0, paint);
canvas.restore();
}
else
canvas.drawBitmap(offScreenBitmap, 0, 0, paint);
if the zoom is 0, then it'll properly draw the scaled bitmap. Because it'll skip your zoom step. else you have a scaling of like 50 which is basically going to maybe have the bitmap be a dot. Try getting the zoom to hover around 1. Something like zoom = 12 / (1 + progress) Then the zoom can range from like 12x to values less than zero. Your drawing seems like it should be there, it's just WAAAAY small. Except at zero where you skip that step and make it 1.

Related

How do I show old bitmap into DrawingView while painting

I want to edit my drawing painted image. I am getting a bitmap image and setting it into a canvas bitmap, but the old image is not appearing. I have tried using the drawingView.refresh() and recycle() methods, but couldn't make it work.
private DrawingView mDrawingView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawing);
if(datadtlimgsItem !=null && datadtlimgsItem.getImageStr()
!=null) {
decodedString = Base64.decode(datadtlimgsItem.getImageStr(),
Base64.DEFAULT);
decodedByte = BitmapFactory.decodeByteArray(decodedString, 0,
decodedString.length);
decodedByte = Util.resize(decodedByte, 400, 100);
mDrawingView.canvasBitmap = decodedByte;
}
}
public class DrawingView extends View{
// To hold the path that will be drawn.
private Path drawPath;
// Paint object to draw drawPath and drawCanvas.
private Paint drawPaint, canvasPaint;
// initial color
private int paintColor = 0xff000000;
private int previousColor = paintColor;
// canvas on which drawing takes place.
private Canvas drawCanvas;
// canvas bitmap
public Bitmap canvasBitmap;
// Brush stroke width
private float brushSize, lastBrushSize;
// To enable and disable erasing mode.
private boolean erase = false;
public DrawingView(Context context, AttributeSet attrs){
super(context, attrs);
setUpDrawing();
}
/**
* Initialize all objects required for drawing here.
* One time initialization reduces resource consumption.
*/
private void setUpDrawing(){
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
// Making drawing smooth.
drawPaint.setAntiAlias(true);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
// Initial brush size is medium.
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
drawPaint.setStrokeWidth(brushSize);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// X and Y position of user touch.
float touchX = event.getX();
float touchY = event.getY();
// Draw the path according to the touch event taking place.
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
if (erase){
drawPaint.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPaint.setXfermode(null);
break;
default:
return false;
}
// invalidate the view so that canvas is redrawn.
invalidate();
return true;
}
public void setColor(String newColor){
// invalidate the view
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
previousColor = paintColor;
}
public void setBrushSize(float newSize){
float pixelAmount =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize=pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
public void setErase(boolean isErase){
//set erase true or false
erase = isErase;
if(erase) {
drawPaint.setColor(Color.WHITE);
//drawPaint.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
else {
drawPaint.setColor(previousColor);
drawPaint.setXfermode(null);
}
}
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}
I have a view like Paint I want to show old image getting from activity in current view and then edit my image.
image is blank but i need to show previous image here
here is saved image want to edit this image
I have a view like Paint I want to show old image getting from activity in current view and then edit my image. I have a view like Paint I want to show old image getting from activity in current view and then edit my image. I have a view like Paint I want to show old image getting from activity in current view and then edit my image. I have a view like Paint I want to show old image getting from activity in current view and then edit my image. I have a view like Paint I want to show old image getting from activity in current view and then edit my image.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (canvasBitmap == null){
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
drawCanvas = new Canvas(canvasBitmap);
}

Custom ImageView loses transparency as soon as it goes out of screen in recycleView

I have a custom ImageView that overrides onDraw method to crop corners using Path to give rounded corner of given radius. I have a RecyclerView where I have these custom ImageView in all of the 4 items. Now the problem is this custom ImageView renders fine for the first time it shows up in the list. Only 2 accommodate in the screen at a time. As I scroll down everything is fine in all views. I can see rounded corner in all of them. But when I scroll up to previous item. Now these corner lose their transparency in corners and become black in all but third item in the list. Canvas in onDraw also has isOpaque = true. I have tried many things but nothing seem to be working. Here is the code
public class RoundedImageView extends ImageView
{
private Paint mPaint;
private int mCornerRadius = 0;
private boolean mRoundedTopLeft = true, mRoundedBottomLeft = true, mRoundedTopRight = true, mRoundedBottomRight = true;
public void setCornerRadius(int mCornerRadius)
{
this.mCornerRadius = mCornerRadius;
}
public void RoundCorners(boolean isRoundedTopLeft, boolean isRoundedTopRight, boolean isRoundedBottomLeft, boolean isRoundedBottomRight)
{
mRoundedTopLeft = isRoundedTopLeft;
mRoundedBottomLeft = isRoundedBottomLeft;
mRoundedBottomRight = isRoundedBottomRight;
mRoundedTopRight = isRoundedTopRight;
}
public RoundedImageView(Context context)
{
super(context);
if (Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setupPaint();
}
public RoundedImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
if (Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setupPaint();
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
if (Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setupPaint();
}
#TargetApi(21)
public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
if (Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
setupPaint();
}
private Paint setupPaint()
{
mPaint = new Paint();
mPaint.setColor(Color.TRANSPARENT);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStrokeWidth(1);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
return mPaint;
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Path path = RoundedRect(0, 0, getWidth(), getHeight(), mCornerRadius, mCornerRadius,
mRoundedTopLeft, mRoundedTopRight, mRoundedBottomRight, mRoundedBottomLeft);
canvas.drawPath(path, mPaint);
}
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl)
{
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else
{
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else
{
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else
{
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else
{
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
return path;
}
}
What I have already tried:
- setting isRecyclable false in ViewHolder
setting different PorterDuff mode in paint
LAYER_TYPE_HARDWARE (hardware acceleration) for this view
setDrawingCacheBackgroundColor(0x00000000); in constructor
setLayerType(View.LAYER_TYPE_SOFTWARE, paint); passing paint in this function
tried making canvas transparent before super.onDraw()
UPDATE:
After a lot of fiddling around I have concluded that whenever my viewHolder's view goes out of screen. All it's alpha channel become black. I have a feeling it has to do something with the setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Worked by making the parent software accelerated.
I solved it by putting
if (Build.VERSION.SDK_INT >= 11)
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
in constructor of my ViewHolder. It worked even if I enabled software acceleration for any parent container view.
Now I don't know why this worked.

Performance issues with Canvas

I want to draw on a bitmap using Canvas.
I tested it on my phone and it appeared to be very slow and it felt like if I drew fast it didn't register the whole movement but only parts of it.
Since I want it to very detailed I need to use bitmaps
How can I improve my performance?
public class DrawView extends View {
public Bitmap mBitmap;
public Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint mPaint;
public DrawView(Context c, AttributeSet attrs) {
super(c, attrs);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFF000000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(9);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
}
If touch events go faster, then onDraw, then you don't need to draw every time you have new point, you should draw, when it's actually asked to - in onDraw method.
Although, skia (which is android canvas based on) is not so fast to draw so many quads. You can draw simple batch of lines, but form these lines as centripethal Catmull-Rom splines or some splines, which is better for you.
And more, Path can store not so much lines

How to make usable padding space around circle in canvas (Android)

I am having problems displaying dots on the outer ring of a circle. When a dot is placed at one of the edges of the circle, the dot is half cut off . Screenshot: https://drive.google.com/file/d/0B9BaYaKRY3v3Y2hXYkpSOE1nY28/edit?usp=sharing
I simply want to make the circles radius a litte smaller so there is some space around it where the outer dots have got some space. Of course the circle must still stay in the middle of the view. Tipps on how to do this are very appreciated.
The working code blow is fully working accept for the fact that the dots are being cut off. (Thanks to #Sherif elKhatib for the help on creating a 2 color circle)
public class PercentView extends View {
public PercentView(Context context) {
super(context);
init();
}
public PercentView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PercentView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.parseColor("#3498db"));
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
bgpaint = new Paint();
bgpaint.setColor(Color.parseColor("#2980b9"));
bgpaint.setAntiAlias(true);
bgpaint.setStyle(Paint.Style.FILL);
rect = new RectF();
circlePaint = new Paint();
}
Paint paint;
Paint bgpaint;
RectF rect;
float percentage = 5;
Paint circlePaint;
float[] dots = new float[1000];
int dotsNum = -1;
String[] colorCode = new String[1000];
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw background circle anyway
canvas.drawArc(rect, -90, 360, true, bgpaint);
if (percentage != 0) {
int left = 0;
int width = getWidth();
int top = 0;
rect.set(left, top, left + width, top + width);
canvas.drawArc(rect, -90, (float) (3.6 * percentage), true, paint);
for (int i = 0; i <= dotsNum; i++) {
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.parseColor(colorCode[i]));
circlePaint.setStyle(Paint.Style.FILL);
float dotX = (float) (this.getWidth() / 2 + this.getWidth() / 2
* Math.cos((dots[i] * 3.6 - 90) * Math.PI / 180));
float dotY = (float) (this.getHeight() / 2 + this.getWidth()
/ 2 * Math.sin((dots[i] * 3.6 - 90) * Math.PI / 180));
canvas.drawCircle(dotX, dotY, 30, circlePaint);
}
}
}
public void setPercentage(float inpercentage) {
this.percentage = inpercentage;
invalidate();
}
public void setDot(int type) {
dotsNum++;
switch (type) {
case 0:
colorCode[dotsNum] = "#27ae60";
break;
case 1:
colorCode[dotsNum] = "#f1c40f";
break;
case 2:
colorCode[dotsNum] = "#e74c3c";
break;
case 3:
colorCode[dotsNum] = "#34495e";
break;
}
dots[dotsNum] = percentage;
invalidate();
}
}
The only one working approach for me was that piece of code "width = getWidth() - padding". Kudos #Catherine.

touch scrolling with libgdx

I'm trying to implement touch scrolling in a libgdx game. I have a wide image that is a panorama of a room. I want to be able to scroll the image so the user can see around the room. I have it so that I can scroll a certain distance but when a new touchDragged event is registered the image is moved back to the original position.
This is how I'm implementing it
public class AttackGame implements ApplicationListener {
AttackInputProcessor inputProcessor;
Texture backgroundTexture;
TextureRegion region;
OrthographicCamera cam;
SpriteBatch batch;
float width;
float height;
float posX;
float posY;
#Override
public void create() {
posX = 0;
posY = 0;
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
backgroundTexture = new Texture("data/pancellar.jpg");
region = new TextureRegion(backgroundTexture, 0, 0, width, height);
batch = new SpriteBatch();
}
#Override
public void resize(int width, int height) {
cam = new OrthographicCamera();
cam.setToOrtho(false, width, height);
cam.translate(width / 2, height / 2, 0);
inputProcessor = new AttackInputProcessor(width, height, cam);
Gdx.input.setInputProcessor(inputProcessor);
}
#Override
public void render() {
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(backgroundTexture, 0, 0, 2400, 460);
batch.end();
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
backgroundTexture.dispose();
}
}
And in the InputProcessor
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
cam.position.set(screenX, posY / 2, 0);
cam.update();
return false;
}
I got this far with help from this question LibGdx How to Scroll using OrthographicCamera?. However it doesn't really solve my problem.
I think the problem is with the touchDragged corodinates not being world coordinates but I have tried unprojecting the camera with no effect.
I have been struggling with this for a few weeks and I would really appreciate some help on this.
Thanks in advance.
I recently did something as what you want. This is my Input class that I use for move the map, you only need to change my 'stage.getCamera()' for your 'cam':
public class MapInputProcessor implements InputProcessor {
Vector3 last_touch_down = new Vector3();
...
public boolean touchDragged(int x, int y, int pointer) {
moveCamera( x, y );
return false;
}
private void moveCamera( int touch_x, int touch_y ) {
Vector3 new_position = getNewCameraPosition( touch_x, touch_y );
if( !cameraOutOfLimit( new_position ) )
stage.getCamera().translate( new_position.sub( stage.getCamera().position ) );
last_touch_down.set( touch_x, touch_y, 0);
}
private Vector3 getNewCameraPosition( int x, int y ) {
Vector3 new_position = last_touch_down;
new_position.sub(x, y, 0);
new_position.y = -new_position.y;
new_position.add( stage.getCamera().position );
return new_position;
}
private boolean cameraOutOfLimit( Vector3 position ) {
int x_left_limit = WINDOW_WIDHT / 2;
int x_right_limit = terrain.getWidth() - WINDOW_WIDTH / 2;
int y_bottom_limit = WINDOW_HEIGHT / 2;
int y_top_limit = terrain.getHeight() - WINDOW_HEIGHT / 2;
if( position.x < x_left_limit || position.x > x_right_limit )
return true;
else if( position.y < y_bottom_limit || position.y > y_top_limit )
return true;
else
return false;
}
...
}
This is the result: http://www.youtube.com/watch?feature=player_embedded&v=g1od3YLZpww
You need to do a lot more computation in the touchDragged callback, you can't just pass whatever screen coordinates were touched on to the camera. You need to figure out how far the user has dragged their finger, and in what direction. The absolute coordinates are not immediately useful.
Consider dragging down from the top-right or dragging down from the top-left. In both cases you want (I presume) to move the camera the same distance, but the absolute values of the screen coordinates will be very different in the two cases.
I think the simplest thing is to just track previousX and previousY (initialize them in the touchDown method. Then invoke cam.translate() with the delta (deltaX = screenX - previousX, for example), during touchDragged. And also update the previous* in touchDragged.
Alternatively, you can look at some of the fancier InputProcessor wrappers libgdx provides (see https://code.google.com/p/libgdx/wiki/InputGestureDetection).
Simple answer:
Declare 2 fields to hold the new and old drag location:
Vector2 dragOld, dragNew;
When just touched you set both of these equal to the touched location or your cam will jump.
if (Gdx.input.justTouched())
{
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
dragOld = dragNew;
}
Update dragNew each frame and simply subtract the vectors from each other to get the x and y for translating the camera.
if (Gdx.input.isTouched())
{
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
if (!dragNew.equals(dragOld))
{
cam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y); //Translate by subtracting the vectors
cam.update();
dragOld = dragNew; //Drag old becomes drag new.
}
}
This is all I use to drag my ortho cam around, simple and effective.
Used drinor's answer but added the line on "touchDown) function so it doesn't reset the camera every time you start dragging again:
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
last_touch_down.set( screenX, screenY, 0);
return false;
}
I have not used it myself, but I would start by looking at the code of:
Have you looked at the code of http://libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/scenes/scene2d/ui/FlickScrollPane.html
See: touchDragged

Categories

Resources