2015-05-29 5 views
0

Я разработчик новичка Android и проблема с крошечным Android-приложением, которое я разрабатываю, что, как я подозреваю, связано с сроками создания динамического представления. Это небольшое приложение для подсчета очков, и у него есть динамически созданные игровые кнопки и текстовые поля, определенные в классе Player. Вот отрывок о том, как я это делаю:Android - проблема с динамическим просмотром времени?

public Player(String name, int score, int number, boolean enabled, RelativeLayout mainScreen, List<Button> presetButtonList, Editor editor, Context context) { 
      super(); 
      this.name = name; 
      this.score = score; 
      this.number = number; 
      this.enabled = enabled; 
      this.editor = editor; 

      // Get the lowest child on the mainScreen 
      Integer count = mainScreen.getChildCount(), lowestChildId = null; 
      Float lowestChildBottom = null; 
      for (int i = 0; i < count; i++) { 
       View child = mainScreen.getChildAt(i); 
       if ((lowestChildId == null || child.getY() > lowestChildBottom) && 
         !presetButtonList.contains(child)) { 
        lowestChildId = child.getId(); 
        lowestChildBottom = child.getY(); 
       } 
      } 

      playerNameText = (EditText) setTextViewDefaults(new EditText(context), name); 
      playerNameText.setSingleLine(); 
    //  playerNameText.setMaxWidth(mainScreen.getWidth()); 
    //  playerNameText.setEllipsize(TextUtils.TruncateAt.END); //TODO: Prevent names which are too long for screen 
      playerNameText.addTextChangedListener(new TextWatcher() { 

        public void afterTextChanged(Editable changedText) { 
         setName(changedText.toString()); 
         updateScreen(); 
        } 

        public void beforeTextChanged(CharSequence changedText, int start, int count, int after) {} 

        public void onTextChanged(CharSequence changedText, int start, int before, int count) {} 
       }); 
      RLParams = new RelativeLayout.LayoutParams(
        RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
      if (lowestChildId != null) { 
       RLParams.addRule(RelativeLayout.BELOW, lowestChildId); 
      } else { 
       RLParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); 
       RLParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 
      } 
      RLParams.setMargins(0, 10, 0, 10);  
      mainScreen.addView(playerNameText, RLParams); 

класс дополнительно определяет кнопки и т.д. аналогичным образом, совместив верхние части с точки зрения название текста. Я называю это, когда пользователь нажимает кнопку, чтобы добавить плеер, и он отлично работает, отображая каждого игрока ниже первого по экрану. Проблема возникает, когда я загружаю кучу сохраненных игроков в начале. Вот где я нагрузить игроков:

public void loadData() { 
     RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout); 
     playerCount = savedData.getInt("playerCount", playerCount); 
     Player player; 
     String name; 
     playerList.clear(); 
     for (int i=1; i<=playerCount; i++) { 
      name = savedData.getString("name" + i, null); 
      if (name != null) { 
       Log.v("name", name); 
       player = new Player(name, savedData.getInt("score" + i, 0), i, savedData.getBoolean("enabled" + i, false), mainScreen, presetButtonList, editor, this);    
       playerList.add(player); 
       player.updateScreen(); 
      } 
     } 
     updateScreen(); 
    } 

Наконец, я называю метод LoadData() при запуске приложения, здесь:

@Override 
protected void onCreate(Bundle savedInstanceState) {   
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    savedData = this.getPreferences(Context.MODE_PRIVATE); 
    editor = savedData.edit(); 

    presetButtonList.add((Button)findViewById(R.id.newGame)); 
    presetButtonList.add((Button)findViewById(R.id.addPlayer)); 
    presetButtonList.add((Button)findViewById(R.id.removePlayer)); 

    loadData();  
} 

Результат? Когда загружается более двух игроков, все игроки загружаются в одно и то же место поверх Игрока 2.

Я подозреваю, как-то, что игроки все сгенерированы в одно и то же время и, следовательно, все считают, что самый низкий игрок - игрок 1, а не проверка друг друга. Я попытался запустить загрузку позже, чем onCreate(), и это все еще происходит. Я также попытался добавить 3-секундный сон в цикл for loadData() после того, как каждый игрок загрузится, чтобы посмотреть, помогло ли это, но не повезло.

Я делаю плохие предположения? Что я делаю неправильно и как я могу это исправить?

+0

Я начинаю думать, что мне нужно выяснить способ заставить экран рисовать после того, как каждый игрок загрузится. Я отправлю сюда, если я это выясню, и если это сработает. – Drake3

ответ

0

Я подозреваю, что здесь происходит то, что вы пытаетесь позиционировать представления, у которых нет идентификаторов (похоже, вы не устанавливаете их нигде в своем коде). Динамически создаваемые виды автоматически не имеют идентификаторов, поэтому звонок getId() вернет NO_ID (See documentation). Если вы хотите использовать ID, вам нужно будет установить его самостоятельно, используя View.setId().

+0

Метод setTextViewDefaults() фактически устанавливает это вместе с некоторыми другими общими параметрами. Я установил его с помощью textView.setId (View.generateViewId()); – Drake3

0

В конце концов, это был вопрос времени. Мне нужно было дождаться загрузки основного экрана, прежде чем я смогу добавить к нему представления. К сожалению, он никогда не будет загружаться до тех пор, пока все действия в потоке пользовательского интерфейса не будут завершены.

Таким образом, мне нужна резьба. Я в конечном итоге положить LoadData() в потоке, как это:

new Thread(new loadDataAsync(this)).start(); 



class loadDataAsync implements Runnable { 

    MainActivity mainActivity; 

    public loadDataAsync(MainActivity mainActivity) { 
     this.mainActivity = mainActivity; 
    } 

    @Override 
    public void run() { 
     try { 
      Thread.sleep(700); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     loadData(mainActivity);   
    } 
} 

Затем я создал игроков обратно в потоке пользовательского интерфейса после первого сна, чтобы дать время для UI для загрузки.

runOnUiThread(new Runnable() { 
       Player player; 
       RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout); 
       @Override 
       public void run() { 
        player = new Player(savedData.getString("name" + playerNum, null), savedData.getInt("score" + playerNum, 0), playerNum, savedData.getBoolean("enabled" + playerNum, false), mainScreen, presetButtonList, editor, mainActivity);  
        playerList.add(player); 
        player.updateScreen(); 
        mainScreen.invalidate(); 
       } 
      }); 

Не самое элегантное решение, но оно работает пока.

Смежные вопросы