如何强制重绘列表视图?

Posted

技术标签:

【中文标题】如何强制重绘列表视图?【英文标题】:How to force redraw of listview? 【发布时间】:2012-06-22 19:21:26 【问题描述】:

这个问题与其他类似标题的问题略有不同。我不是在尝试更新列表中的数据,而是在尝试更新列表的 look

我的应用是基于片段的,使用支持库。我有一个 PreferenceActivity,我允许用户在列表中设置他们想要的文本颜色(适配器读取首选项并设置颜色)。这在大多数情况下都按预期工作。

我遇到的问题如下。当我在屏幕上有列表(它是 ListFragment)并拉出菜单时,选择 Preferences 并更改颜色首选项。从 PreferenceActivity 返回列表后,我似乎无法让列表使用指定的新颜色重新绘制自身。

如果我离开列表并返回它,它会使用新颜色重新生成。

我正在尝试使用onResume 进行更改。我目前拥有的代码(似乎对列表没有任何作用,但会更改标题颜色):

@Override
public void onResume() 
    super.onResume();
    header.setTextColor(MyApplication.header);
    line.setBackgroundColor(MyApplication.header_line);
    subheader.setTextColor(MyApplication.header);
    getListView().invalidateViews();

我试过invalidateViewsinvalidate。绝望中我尝试在适配器上调用notifyDataSetChanged,即使数据本身没有变化。似乎没有任何效果。

我是否遗漏了一些明显的东西,或者没有办法做到这一点?

编辑

我的适配器中的“getView”方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) 
    if (convertView == null)
        convertView = View.inflate(context, layout, null);
    View row = convertView;
    c.moveToPosition(position);
    TextView first = (TextView) convertView.findViewById(R.id.ListItem1);
    TextView second = (TextView) convertView.findViewById(R.id.ListItem2);
    TextView third = (TextView) convertView.findViewById(R.id.ListItem3);
    TextView fourth = (TextView) convertView.findViewById(R.id.ListItem4);

    DecimalFormat df = new DecimalFormat("0.00");
    Double hold = Double.valueOf(c.getString(3));
    Double qty = Double.valueOf(c.getString(1));
    Double total = hold * qty;

    String color = "#FF00FF";
    first.setText(c.getString(2));
    first.setTextColor(MyApplication.shoplistitem_name);
    second.setText(c.getString(4));
    second.setTextColor(MyApplication.shoplistitem_desc);
    third.setText(c.getString(1));
    third.setTextColor(MyApplication.shoplistitem_qty);
    fourth.setText("$" + df.format(total));
    fourth.setTextColor(MyApplication.shoplistitem_desc);

    if (strikethroughState[position] == 1) 
        first.setPaintFlags(first.getPaintFlags()
                | Paint.STRIKE_THRU_TEXT_FLAG);
        second.setPaintFlags(second.getPaintFlags()
                | Paint.STRIKE_THRU_TEXT_FLAG);
        third.setPaintFlags(third.getPaintFlags()
                | Paint.STRIKE_THRU_TEXT_FLAG);
        fourth.setPaintFlags(third.getPaintFlags()
                | Paint.STRIKE_THRU_TEXT_FLAG);
        row.setBackgroundColor(MyApplication.shoplistitem_checked);
     else 
        first.setPaintFlags(first.getPaintFlags()
                & ~Paint.STRIKE_THRU_TEXT_FLAG);
        second.setPaintFlags(second.getPaintFlags()
                & ~Paint.STRIKE_THRU_TEXT_FLAG);
        third.setPaintFlags(third.getPaintFlags()
                & ~Paint.STRIKE_THRU_TEXT_FLAG);
        fourth.setPaintFlags(third.getPaintFlags()
                & ~Paint.STRIKE_THRU_TEXT_FLAG);
        row.setBackgroundResource(R.color.black);
    
    return (row);

【问题讨论】:

【参考方案1】:

notifyDataSetChanged() 当然应该为你工作。您如何处理偏好更改?如果您只是将首选项提交给 SharedPreferences 那么它永远不会更新静态 MyApplication 变量。您可以发布用于设置首选项的代码吗?如果您不使用它,请为颜色首选项设置onPreferenceChangedListener(),以便在更改时设置该静态变量。

【讨论】:

嗯...这为我找到问题指明了方向...我感到非常愚蠢。我打电话给MyApplication.setPreferences。方法是MyApplication.setPrefs叹息【参考方案2】:

你应该在你的适配器上调用notifyDataSetChanged()。

【讨论】:

您是否错过了我在帖子中说我尝试过但没有成功的部分?刚刚又试了一次,还是一样。没有重绘视图。 您可以从适配器发布您的 getView() 方法吗? 您在 getView() 的哪个位置将文本的颜色设置为首选项中的颜色? first.setTextColor(MyApplication.shoplistitem_name);。当 PreferenceActivity 退出时,它会从 MyApplication 调用一个方法,该方法将所有首选项读入静态变量中,以便在整个应用程序中使用。 hasStableIds() 是否返回 false?如果不是,当你在 hasStableIds() 中返回 false 时会发生什么?【参考方案3】:

Invalidate、invalidateviews、notifyDatasetChanged,对我没用! 要更新列表视图(使用 cursoradapter),我只是这样做:

cur = db.rawQuery( "SELECT * FROM ssnt WHERE mid = 1000" ); //optional, initial query
adapter.changeCursor(cur); // or swapCursor(), cur is the initial and the only cursor 

但要获得正确的背景颜色、可绘制、下划线文本,我只是这样做:

cur = db.rawQuery( "SELECT * FROM ssnt WHERE mid = 1000" );
adapter.changeCursor(cur);
list.setAdapter(adapter);    //just like I did oncreate

我不喜欢 Barak 解决方案,因为它看起来很重,并且在不需要时执行代码。

【讨论】:

以上是关于如何强制重绘列表视图?的主要内容,如果未能解决你的问题,请参考以下文章

目标 C. ScrollView:每次用户滚动时如何强制它重绘可见部分?

如何在 NSScrollView 中强制重绘内容

如何重绘标签栏控制器显示的视图

如何在更改其边界的动画期间强制重绘 CALayer

在缩放/变换上强制重绘 UIView 或 CALayer

如何在 TouchEvent 之后重绘视图?