java - 尝试在 RecyclerView 中添加新元素时,某些项目重复

标签 java android android-recyclerview

我创建了一个游戏,用户需要在回收器 View 中输入玩家的姓名才能开始游戏。
我的问题是,当我尝试添加新玩家时,每 8 或 9 个玩家,输入的名字就会重复。
我尝试在网上搜索原因,但没有成功找到解决方案,而且真的看不出问题出在哪里。
此外,当我修改重复的名称时,它还会更改回收器 View 中该名称的每个实例。
该 Activity 运行良好,当游戏开始时,输入的每个名称都在游戏中,没有重复。

编辑:我添加了holder.playerName.getText().clear();在适配器类的 onBindViewHolder 中,它纠正了重复问题,但又创建了另一个问题:我现在有空的 EditText,没有任何提示(其中 EditText 应该提示玩家编号)

编辑2:将holder.playerName.getText().clear()行放在onBindViewHolder方法中的holder.playerName.setHint(players.get(position).getName())行下就可以了! 谢谢!

以下是该 Activity 的代码:

 public class PlayersNameScreen extends AppCompatActivity {

  public PlayerMenu playerMenu;                           // A PlayerMenu used to populate the screen when started
  public static PlayerMenu playerMenu1;                   // A static PlayerMenu to store all the players entered on this screen and access it on the next

  private RecyclerView listOfPlayers;                     // The recycler view where the players can see, add and enter other players
  private ListOfPlayersAdapter listOfPlayersAdapter;      // The adapter for the recycler view

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      initializeScreen();
  }

  /**
   * Sets the contents of the screen
   */
  private void initializeScreen() {

      setContentView(R.layout.activity_players_name_screen);

      listOfPlayers = findViewById(R.id.playerNames);
      // The button used to add a player
      FloatingActionButton addPlayer = findViewById(R.id.addPlayer);

      // Start the game with the new players entered, filtering the menu as well
      // The button to start the game
      Button startGame = findViewById(R.id.Booze);
      startGame.setOnClickListener(view -> {
          playerMenu1 = new PlayerMenu();
          playerMenu1.removeAllPlayers();
          playerMenu1.addAllPlayers(playerMenu.getPlayers());
          playerMenu1.filter();
          goToCardScreen();
      });

      playerMenu = new PlayerMenu();

      // Set the default view of the list
      setListOfPlayersView(playerMenu.getPlayers());

      // Adds a row to the list and a player to the menu, scrolls to the new player entered
      addPlayer.setOnClickListener((View view) -> {
          playerMenu.addPlayer(playerMenu.size());
          listOfPlayersAdapter.notifyItemInserted(playerMenu.size() - 1);
          listOfPlayers.smoothScrollToPosition(playerMenu.size() - 1);
      });

  }

  /**
   * Creates the list of all the players (the view)
   * @param playerz the list of the players
   */
  void setListOfPlayersView(ArrayList<Player> playerz) {
      listOfPlayersAdapter = new ListOfPlayersAdapter(playerz);
      RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());

      listOfPlayers.setLayoutManager(layoutManager);
      listOfPlayers.setItemAnimator(new DefaultItemAnimator());
      listOfPlayers.setAdapter(listOfPlayersAdapter);

  }

  /**
   * Before launching the game, check that the names are correct
   */
  private void goToCardScreen() {
      Set<String> set = new HashSet<>(playerMenu1.getPlayersNames());
      boolean playersNameOK = true;
      boolean playersEntered = true;
      boolean enoughPlayers = true;

      if (set.size() < playerMenu1.getPlayers().size()) {
          // Shows a message that the player entered duplicated names
          playersNameOK = false;
      }

      if (set.isEmpty()) {
          // Shows a message saying they need to enter players
          playersEntered = false;
      }

      if (set.size() == 1) {
          // Shows a message showing that there aren't enough players
          enoughPlayers = false;
      }

      if (playersNameOK && playersEntered && enoughPlayers) {
          createWaiver(); --> eventually leads to next activity
      }
  }
}

