onClick监听器没有响应

时间:2014-12-23 21:52:38

标签: android onclicklistener android-handler

我正在为我的班级制作一个项目。这就像鼹鼠游戏。我有9个imageView。当你点击它们时,它们会变成一个空洞的预定义图像,如果没有,处理程序会将它改回正常,你将失去生命。但是对于一张照片,如果它出现并且你点击它,你就会失去生命。现在我已将图像修复为后者。如果我非常快地点击它们,显示生命的textView,永远不会更新到游戏结束,任务继续,但如果我慢慢点击,它会更新到游戏结束。我试过调试,发现当我很快点击它们时,代码永远不会转到onClick监听器。

以下是代码:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import Hole;


public class MainActivity extends Activity {

final Activity mainActivityObject = this;
final int MIN_TYPES_OF_MOLES = 0;
final int TYPES_OF_MOLES_INC_INT = 1;
final int MAX_MOLE_LIFE_TIME = 3000;
final int LIFE_TIME_DECREASE_INT = 150;
final int MAX_MOLE_APPEARANCE_INT = 1000;
final int APPEARANCE_TIME_DECREASE_INT = 60;
final int SPEED_UP_TIME_INT = 20000;
final int BOMB_MOLE_ID = 3;
final int MIN_DIFFICULTY_LEVEL = 1;

private Toast toast;
final Handler handler = new Handler();
Runnable moleAliveChecker;
Runnable speedUp;
TextView lives;
TextView tView;

//private ImageView[] holeImage = new ImageView[9];
private Hole[] hole = new Hole[9];
private int totalScore = 0;
private int active = 0;
private int numberOfLives = 3;
private int appearanceInterval = MAX_MOLE_APPEARANCE_INT;
private int moleLifeTime = MAX_MOLE_LIFE_TIME;
private int typesOfMoles = MIN_TYPES_OF_MOLES;
private int speedUpTime = SPEED_UP_TIME_INT;
private int difficultyLevel = MIN_DIFFICULTY_LEVEL;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);// hide the title
    setContentView(R.layout.activity_main);

    tView = (TextView) findViewById(R.id.time_left);
    lives = (TextView) findViewById(R.id.lives_left);
    toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);

    //set images and listener for each hole, ends game if lives < 1
    for(int counter=0;counter<9;counter++)
    {
        int resID=getResources().getIdentifier("hole"+(counter+1),"id",getPackageName());
        hole[counter] = new Hole((ImageView)findViewById(resID), this);

        final int i=counter;//inside the onClickListener, index number has to be final

        hole[counter].getImage().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ImageView image = hole[i].getImage();
                switch ((Integer) image.getTag()) {
                    case R.drawable.hole:
                        break;
                    default:
                        if (numberOfLives < 1) {
                            handler.removeCallbacks(speedUp);
                            lives.setText("GAME OVER!!");
                        }
                        else if (hole[i].getMole().ishit()) {
                            changeScoreAndLives(hole[i], i);
                        }
                        break;
                }
            }
        });
    }

    // gives a time delay of 3 seconds before beginning the game and updates text view
    //  tView every 1 second and when time approaches 0, it starts the game
    final Runnable r = new Runnable() {
        int t = 3;
        public void run() {
            if (t > 0) {
                tView.setText("Game begins in : " + t-- + " Seconds");
                handler.postDelayed(this, 1000);
            }
            else if (t == 0)
            {
                t--;
                tView.setText("Begin!!");
                handler.postDelayed(this, 300);
            }
            else
            {
                if (numberOfLives >= 1) {
                    playGame();
                    handler.postDelayed(this, appearanceInterval);
                }
            }
        }
    };
    handler.postDelayed(r, 1000);

    // speeds up the game after a set interval (20 seconds)
    speedUp = new Runnable() {
        public void run() {
            appearanceInterval -= APPEARANCE_TIME_DECREASE_INT;
            moleLifeTime -= LIFE_TIME_DECREASE_INT;
            typesOfMoles += TYPES_OF_MOLES_INC_INT;
            difficultyLevel++;
            if (difficultyLevel < 6 && numberOfLives >= 1) {
                handler.postDelayed(this, speedUpTime);
            }
            toast.setText("Difficulty Level increased");
            toast.show();
        }
    };
    handler.postDelayed(speedUp, speedUpTime);
}
// end of onCreate

