Как правильно использовать TextSwitcher в ListView? - PullRequest
8 голосов
/ 23 мая 2011

My TextSwitcher для каждой записи в ListView должно отображаться первое значение ( text1 ), а затем другое значение ( text2 ), затем снова первое значение и так далее.Это должно произойти, только если text2 не пусто.В противном случае text1 должен всегда отображаться (без каких-либо изменений и анимации).

Я создал Runnable(), который изменяет логическую переменную ( time2 ), чтобы затем вызватьitems.notifyDataSetChanged().Он работает, как ожидалось, и в результате setViewValue() для моего ListView называется.

Вот код:

items.setViewBinder(new SimpleCursorAdapter.ViewBinder() {

    @Override
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
      int viewId = view.getId();
      switch(viewId) {
      case R.id.timetext:
          TextSwitcher itemTime = (TextSwitcher) view;
          if (itemTime.getChildCount() != 2) {
              itemTime.removeAllViews();
              itemTime.setFactory(new ViewSwitcher.ViewFactory() {
                  @Override
                  public View makeView() {
                      TextView t = new TextView(MyActivity.this);
                      t.setTextSize(18);
                      t.setTypeface(null, Typeface.BOLD);
                      t.setTextColor(Color.WHITE);
                      return t;
                    }
                  });
              itemTime.setAnimateFirstView(true);
              itemTime.setInAnimation(AnimationUtils.loadAnimation(MyActivity.this,
                      R.anim.push_up_in));
              itemTime.setOutAnimation(AnimationUtils.loadAnimation(MyActivity.this,
                      R.anim.push_up_out));
          }

          if (!text2.equals("")) {
              if (!time2) {
                  itemTime.setText(text1);
              } else {
                  itemTime.setText(text2);
              }
          } else {
                      itemTime.setCurrentText(text1);
              }
          return true;
      } 
      return false;
    }
  } );

Он работает почти так, как ожидалось.С одним второстепенным элементом - когда нужно показать text2 , он сначала меняет отображаемое значение на какое-то другое значение (из другой записи!), А затем воспроизводится анимация.Изменение text2 на text1 происходит правильно.

Я понимаю, что причина в следующем - перед отображением text2 , все виды itemTime удаляются и, следовательно, воссоздаются, и поэтому на секунду показывается какое-то другое значение.Но почему он показывает значение из какой-то другой записи?

На самом деле text2 и text1 являются значениями из базы данных, например.text2 = cursor.getString(cursor.getColumnIndexOrThrow(DbAdapter.KEY_TIME_2)), возможно, здесь что-то не так и setViewValue вызывается с неверными параметрами?

Upd. text1 и text2 считываются из базы данных на setViewValue.Вот пример полного кода:

itemTime.setText(cursor.getString(cursor.getColumnIndexOrThrow(DbAdapter.KEY_CLOSE_TIME_1)) + " - " + cursor.getString(cursor.getColumnIndexOrThrow(DbAdapter.KEY_OPEN_TIME_1)));

Ответы [ 4 ]

4 голосов
/ 05 июня 2011

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

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

Какпросто, как это:

/* Add your items to your ViewFlipper first */
myViewFlipper.setFlipInterval(1000); //time in millseconds
myViewFlipper.startFlipping();

В вашем текущем методе, который вы описали, когда вы вызываете items.notifyDataSetChanged(), вы получаете огромный удар по производительности, потому что все элементы вашей базы данных будут перечитаны, и ваш список будетбыть "перерисован" снова.Вы должны делать это только в том случае, если ваши фактические данные действительно изменились, вместо того чтобы использовать их для переключения между текстом, который у вас уже есть и не меняется со времени создания.

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

Только мои 2 цента.

Дайте мне знать, как это происходит.

2 голосов
/ 09 июня 2011

Мне кажется, я вижу, что здесь происходит, и это из-за того, как работает ListView.

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

Скажем, у вас есть три элемента списка: itemA, itemB, itemC в этом порядке. Каждый из них сначала содержит текст1, текст2 и текст3 соответственно.

Когда вы вызываете items.notifyDataSetChanged(), ListView перезагружает все эти элементы списка, как ему кажется, поэтому вы можете получить новый порядок itemC, itemA, itemB; и тогда текст будет читать text3, text1, text2.

В результате, когда вы измените текст первого элемента списка на «text2», вы фактически увидите, что «text3» изменится на «text2» вместо перехода от «text1» к «text2», как у вас. ожидая.

0 голосов
/ 25 июля 2016

Это сработало для меня:

myViewFlipper.setFlipInterval(1000);
myViewFlipper.startFlipping();
0 голосов
/ 03 июня 2011

Сохраняются ли text1 и text2 в файле ресурсов (res / values ​​/ strings.xml)?Если это так, Android иногда будет путать переменные.Простое выполнение Project > Clean в этом проекте может решить проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...