这是适配器的代码

 public class ListOfPlayersAdapter extends RecyclerView.Adapter<ListOfPlayersAdapter.MyViewHolder>{

  private ArrayList<Player> players; // The array to old every player entered

  @NonNull
  @Override
  public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.player_name_row, parent, false);
      return new MyViewHolder(itemView);
  }

  @Override
  public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
      int x = holder.getLayoutPosition();
      // If a real name was entered (names that don't include the string <player>), set the text of the EditText to the name of the player
      if (!players.get(x).getName().contains("Player")){
          holder.playerName.setText(players.get(x).getName());
      }
      else {
          // Keep hinting the player number (aka Player x)
          holder.playerName.setHint(players.get(position).getName());
          holder.playerName.getText().clear();
      }
  }
      @Override
  public int getItemCount() {
      return players.size();
  }

  ListOfPlayersAdapter(ArrayList<Player> players) {
      this.players = players;
  }

  class MyViewHolder extends RecyclerView.ViewHolder {

      private EditText playerName;

      MyViewHolder(View itemView) {
          super(itemView);
          playerName = itemView.findViewById(R.id.playerInput);

          playerName.addTextChangedListener(new TextWatcher() {
              @Override
              public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

              @Override
              public void onTextChanged(CharSequence s, int start, int before, int count) {
                  Player playerBis = new Player(s.toString());
                  players.set(getAdapterPosition(),playerBis);
              }

              @Override
              public void afterTextChanged(Editable s) {
              }
          });
      }
  }
 }

这是播放器菜单的代码:

 class PlayerMenu {
  private ArrayList<Player> players; // List to store every player

  PlayerMenu() {
      // Creating and adding the players to the menu
      players = new ArrayList<>();

      Player player1 = new Player("Player 1");
      Player player2 = new Player("Player 2");
      Player player3 = new Player("Player 3");

      players.add(player1);
      players.add(player2);
      players.add(player3);
  }

  /**
   *
   * @param i The position of the player in the list
   * @return The name of the player
   */
  String getPlayer(int i) {
      return players.get(i).getName();
  }

  /**
   * Method to add a player in the menu
   */
  void addPlayer(int position){
      Player player = new Player("Player" + " " + (players.size() + 1));
      players.add(position, player);
  }

  /**
   * Method to add all players from an ArrayList to the players array list
   * @param playerz The ArrayList we want to get the players from
   */
  void addAllPlayers(ArrayList<Player> playerz) {
      players.addAll(playerz);
  }

  /**
   * Method to remove all players from the list
   */
  void removeAllPlayers() {
      players.clear();
  }

  /**
   * To see the list of players
   * @return the list of all the players
   */
  ArrayList<Player> getPlayers() {
      return players;
  }

  /**
   * Remove from the list of players all those who are nameless (aka Player i)
   */
  void filter() {
      players.removeIf(player -> player.getName().toLowerCase().contains("player")) || player.getName().isEmpty()));
  }

  /**
   * Size of the list
   * @return the size of the list of players
   */
  public int size() {
      return players.size();
  }
 }

When the activity screen loads and when we press on the "+" button

Adding a new player called Bob, and scrolling down: Bob is duplicated

If we add a new player John (at the top)...

...and press on the "+" button, John is also duplicated

If we keep pressing the "+" button, every 6-9 times, the names entered are duplicated

If we replace one of the player's name (here John) with another name (Karen)...

... and scroll back up, we can see that some instances of John are replaced with karen

最佳答案

尝试在您的bindviewholder方法中添加以下代码:

     @Override
  public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
      int x = holder.getLayoutPosition();
      // If a real name was entered (names that don't include the string <player>), set the text of the EditText to the name of the player
      if (!players.get(x).getName().contains("Player")){
          holder.playerName.setText(players.get(x).getName());
      }
      else {
          holder.playerName.setText("")
          // Keep hinting the player number (aka Player x)
          holder.playerName.setHint(players.get(position).getName());
      }
  }

holder.playerName.setText("") You need to add some value in else condition also, as recyclerview recycles the items and hence you are getting duplicate items.

希望这有帮助!

关于java - 尝试在 RecyclerView 中添加新元素时,某些项目重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57825794/

相关文章:

java - Spring 4.0.6 与 quartz 1.8.6 : setCronExpression method is not exposed to CronTriggerBean class

java - 更新安卓图库

java - 如何显示上一个和下一个列表项的详细信息

android - 滚动时图像和文本进入标题

java - 如何在recyclerview中使用listview?

android - RecyclerView android 中的 ScrollView

java - 在 Java 和 SOAPUI 中使用 Web 服务

Java Swing GUI 客户端和服务器聊天应用程序 TextArea 未更新

android - 多个倒数计时器 recyclerview

java - 不显示在 GridLayout 的 JPanel 中