hi i need to rotate an ImageView in my app on touch
and i am using the following code
public android.view.View.OnTouchListener onTableTouched = new android.view.View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent evt) {
WrapMotionEvent event = WrapMotionEvent.wrap(evt);
ImageView view = (ImageView) v;
// Dump touch event to log
dumpEvent(event);
//
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = NONE;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
if(mode == NONE){
updateRotation();
}
break;
}
return true;
}
};
private void updateRotation()
{
matrix.postRotate(10);
Bitmap redrawnBitmap = Bitmap.createBitmap(itembmp, 0, 0,itembmp.getWidth(), itembmp.getHeight(), matrix, true);
itembmp=redrawnBitmap;
image.setImageBitmap(itembmp);
}
but by using this i can rotate the image in clock-direction only.
But i need to rotate the image in both directions .
How to do that.
I would make two functions, one called updateRotationClockwise, one called updateRotationCounterClockWise.
In clockwise, it should stay:
matrix.postRotate(10);
In counterclockwise, it should say:
matrix.postRotate(350);
I am in process of developing this logic.
1. Difference in angle. one needs to also check other boundary conditions for more accuracy.
2. Instead of handling touch actions. I used in build ScaleGestureDetector class for information.
In onScaleBegin assuming I get the event using a setter (called in on touch) in the OnScaleGestureListener.
before=gety/getx;
In on ScaleEnd
after=gety/getx;
thus difference is tan-1(before)-tan-1(after)
if +tive anticlockwise -tive clockwise.
It is not so accurate I am adding conditions but one can try this out.
from the class ClockView you can find the method for rotation for your bitmap image
https://github.com/jselbie/xkcdclock
Related
I would like to set image1 for the button, but when it is pressed - change it to image2. After releasing, the button should be again an image1. I tried to do it this way in onClick() method:
button.setImageResource(R.drawable.image1);
if(button.isPressed())
button.setImageResource(R.drawable.image2);
but after first pressing the image of button changed to the image2 and stayed like that.
Could You help me with that problem?
I think this is what you want:
MyCustomTouchListener myCustomTouchListener = new MyCustomTouchListener();
button.setOnTouchListener(myCustomTouchListener);
Now the MyCustomTouchListener :
class MyCustomTouchListener implement OnTouchListener {
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
// touch down code
button.setImageResource(R.drawable.image1);
break;
case MotionEvent.ACTION_MOVE:
// touch move code
break;
case MotionEvent.ACTION_UP:
// touch up code
button.setImageResource(R.drawable.image1);
break;
}
return true;
}
}
You can do this easily with a state list drawable, and it requires no additional java code on your part (unless you are creating a StateListDrawable at runtime, but even that is a more suitable approach than implementing custom touch interaction).
Use the following:
int dispImg = 0;
button.setImageResource(R.drawable.image1);
if (button.isPress()) {
if (dispImg == 0) {
button.setImageResource(R.drawable.image2);
dispImg = 1;
}
else if (dispImg == 1) {
button.setImageResource(R.drawable.image1);
dispImg = 0;
}
}
Explanation: dispImg keeps track of the image you're showing. When it is 0, it means that the 1st Image is showing and so, we should switch to the 2nd.
Hope I Helped :D
I have a project which i'm required to develop Android game that display a 5*5 table and and image for each player which each one of them can move the image in place inside the 5*5 table.
ex:
Note : I need to know the exact coordinates (or anything relative) so i can save the position in array and move the image to that new place (eg : re-draw it on the new position).
Any ideas ?
Thanks in advance.
Just use a RelativeLayout with 5x5 ImageViews (set to not visible).
And on the images that the user can move to the place, use Drag and Drop.
In onDrag you set the visibility of the image to Gone.
For all ImageView (5x5 Table), you set the onDragListener.
After that, in the overwritten method OnDrop, you can receive the view that is dropped and can determine which drawable to show.
edit:
Oh well, in this case I would use GridView as said in the comments. And make usage of drag and drop. You don't need to attach a DragListener to every image then. You can simply let the GridView listen to the drop events and determine by the x and y where to drop.
Little example (just as a hint)
gameStoneView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
DragShadowBuilder shadowBuilder = new DragShadowBuilder(gameStoneView);
gameStoneView.startDrag(null, shadowBuilder, gameStoneView, 0);
if (dragListener != null) {
dragListener.onDragStart();
}
break;
default:
LOG.v("Motion event reorderIcon: DEFAULT - not action down");
}
return true;
}
});
gridView.setOnDragListener(new OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
currentY = event.getY();
currentX = event.getX();
break;
case DragEvent.ACTION_DROP:
final Point position = getPositionOfItem(currentX, currentY);
dropItemAt(position);
break;
case DragEvent.ACTION_DRAG_EXITED:
//BORDER DRAGEVENT: ACTION_DRAG_EXITED
viewDraggedOutSide = true;
break;
case DragEvent.ACTION_DRAG_ENDED:
//BORDER DRAGEVENT: ACTION_DRAG_ENDED
if (viewDraggedOutSideList) {
reinsertDraggedItem();
update();
}
viewDraggedOutSideList = false;
return true;
default:
return true;
}
}
});
I've got an imageview that resizes to a random size within a given range. The method below is called in onCreate and works fine when it's called the first time. However when it is called in onTouchEvent, the method runs but doesn't resize the imageView.
public void setInnerCircleSize()
{
widthMultiplier = r.nextInt(75 - 25) + 25;
widthToSet = ((widthScreen / 100) * widthMultiplier);
circle.getLayoutParams().height = widthToSet;
circle.getLayoutParams().width = widthToSet;
}
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
if(hitCheck == true)
{
hitCheck = false;
setInnerCircleSize();
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
hitCheck = true;
break;
}
}
setInnerCircleSize is being called fine when there is a motionevent and the random variables are created so there's nothing wrong in that respect. It's just that it won't resize a second time even though it worked perfectly fine when called from onCreate.
You have to invalidate the view to tell android to redraw it. Since you are changing the view bounds, I think you are suppose to use:
View.requestLayout();
i am developing game.i am displaying gun object center bottom of the screen.when user tap on screen i need to rotate gun that direction.i done rotating image.but when user tap on screen i need to rotate image that direction.can you please help me
Thanks in advance
Aswan
is your image a bitmap? could you convert it to one? Would an onClick listener not work and when the user clicks do something like.. http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
Seeing some code as to what you've attempting would be nice also. The following will help you with checking if the bitmap has been clicked in case you're stuck on that also http://developer.android.com/reference/android/view/View.html .
I've never attemped this myself but I think that would work. Try redrawing the bitmap when you have resized it.
Just use onTouchListener for your View and use this code for that
#Override
public boolean onTouch(View v, MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
Log.i(TAG, "action type is"+event.getAction());
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
Log.i(TAG, "Entering in onTouch");
double rotationAngleRadians = Math.atan2(currentX - dialer.centerX, dialer.centerY - currentY);
dialer.rotationAngle = (int) Math.toDegrees(rotationAngleRadians);
Log.i(TAG, "rotaion angle"+dialer.rotationAngle);
dialer.invalidate();
return true;
}
}
return true;
}
My class extends View and I need to get continuous touch events on it.
If I use:
public boolean onTouchEvent(MotionEvent me) {
if(me.getAction()==MotionEvent.ACTION_DOWN) {
myAction();
}
return true;
}
... the touch event is captured once.
What if I need to get continuous touches without moving the finger?
Please, tell me I don't need to use threads or timers. My app is already too much heavy.
Thanks.
Use if(me.getAction() == MotionEvent.ACTION_MOVE). It's impossible to keep a finger 100% completely still on the screen so Action_Move will get called every time the finger moves, even if it's only a pixel or two.
You could also listen for me.getAction() == MotionEvent.ACTION_UP - until that happens, the user must still have their finger on the screen.
You need to set this properties for the element
android:focusable="true"
android:clickable="true"
if not, just produce the down action.
Her is the simple code snippet which shows that how you can handle the continues touch event. When you touch the device and hold the touch and move your finder, the Touch Move action performed.
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if(isTsunami){
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Write your code to perform an action on down
break;
case MotionEvent.ACTION_MOVE:
// Write your code to perform an action on contineus touch move
break;
case MotionEvent.ACTION_UP:
// Write your code to perform an action on touch up
break;
}
}
return true;
}
Try this. It works to me:
public static OnTouchListener loadContainerOnTouchListener() {
OnTouchListener listener = new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
LinearLayout layout = (LinearLayout)v;
for(int i =0; i< layout.getChildCount(); i++)
{
View view = layout.getChildAt(i);
Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if(outRect.contains((int)event.getX(), (int)event.getY()))
{
Log.d(this.getClass().getName(), String.format("Over view.id[%d]", view.getId()));
}
}
}
Remember: the listener you´ll set must be a container layout (Grid, Relative, Linear).
LinearLayout layout = findViewById(R.id.yourlayoutid);
layout.setOnTouchListener(HelperClass.loadContainerOnTouchListener());
This might help,
requestDisallowInterceptTouchEvent(true);
on the parent view, like this -
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch(motionEvent.getAction()){
}
return false;
}
I was making a game with a custom view used as a thumb control. . . here is what I did
float x = 0, y = 0;
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
// handle touch events with
switch( event.getActionMasked() ) {
case MotionEvent.ACTION_DOWN :
if(cont)
{
// remove any previous callbacks
removeCallbacks(contin);
// post new runnable
postDelayed(contin, 10);
}
invalidate();
return true;
case MotionEvent.ACTION_MOVE :
if(!cont && thumbing != null)
{
// do non-continuous operations here
}
invalidate();
return true;
case MotionEvent.ACTION_UP :
// set runnable condition to false
x = 0;
// remove the callbacks to the thread
removeCallbacks(contin);
invalidate();
return true;
default :
return super.onTouchEvent(event);
}
}
public boolean cont = false;
// sets input to continuous
public void set_continuous(boolean b) { cont = b; }
public Runnable contin = new Runnable()
{
#Override
public void run() {
if(x != 0)
{
// do continuous operations here
postDelayed(this, 10);
}
}
};
A quick note however, make sure in your main activity that is calling this view removes the callbacks manually via the onPause method as follows
#Override
protected void onPause() {
if(left.cont) left.removeCallbacks(left.contin);
if(right.cont) right.removeCallbacks(left.contin);
super.onPause();
}
That way if you pause and come back touch events aren't being handled twice and the view is free from it's thread's overhead.
** tested on Samsung Galaxy S3 with hardware acceleration on **
All these answer are partially correct but they do not resolve in the right way the problem.
First of all, for everyone out there that decide to track when the event is ACTION_MOVE. Well that works only guess when? When user move his finger, so could if you decide to implement a custom thumb control is okay but for a normal custom button that's not the case.
Second, using a flag inside ACTION_DOWN and check it in ACTION_UP seems the logic way to do it, but as Clusterfux find out if you implement a while(!up_flag) logic you get stuck into troubles ;)
So the proper way to do it is mentioned here:
Continuous "Action_DOWN" in Android
Just keep in mind that if the logic you're going to write during the continuous press has to modify the UI in some way, you have to do it from the main thread in all the other cases it's better use another thread.
You can use the below code snippet as a reference in which I used the background to detect if the screen is held or not...
Main_Layout.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ResourceAsColor")
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Main_Layout.setBackgroundColor(R.color.green);
event.setAction(MotionEvent.ACTION_DOWN);
break;
default:
Main_Layout.setBackgroundColor(R.color.blue);
break;
}
return false;
}
});