添加视图会使片段中的ListView刷新

时间:2014-04-09 18:37:41

标签: android android-layout listview android-fragments android-listview

这可能有点难以解释,所以我能想到的最佳方式是为您提供一个显示问题的视频。

在视频中我自己滚动列表视图,5秒后,创建一个视图并添加到底部的持有者中。在那一刻,listview被刷新。

http://tinypic.com/player.php?v=vpz0k8%3E&s=8#.U0VrIvl_t8E

问题如下:

我的活动布局包含:

  1. Fragment(在RelativeLayout上方),匹配parent,匹配parent。
  2. RelativeLayout,as wrap content。
  3. 片段显示一个ListView,其中包含每行的动画。

    如果我在“RelativeLayout”上添加一个View,它会使片段重新调整为新的大小,因为它设置在此RelativeLayout之上,因此每个Row都会重新重建。

    你们想以任何方式避免这种情况吗?

    编辑:源代码: https://bitbucket.org/sergicast/listview-animated-buggy

3 个答案:

答案 0 :(得分:5)

如果添加的页脚视图的布局过程正在运行,请不要启动动画。可以使用ViewTreeObserver确定布局过程的结束(开始显然从添加页脚视图开始):

    hand.postDelayed(new Runnable() {

        @Override
        public void run() {
            ViewTreeObserver viewTreeObserver = holder.getViewTreeObserver();
            viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
                @SuppressWarnings("deprecation")
                @Override
                public void onGlobalLayout() {
                    holder.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    mIgnoreAnimation = false;
                }
            });

            mIgnoreAnimation = true;
            holder.addView(viewToAdd);
        }
    }, 5000);

将此方法添加到您的活动:

public boolean ignoreAnimation() {
    return mIgnoreAnimation;
}

并在片段中查看:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Context context = FragmentTest.this.getActivity();

    TextView tv = new TextView(context);
    tv.setText("Pos: " + position);
    tv.setTextSize(35f);

    if (runAnimation()) {
        Animation anim = AnimationUtils.loadAnimation(context, R.anim.animation);
        tv.startAnimation(anim);
    }

    return tv;
}

private boolean runAnimation() {
    Activity activity = getActivity();
    if (activity != null && activity instanceof MainActivity) {
        return ! ((MainActivity)activity).ignoreAnimation();
    }
    return true;
}

当然整个Activity - Fragment通信可以大大改进,但是这个例子让你了解如何解决这个问题。

虽然它阻止动画启动,但它并不会阻止ListView刷新,尽管用户不会注意到。如果您担心性能,可以通过重新使用视图来改进适配器代码:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Context context = FragmentTest.this.getActivity();
    TextView tv = null;
    if (convertView != null && convertView instanceof TextView) {
        tv = (TextView) convertView;
    }
    else {
        tv = new TextView(context);
    }

答案 1 :(得分:0)

是的,我可以想出解决这个问题的可行方法。

你的问题是:

  1. 您已将holder的布局参数设置为wrap_content。默认情况下,当它没有内容时,它是"零大小的"在底部的某个地方,对你来说是不可见的(就Android来说,不是不可见的,不过,sic!)
  2. 当您向此holder添加视图时,框架会理解,holder容器的大小现在不同了。但是这个容器是另一个容器的孩子 - 你的 root RelativeLayout,反过来又包含另一个孩子 - 你的<fragment>
  3. 因此,框架决定,根容器与其子项一起应该再次布局。这就是您的列表无效并重新绘制的原因。
  4. 要修复列表获取无效并重新绘制的问题,只需为holder指定一些固定的布局参数即可。例如:

    <RelativeLayout
        android:id="@+id/holder"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" >
    </RelativeLayout>
    

    这将阻止重新绘制列表。但在这种情况下,您将从一开始就显示holder

答案 2 :(得分:-1)

是。这是 RelativeLayout

的预期行为

您正在将 ListView Fragment 和TextView添加到RelativeLayout中,因此,只要子视图维度发生更改,就会影响RelativeLayout中的其他子项。

因此,当您添加新的TexView时,即使其高度为match_parent,另一个子Fragment也会受到影响。

您只能通过将父版面更改为 LinearLayout 来解决此问题。