Question

I m working on a word scramble game which allows user to move the image to image..if the image doesn't match then it should come back to it's original position from where it was dragged.I have written a sample code to move the image but the problem here is if I move one image the neighbouring image also starts moving.. Here is the sample code.

 /** Touchmoveimage.java*/
     package com.examples.Touchmoveimage;
     import android.app.Activity;
     import android.content.Intent;
     import android.os.Bundle;
     import android.view.MotionEvent;
     import android.view.View;
     import android.view.View.OnTouchListener;
     import android.widget.ImageView;
     import android.widget.LinearLayout.LayoutParams;
     public class Touchmoveimage extends Activity implements OnTouchListener{

int windowwidth;
int windowheight;

   private LayoutParams layoutParams ;
   private LayoutParams layoutParams1 ;
   @Override
   public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

  windowwidth = getWindowManager().getDefaultDisplay().getWidth();
  windowheight = getWindowManager().getDefaultDisplay().getHeight();

  ImageView ball= (ImageView)findViewById(R.id.ball);
  ball.setOnTouchListener(this);

  ImageView ball1 = (ImageView)findViewById(R.id.ball1);
  ball1.setOnTouchListener(this); 

 }   
 public boolean onTouch(View v,MotionEvent event) {
 switch(v.getId())
 {
 case R.id.ball:
   ImageView ball= (ImageView)findViewById(R.id.ball);
   layoutParams = (LayoutParams) ball.getLayoutParams();
      switch(event.getAction())
      {
      case MotionEvent.ACTION_DOWN:   
             break;
      case MotionEvent.ACTION_MOVE:
                   int x_cord = (int)event.getRawX();
                   int y_cord = (int)event.getRawY();

                   if(x_cord>windowwidth){x_cord=windowwidth;}
                   if(y_cord>windowheight){y_cord=windowheight;}

                  layoutParams.leftMargin = x_cord -25;
                 layoutParams.topMargin = y_cord - 75;

                 ball.setLayoutParams(layoutParams);
             break;
             default : break;
      }
 case R.id.ball1:
     ImageView ball1= (ImageView)findViewById(R.id.ball1);
       layoutParams1 = (LayoutParams) ball1.getLayoutParams();
          switch(event.getAction())
          {
          case MotionEvent.ACTION_DOWN:   
                 break;
          case MotionEvent.ACTION_MOVE:
                       int x_cord = (int)event.getRawX();
                       int y_cord = (int)event.getRawY();

                       if(x_cord>windowwidth){x_cord=windowwidth;}
                       if(y_cord>windowheight){y_cord=windowheight;}

                      layoutParams1.leftMargin = x_cord -25;
                       layoutParams1.topMargin = y_cord - 75;

                       ball1.setLayoutParams(layoutParams1);
                 break;          
       default : break;
        }
      }
     return true;}

      }
     <!-- main.xml -->

       <?xml version="1.0" encoding="utf-8"?>
       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:orientation="vertical"
       android:layout_width="fill_parent"
      android:layout_height="fill_parent"
     >
     <ImageView 
     android:layout_width="50sp" 
     android:layout_height="50sp" 
     android:id="@+id/ball"
    android:src="@drawable/ball">
   </ImageView>

   <ImageView 
    android:layout_y="30dip" 
    android:layout_x="118dip" 
    android:layout_width="50sp" 
    android:layout_height="50sp" 
    android:id="@+id/ball1"
    android:src="@drawable/ball1">
   </ImageView>

    </LinearLayout>

Anyone plz help me out..Trying all possible thing to solve it..

Was it helpful?

Solution

You need to make sure the event is happening in the given ball. The onTouch event will be declared even if you are touching outside of the image object. So what you could do is to check in the ACTION_DOWN phases you've blocked off to make sure the touch is in the bounds of the object. You could then set a flag to tell the system which ball is being moved. I'll let you do the coding up, but hopefully this will let you get an idea as to what to do.

OTHER TIPS

You can take an idea from this code, it will be very helpful... and i also working in this concept.

