I have a view, and I want to move it with finger. I wanted to get the xDelta and yDelta and just translate the matrix of the view (not image view, any view, RelativeLayout for example).
I am wondering how to do that:
Overriding RelativeLayout's onDraw and apply translation matrix there. Is that possible?
I am currently doing it with applying animation on each onTouch event. The animation is with duration 0 and the start/end of x/y is the same (setFillAfter = true). It just puts the view where I want. But isn't that too expensive?
Can't I manipulate the matrix of any view directly through onDraw? I tried something like this:
#Override
protected void onDraw(Canvas canvas) {
if (getDx() != 0 && getDy() != 0) {
m = canvas.getMatrix();
m.postTranslate(dx, dy);
canvas.setMatrix(m);
}
super.onDraw(canvas);
}
But it seems that I am doing it wrong.
If you want to implement drag gesture then you can use onTouchListener and in its MotionEvent.ACTION_MOVE set padding using setPadding to that view.
Here is the sample code:
case MotionEvent.ACTION_MOVE:
yourView.setPadding((int)event.getRawX(), (int)event.getRawY(), 0, 0);
Sample for onTouchListener :-
OnTouchListener drag= new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_MOVE:
img.setPadding((int)event.getRawX(), (int)event.getRawY(), 0, 0);
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
} return true;
}
};
You need to create the dragging image at run time and have to adjust its position. In this sample code I have not adjusted the position so the dragged image is not created at the position of touch. You also need to consider the height and width of the image to be dragged.
Hope it helps !
I hate to be the one to tell you that your problem is even easier than you thought, but here's what it looks like:
#Override
protected void onDraw(Canvas canvas) {
if (getDx() != 0 && getDy() != 0) {
canvas.translate(getDx(), getDy());
}
super.onDraw(canvas);
}
Hope this helps!
If you want to Move your layout permanently (In case of temporary, we can use animation ) then Use Drag And Drop API from android Official Page . Hope this will help you
Couple of things that would help in achieving it:
Make sure that your view originally has enough space in the direction you want to use. Like 'match_parent' etc
Use GestureDetector.onSimpleGestureListener and override onDraw ( return true;) , onScroll -- connect it using onTouchEvent and you will directly get the distance , or you can calculate yourself by using the event1 and event2
Store this information in variable(s) and call invalidate()
in your onDraw method - use this information by canvas.translate(..use those variables..); super.onDraw(canvas);
and your will achieve the result
PS: The drawing starts by taking left-top as 0,0
Related
Im facing the next 2 problems:
1) When I translate an imageview from outside the screen to inside the screen, when the image is moving the image is cropped, and when finishes moving the imageview fixes and shows ok. Why this is happening?
2) I use translateAnimation to move an imageview for example from (0,0) to (300,0).
I have implemented the on touch listener. When I try to move the imageview that translate before, when I try to move with the finger the ontouch not works, but if a touch with the finger in the position (0,0) the imageview moves but the image not shows! I don’t understand what is happening.
I try to move the imageView with the finger in the position (300,0) but not work, and when i touch in the position (0,0) moves. But if i move for example 100 in x axis, the imageview is not in position (100,0), its in (400,0)!! i dont understand what is happening. Something is missing, i think the imageview saves the position that start to move or someting, i dont understand. If i remove the translate animation to that imageview, the ontouch works OK!
I hope I was clear.
Here is my code for problem 1:
public void showImageFromOutside(ImageView image){
image.setImageResource(obtenerImagen(cartasJugador.get(0).toString()));
TranslateAnimation animation1 = new TranslateAnimation(100, 425, 100, 525);
animation1.setDuration(800);
animation1.setFillAfter(true);
animation1.setAnimationListener(animationListener);
image.startAnimation(animation1);
}
Here is my code for problem 2:
public void moveImageView(Imageview image){
animation = new TranslateAnimation(0, 300, 0, 0);
animation.setDuration(250);
animation.setFillAfter(true);
animation.setAnimationListener(animationListener);
image.startAnimation(animation);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
seMueve = true;
break;
case MotionEvent.ACTION_MOVE:
if (seMueve) {
x = (int) event.getRawX() - v.getWidth()/2;
y = (int) event.getRawY() - v.getHeight();
v.setX(x);
v.setY(y);
}
break;
case MotionEvent.ACTION_UP:
seMueve = false;
break;
}
v.performClick();
return seMueve;
}
Greets
Takes a look:
http://developer.android.com/guide/topics/graphics/prop-animation.html#property-vs-view
especially to
...another disadvantage of the view animation system is that it only modified where the View was drawn, and not the actual View itself. For instance, if you animated a button to move across the screen, the button draws correctly, but the actual location where you can click the button does not change, so you have to implement your own logic to handle this.
I think that you can not use onTouchListener with Animation. You shoulds use ObjectAnimator, its easy.
If your API is lower than 11 you can try with http://nineoldandroids.com/.
Regards
I'm working on an app that plots nodes on a map, and each node has edges that are represented by a line between them. I've drawn the edges using Canvas and drawLine(), but it would be useful if the lines themselves could be clickable. By that I mean a method of allowing the user to touch the line or think they're touching the line and an event can trigger. (like display edge info, etc...)
I can't rightly attach a touch event to a line I've drawn with Canvas, so I was thinking of placing ImageViews inbetween the ends of each edge line that's drawn. The ImageView could be a dot so it's clear where the touch event triggers.
Does anyone have any other suggestions? I'm mainly looking for ideas that I've missed. Maybe there's something in the Android API that can help with this that I'm unaware of.
Thanks in advance for any tips!
Use a path to draw the line:
Path linePath;
Paint p;
RectF rectF;
float point1X, point1Y, point2X, point2Y;
// initialize components
// draw the line
linePath.moveTo(point1X, point1Y);
linePath.lineTo(point2X, point2Y);
canvas.drawPath(linePath, p);
linePath.computeBounds(rectF, true);
Override onTouchEvent(MotionEvent):
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (rectF.contains(touchX, touchY)) {
// line has been clicked
}
break;
}
return true;
}
I have created my own component which extends RelativeLayout, inside it I have a field of View type which is being positioned with margins:
Blue quad represents my parent view, and a red circle is a child.
Now I want to allow user to move this red circle while moving a finger on a screen.
This is my onTouchEvent() method:
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventAction = event.getAction();
switch (eventAction) {
case MotionEvent.ACTION_DOWN:
// finger touches the screen
break;
case MotionEvent.ACTION_MOVE:
marginX = (int)event.getX();
marginY = (int)event.getY();
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams(); // pointer is this red circle
lp.setMargins(marginX, marginY, 0, 0);
break;
case MotionEvent.ACTION_UP:
// finger leaves the screen
break;
}
return true;
}
But I quickly found out that it doesn't refresh it's position while user is moving his finger on a screen, but instead it does it only when user releases his finger from the screen. So basically, when I move my finger, circle stays in a same position, but when I stop moving, circle is drawn in new position. I tried using invalidate() method on both, parent and child views, but it didn't help. I assume that it may have something to do with UI thread, but I don't have access to runOnUiThread()' method as it's not anActivity`.
EDIT:
I passed an activity to my class, so that I can use runOnUiThread(). My case: ACTION_MOVE now looks like this:
case MotionEvent.ACTION_MOVE:
marginX = (int)event.getX();
marginY = (int)event.getY();
activity.runOnUiThread(new Runnable() {
public void run() {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams();
lp.setMargins(marginX, marginY, 0, 0);
pointer.invalidate();
}
});
break;
If it's simple pointer you can draw it on Canvas as Drawable:
#Override
protected void onDraw(Canvas canvas) {
pointer.setBounds(marginX, marginY, marginX + pointerWidth, marginY + pointerHeight);
pointer.draw(canvas);
super.onDraw(canvas);
}
And then call invalidate() on pointer in onTouchEvent() method.
I think you need drag and drop function
Refer http://www.vogella.com/articles/AndroidDragAndDrop/article.html
How to make picture in a Canvas onTouch, like a button. Just to be press and nothing else. I can insert picture in Canvas, now how can I make her onTouch? Can somebody pls give me easy exsample? Dont be mad, cuz this is probably stupid and easy question
Thank you
public boolean handleTouch(MotionEvent event)
{
float newX = event.getX();
float newY = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
if (isInRect((int) newX, (int) newY))
{
refreshView();
}
//....
}
}
You cannot add an onClick or onTouch listener to something you've drawn with the canvas. These listeners can only be applied to views.
Another method will be to apply the onTouchListener to the view, and find the touch position to find whether the touch was on the pictures position.
I have a table-top style game board consisting of 10x10 squares. Each square is a PNG image. On top of these squares I want to place tiles which can be drag and dropped on top of the squares.
What would be my best approach concerning Views?
Is it possible to have two layers where layer one is a grid of ImageView's which represents the board. Would it then be possible to let the tile be an ImageView also which could be "stacked" on top of the ImageView's which represents the board?
Any good design ideas are welcome!
Thanks.
/ Henrik
Override onTouchEvent in your View:
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (!mEnable) {
return false;
}
int action = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
onTouchActionDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
onTouchActionMove(x, y);
break;
case MotionEvent.ACTION_UP:
onTouchActionUp(x, y);
break;
}
return true;
}
Then in either onTouchActionUp/Down just use the co-ordinates and redraw your image resource, i.e. invalidate() your view.
Override onDraw to draw the dragged graphic:
#Override
protected void onDraw(Canvas canvas)
drawMyDragGfx();
}
I did a override on onDraw and onTouchEvent in my View. I.e. I did the drag and drop drawing all by myself.
Worked like a charm :-)