【问题标题】:How to correctly use TextSwitcher in ListView?如何在 ListView 中正确使用 TextSwitcher?
【发布时间】:2011-05-23 18:44:50
【问题描述】:

ListView 中每条记录的 TextSwitcher 应显示第一个值 (text1),然后显示另一个值 (text2),然后再次显示第一个值,依此类推.只有当 text2 不为空时才会发生。否则 text1 应该总是显示(没有任何变化和动画)。

我创建了Runnable(),它将布尔变量 (time2) 更改为调用 items.notifyDataSetChanged()。它按预期工作,结果setViewValue() for my 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 时,它首先将显示的值更改为其他值(来自另一条记录!),然后播放动画。 text2text1 的更改发生正确。

我的理解是原因如下 - 在显示 text2 之前,itemTime 的所有视图都被删除,因此它被重新创建,这就是为什么会显示一些其他值的原因。但为什么它显示出其他记录的价值呢?

实际上 text2text1 是来自数据库的值,例如。 text2 = cursor.getString(cursor.getColumnIndexOrThrow(DbAdapter.KEY_TIME_2)),可能是这里出了点问题,setViewValue 调用了错误的参数?

更新。 text1text2setViewValue 的数据库中读取。以下是完整代码示例:

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

【问题讨论】:

    标签: android sqlite android-listview


    【解决方案1】:

    我知道这可能无法直接回答问题,但我会回复您关于创建 Runnable() 来为您完成切换工作的评论,因为我怀疑它可能会弄乱您的数据(很难告诉你什么时候看不到完整的代码)。

    我建议您使用ViewFlipper 而不是TextSwitcher。这样做的原因是,一旦您在ViewFlipper 中添加了TextView,您就可以设置翻转间隔,然后开始翻转,它会自动为您完成。

    就这么简单:

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

    在您描述的当前方法中,当您调用items.notifyDataSetChanged() 时,您会遭受巨大的性能损失,因为您的数据库的所有项目都将被重新读取,并且您的列表将再次“重新绘制”。仅当您的实际数据真的发生变化时,您才应该这样做,而不是使用它在您已经拥有的文本之间切换,并且不会从创建时更改。

    令人惊讶的是,您可能会注意到您的问题消失了,因为您不必再​​次从 DB 中重新读取所有内容,并且减少了 item1 和 item2 混淆的机会,因为您只需要阅读在您的 ListView 中创建行时它们一次

    只要我的 2 美分。

    告诉我进展如何。

    【讨论】:

    • 谢谢,@wnafee。您能否澄清一下我需要在哪里(在什么时候,以什么方法)将我的视图(TextViews)添加到 ViewFlipper?
    • 我会将switch 语句case R.id.timetext 下的代码替换为新的ViewFlipper 代码。在那里你可能会设置你的ViewFlipper,然后在其中添加你的 2 个文本视图,然后设置翻转间隔,然后调用开始翻转,然后你就可以开始了。 (顺便说一句,您上面的代码没有显示您从cursor 获取文本的位置,因此很难看出您在什么时候实际从数据库中检索数据,但我认为它在setViewValue() 但您省略了它。您应该根据传递给您的columnIndex 在其中进行cursor 查找)
    • @wnafee,我已经更新了问题,并解释了我如何从数据库中读取我的值。
    • @LA_,感谢更新。最有可能的是,问题在于listViews 使用的convertView 的概念。基本上,列表重用离开屏幕的行项目(例如,用户滚动和行滚动离开屏幕)并将它们发送到屏幕上的下一行使用和重新填充。如果您在输入新信息之前没有清除该回收视图中的所有文本项,您可能会看到来自其他行的旧数据仍在其中。尝试清除 view 对象中的所有内容,然后再向其中添加内容。这与 codefusionmobile 发布的内容一致。
    • @wnafee,itemTime.removeAllViews(); 不会清除视图中的所有内容吗?或者,我应该每次都这样做吗(不仅仅是if (itemTime.getChildCount() != 2))?
    【解决方案2】:

    我想我明白这里发生了什么,这是因为 ListView 的工作方式。

    ListView 在内部回收它的所有视图,这样您就可以创建尽可能多的视图在屏幕上显示。但是,这也意味着,当您在 setViewValue 方法中将值绑定到视图时,并不总是会获得与之前列表中相同位置的视图。

    假设您有三个列表项:按顺序排列的 itemA、itemB、itemC。每个分别包含 text1、text2 和 text3。

    当您调用items.notifyDataSetChanged() 时,ListView 会回收所有这些列表项,但感觉如何,因此您可能会得到 itemC、itemA、itemB 的新顺序;然后文本将显示为 text3、text1、text2。

    因此,当您将第一个列表项的文本更改为“text2”时,您实际上会看到“text3”更改为“text2”,而不是像您一样从“text1”转换为“text2”期待。

    【讨论】:

    • @LA_ 完全正确。 ListView 正在重用之前保存另一条记录的 TextSwitcher。
    【解决方案3】:

    text1 和 text2 是否存储在资源文件 (res/values/strings.xml) 中?如果是这样,Android 有时会混淆变量。只需在此项目上运行 Project > Clean 即可解决问题。

    【讨论】:

    • 不,它们来自数据库,而不是资源。
    【解决方案4】:

    这对我有用:

    myViewFlipper.setFlipInterval(1000);
    myViewFlipper.startFlipping();
    

    【讨论】:

      猜你喜欢
      • 2019-11-08
      • 2021-08-05
      • 1970-01-01
      • 2019-06-17
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 2012-03-10
      相关资源
      最近更新 更多