package com.example.drag;

 import android.app.*;
 import android.graphics.*;
 import android.os.*;
 import android.util.Log;
 import android.view.*;
 import android.view.View.*;
 import android.widget.*;
 import android.widget.AbsoluteLayout.LayoutParams;

public class MainActivity extends Activity implements OnTouchListener {
    // The letter that the user drags.
   // The letter outline that the user is supposed to drag letterView to.
    private AbsoluteLayout mainLayout;
    TextView letterView;
    TextView emptyLetterView;
    TextView letter_E,letter_I,letter_O,letter_U;
    TextView letter_C,letter_T;
    int status=0;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            mainLayout = (AbsoluteLayout) findViewById(R.id.absLayout);
            mainLayout.setOnTouchListener(this);
            letterView = (TextView) findViewById(R.id.imageView);
            letterView.setOnTouchListener(this);

            emptyLetterView = (TextView) findViewById(R.id.textView1);

            letter_E= (TextView) findViewById(R.id.text_E);
            letter_I= (TextView) findViewById(R.id.text_I);
            letter_O= (TextView) findViewById(R.id.text_O);
            letter_U= (TextView) findViewById(R.id.text_U);
            letter_C= (TextView) findViewById(R.id.text_C);
            letter_T= (TextView) findViewById(R.id.text_T);


            letter_I.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // TODO Auto-generated method stub
                    status=2;
                    return false;
                }
            });
            letter_E.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // TODO Auto-generated method stub
                    status=1;
                    Log.i("ImageStatus",""+status);
                    return false;
                }
            });
            AbsoluteLayout abl=(AbsoluteLayout)findViewById(R.id.absLayout);
            abl.setOnTouchListener(new OnTouchListener() {

                   @Override
                   public boolean onTouch(View v, MotionEvent event) {
                       // TODO Auto-generated method stub
                       Log.i("touch",""+event);

                       if(status==1) // any event from down and move
                       {
                           LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,(int)event.getX()-letter_E.getWidth()/2,(int)event.getY()-letter_E.getHeight()/2);
                           letter_E.setLayoutParams(lp);                      
                       }
                       else if (status==2) {
                           LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,(int)event.getX()-letter_E.getWidth()/2,(int)event.getY()-letter_E.getHeight()/2);
                           letter_I.setLayoutParams(lp);
                    }
                       if(event.getAction()==MotionEvent.ACTION_UP){
                           status=0;
                           letter_E.setBackgroundColor(Color.TRANSPARENT);
                           letter_I.setBackgroundColor(Color.TRANSPARENT);
                       }
                       return true;
                }
            });

            Typeface type= Typeface.createFromAsset(getAssets(), "AlphaBalloon.ttf");

            letterView.setTypeface(type);
            emptyLetterView.setTypeface(type);
            letter_E.setTypeface(type);
            letter_I.setTypeface(type);
            letter_O.setTypeface(type);
            letter_U.setTypeface(type);
            letter_C.setTypeface(type);
            letter_T.setTypeface(type);
    }

    private boolean dragging = false;
    private Rect hitRect = new Rect();

    @Override
    /**
     * NOTE:  Had significant problems when I tried to react to ACTION_MOVE on letterView.   Kept getting alternating (X,Y) 
     * locations of the motion events, which caused the letter to flicker and move back and forth.  The only solution I could 
     * find was to determine when the user had touched down on the letter, then process moves in the ACTION_MOVE 
     * associated with the mainLayout.
     */
    public boolean onTouch(View v, MotionEvent event) {
            boolean eventConsumed = true;
            int x = (int)event.getX();
            int y = (int)event.getY();

            int action = event.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                    if (v == letterView) {
                            dragging = true;
                            eventConsumed = false;
                    }
            } else if (action == MotionEvent.ACTION_UP) {

                    if (dragging) {
                            emptyLetterView.getHitRect(hitRect);
                            if (hitRect.contains(x, y))
                                    setSameAbsoluteLocation(letterView, emptyLetterView);
                    }
                    dragging = false;
                    eventConsumed = false;

            } else if (action == MotionEvent.ACTION_MOVE) {
                    if (v != letterView) {
                            if (dragging) {
                                    setAbsoluteLocationCentered(letterView, x, y);
                            }
                    }
            }

            return eventConsumed;
    }
    private void setSameAbsoluteLocation(View v1, View v2) {
            AbsoluteLayout.LayoutParams alp2 = (AbsoluteLayout.LayoutParams) v2.getLayoutParams();
            setAbsoluteLocation(v1, alp2.x, alp2.y);


            letterView.setVisibility(View.GONE);
            emptyLetterView.setText("A");
            emptyLetterView.setTextColor(Color.BLACK);
            Toast.makeText(getApplicationContext(), "C for Cat", Toast.LENGTH_SHORT).show();
    }
    private void setAbsoluteLocationCentered(View v, int x, int y) {
            setAbsoluteLocation(v, x - v.getWidth() / 2, y - v.getHeight() / 2);

    }
    private void setAbsoluteLocation(View v, int x, int y) {
            AbsoluteLayout.LayoutParams alp = (AbsoluteLayout.LayoutParams) v.getLayoutParams();
            alp.x = x;
            alp.y = y;
            v.setLayoutParams(alp);
    }
  }