// not been used yet
private void resetOneStep()
{
    if (difficultyLevel > MIN_DIFFICULTY_LEVEL) {
        appearanceInterval += MAX_MOLE_APPEARANCE_INT;
        moleLifeTime += MAX_MOLE_LIFE_TIME;
        typesOfMoles -= MIN_TYPES_OF_MOLES;
        difficultyLevel--;
        handler.postDelayed(speedUp, speedUpTime);
    }
}

// not related to the current problem as currently not being used
public void bombMoleCredit()
{
    for (int count = 0; count < hole.length; count++)
        if (hole[count].getMole() !=null) {
            totalScore += hole[count].getMole().getPoints();
            handler.removeCallbacksAndMessages(count);
            hole[count].setImage(null, mainActivityObject);
        }
    tView.setText("Total Score: " + totalScore);
    active = 0;
}

// called by onclick listener if lives > 0 to change lives, score, and image
public void changeScoreAndLives(Hole hole, int number)
{
    totalScore = totalScore + hole.getMole().getPoints();
    if (hole.getMole().getPoints() < 0) {
        numberOfLives--;
        lives.setText("Lives Left: " + numberOfLives);
    }
    if (hole.getMole().getID() == BOMB_MOLE_ID) {
        bombMoleCredit();
        return;
    }
    handler.removeCallbacksAndMessages(number);
    hole.setImage(null, mainActivityObject);
    active--;
    tView.setText("Total Score: " + totalScore);
}


// called by runnable after a set interval
public void playGame()
{
    if (active == 9)
        return;
    final int holeNumber = (int) (Math.random() * hole.length);
    if (hole[holeNumber].getMole() == null && numberOfLives >= 1) {
        hole[holeNumber].setMoleFromRange(4, 4, this);
        active++;

        // checks if the hole has been clicked or not after a few seconds, if not, player
        // looses a life
        moleAliveChecker = new Runnable() {

            Hole holeToBeChecked = hole[holeNumber];

            public void run() {
                if (holeToBeChecked.getMole() != null && numberOfLives >= 1) {
                    if(holeToBeChecked.getMole().getID() == 4) {
                        holeToBeChecked.setImage(null, mainActivityObject);
                        active--;
                        return;
                    }
                    holeToBeChecked.setImage(null, mainActivityObject);
                    numberOfLives--;
                    active--;
                    TextView lives = (TextView) findViewById(R.id.lives_left);
                    lives.setText("Lives Left: " + numberOfLives);
                    toast.setText("OOPS!! you lost a life. Game Reset");
                    toast.show();
                    //resetOneStep();
                }
            }
        };
        handler.sendMessageDelayed(getPostMessage(moleAliveChecker, holeNumber), moleLifeTime);
    }
    else
        playGame(); // in case the random number choses the image which has the mole
}