And XML is.....

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/LLayout">


<AbsoluteLayout
    android:id="@+id/absLayout"
    android:layout_width="fill_parent"
    android:layout_height="300dp"
    android:layout_alignParentBottom="true" >


    <TextView
      android:id="@+id/imageView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="10dp"
      android:layout_y="-3dp"
      android:text="A"
      android:textSize="80dp" />

  <TextView
      android:id="@+id/text_"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="73dp"
      android:layout_y="-3dp"
      android:text="E"
      android:textSize="80dp"/>

  <TextView
      android:id="@+id/text_I"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="134dp"
      android:layout_y="-4dp"
      android:text="I"
      android:textSize="80dp" />

  <TextView
      android:id="@+id/text_O"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="196dp"
      android:layout_y="-4dp"
      android:text="O"
      android:textSize="80dp" />

  <TextView
      android:id="@+id/text_U"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="260dp"
      android:layout_y="-4dp"
      android:text="U"
      android:textSize="80dp" />



  <TextView
      android:id="@+id/text_T"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="196dp"
      android:layout_y="131dp"
      android:text="T"
      android:textSize="80dp" />

  <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="120dp"
      android:layout_y="128dp"
      android:text="A"
      android:textColor="#ffff9f"
      android:textSize="80dp" />

  <TextView
      android:id="@+id/text_C"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="45dp"
      android:layout_y="129dp"
      android:text="C"
      android:textSize="80dp" />

 </AbsoluteLayout>
 <AbsoluteLayout
    android:id="@+id/absLayoutNew"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
 </AbsoluteLayout>

 <TextView
     android:id="@+id/text_E"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="H"
     android:textSize="80dp" />

Silly me... After looking at it more carefully, I realized it is your fundamental approach that is wrong. You want to set the onTouchListener on the ball's ImageView. I'd actually just create a ball object, you're bound to want to do something with them later. The raw coordinates should work just as well there as anywhere, so... Give that a shot, and let me know how it works.

The problem is with the LinearLayout ,as it has its views related to each other , horizontally or vertically. Simply change your layout to FrameLayout or to the deprecated AbsoluteLayout. That would work just fine for you.

I'm trying to write a similar program and have the same problem. It seems to me that it's possible to have only one "onTouchListener" in the whole program. I use FrameLayout and when I touch the screen I want a new ball to appear. It works when I define "FrameLayout.setOnTouchListener"

If I touch existing ball I want to drag it somewhere. It works when "Ball.setOnTouchListener" is defined.

But when I use both "setOnTouchListeners" than only one of them works.

So I think that Android can work with only one "setOnTouchListener" and in it you have to somehow (I don't know how) check which dynamically created ball was touched and process it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top