// to pass object as a token in postDelayed in handler, to cancel the callbacks
private final Message getPostMessage(Runnable r, Object token) {
    Message m = Message.obtain(handler, r);
    m.obj = token;
    return m;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

除了这个之外,所有其他课程都正常。

其他重要课程: 的 Mole.java

import android.app.Activity;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

import java.io.InputStream;

public class Mole
{
   public static final int DEFAULT_ID = 0; // regular mole ID

   // private methods
   private JSONParser parser;
   private JSONObject mole;
   private int ID, timesToBeHit, timesHit, points;
   private String name;
   private JSONArray moles;
   private boolean active;

   public Mole(int ID, Activity map)
   {
       try {
           // initialize and read json and convert each object to jsonArray
            parser = new JSONParser();
           // tries to set the value set by user. If fails, sets the default value
           if (!setMoleByID(ID, map))
               setMoleByID(DEFAULT_ID, map);
       }
       catch (Exception e)
       {
           e.printStackTrace();
       }
   }

   // helper for constructor
   private boolean setMoleByID(int ID, Activity map) throws Exception
   {
       InputStream is = map.getAssets().open("moles.json");
       int size = is.available();
       byte[] buffer = new byte[size];
       is.read(buffer);
       is.close();
       String json = new String(buffer, "UTF-8");

       moles = (JSONArray)parser.parse(json);
      // go through each object in array moles
      for ( Object obj : moles)
      {
         // convert oobject to jsonObject
         mole = (JSONObject) obj;

         // if id matches it leaves the mole to be that jsonObject and exits 
         // the loop
         if ((long)mole.get("ID") == ID)
            break;
      }

      if ((long)mole.get("ID") != ID)
         return false;

      // initialize private data so that we don't have to rely on json 
      // anymore after this step
      this.ID = (int)(long)mole.get("ID");
      name = (String)mole.get("name");
      timesToBeHit = (int)(long)mole.get("timesToBeHit");
      timesHit = 0;
      points = (int)(long)mole.get("points");

      return true;
   }

   // get methods
   public int getID() { return ID; }
   public String getName() { return name; }
   public int getTimesHit() { return timesHit; }
   public int getTimesToBeHit() { return timesToBeHit; }
    public int getPoints() { return points; }

   public boolean ishit()
   {
       if (timesHit >= timesToBeHit - 1)
         return true;
      timesHit++;
      return false;
   }

   public static int getTotalTypesOfMoles() throws Exception
   {
       return 5;
   }
}

Hole.java

import android.app.Activity;
import android.widget.ImageView;

import com.example.phoenix.whac_a_mole03.R;

// NOT completed yet
// HOLE Class -----------------------------------------------------------------
public class Hole
{
   private Mole mole;
   private boolean active; // if true then mole is present
   private ImageView image;

   public Hole(ImageView view,final Activity map)
   {
      mole = null;
      image = view;
      setImage(mole, map);
   }

   // sets mole from a random value
   public boolean setMoleFromRange(int minMoleID, 
         int maxMoleID, Activity map)
   {
      try {
          int typesOfMoles = Mole.getTotalTypesOfMoles() - 1;

          // checks for validity of data here
          if (!(minMoleID >= 0 & minMoleID <= typesOfMoles))
              return false;
          if (!(maxMoleID >= 0 & maxMoleID <= typesOfMoles))
              return false;
          if (minMoleID > maxMoleID)
              return false;

          // chooses the random value between a range
          int moleID =
                  (int) (Math.random() * (maxMoleID + 1 - minMoleID)) + minMoleID;
          mole = new Mole(moleID, map);
          setImage(mole, map);

          return true;
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
          return false;
   }

    private void clear()
    {
        mole = null;
    }

   public void setImage(Mole mole, Activity map)
   {
      if (mole == null) {
          image.setImageResource(R.drawable.hole);
          image.setTag(R.drawable.hole);
          clear();
          return;
      }
      int imageID = map.getResources().getIdentifier("mole" + mole.getID() , "drawable", map.getPackageName());
      image.setImageResource(imageID);
      image.setTag(imageID);
      this.mole = mole;
   }

   public boolean hit(Activity map)
   {
       if (!mole.ishit())
           return false;
       setImage(mole, map);
       return true;
   }

   // get methods
   public Mole getMole() { return mole; }
   public ImageView getImage() { return image;}

   // REST STUFF TO BE ADDED HERE-------------
}

activity_main.xml中

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:id="@+id/time_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/lives_left"
        android:layout_alignParentRight="true"
        android:text="Lives Left: 3"
        android:textAlignment="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <GridLayout
        android:columnCount="3"
        android:rowCount="3"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/hole1"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole2"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole3"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole4"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole5"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole6"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole7"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole8"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        <ImageView
            android:id="@+id/hole9"
            android:src="@drawable/hole"
            android:layout_width="100dp"
            android:layout_height="100dp" />
        </GridLayout>

    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/life1"/>
        <ImageView
            android:id="@+id/life2"/>
        <ImageView
            android:id="@+id/life3"/>
        </GridLayout>

</RelativeLayout>

任何图片都可以使用,只要它名为mole4.png,当没有mmole时就可以使用hole.png

非常感谢。我将非常感谢您的帮助

0 个答案:

没有答案