【问题标题】:Adding a View makes a ListView within a fragment to refresh添加 View 使片段内的 ListView 刷新
【发布时间】:2014-04-09 18:37:40
【问题描述】:

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

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

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

问题如下:

我有一个布局,其中包含:

  1. 片段(RelativeLayout 上方),匹配父级,匹配父级。
  2. RelativeLayout,作为包装内容。

片段显示一个 ListView,其中包含每一行的动画。

如果我在“RelativeLayout”上添加一个视图,它会使片段重新调整到新的大小,因为它设置在这个RelativeLayout之上,所以每一行都会重新构建。

你们有什么办法可以避免这种情况吗?

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

【问题讨论】:

  • 尝试将此视图添加到列表视图的页脚,看看会发生什么。它可能不会刷新列表视图。
  • View 是由 Activity 生成的,Fragment 不应该关心它。这就是为什么它没有在列表视图中添加为一行。另外,无论用户是否滚动,我都想将其添加到底部。
  • 我认为您应该阅读一些关于页脚的内容。如果您在运行时添加任何内容,总是会进行重新调整。请查看链接,google.com/…。这是一个显示页脚(确定按钮)的图片的链接
  • 您提供的链接实际上做了我已经在做的事情。一个包含 Spinner - ListView - Button 的容器。我的问题是因为:Fragment(ListView Inside) - View
  • 我附上了源代码,你可以自己编译和检查。

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


【解决方案1】:

如果添加的页脚视图的布局过程正在运行,则不要启动动画。可以使用 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);
    }

【讨论】:

  • 我想知道您的方法是否会阻止 ListView 在 OP 设置的条件下失效和重绘
  • 如果你读过我的回答,你会知道它没有,但我想你的问题只是一个修辞问题......我认为问题不在于 ListView 的重绘,而是对用户可见的工件(动画)。没有这些,用户不会注意到任何东西。但是让 OP 决定什么是更好的解决方案,在屏幕上放置一个固定大小的视图(从实际的 ListView 中占用空间)或我的解决方案。
  • 不是修辞的。我很好奇您的解决方法是否真的使重绘过程对用户透明 - 除了 OP 提供的动画。至于我的解决方案 - 我不认为它在 UI 方面是一个好的解决方案,我只是努力描述问题的根源并展示一种可能的方式来处理这一切。又快又脏 :)
  • 我实际上正在考虑一种方法来防止重绘发生(使用忽略某些“事件”的自定义 ListView,例如调用 invalidate() 或 requestLayout() 但是 1)没有t 工作和 2) 抑制布局过程可能不是一个好主意,因为它在将新视图添加到布局时运行是有原因的,并且它可能会产生不希望的副作用来抑制它。
  • 检查我的新“ddd”方法。 i.imgur.com/JsS1D47.png 看起来很干净,而且工作正常。
【解决方案2】:

是的,我可以想办法解决这个问题。

你的问题是:

  1. 您已将holder 的布局参数设置为wrap_content。默认情况下,当它没有内容时,它在底部某处是“零大小”并且对您不可见(但就 Android 而言,不是 invisible,原文如此!)
  2. 当你向这个holder 添加一个视图时,框架会理解你的holder 容器的大小现在不同了。但这个容器是另一个容器的子容器 - 您的 root RelativeLayout,而后者又包含另一个子容器 - 您的 <fragment>
  3. 因此,框架决定,根容器及其子容器应重新布局。这就是为什么您的列表会失效并重新绘制。

要解决列表失效和重绘的问题,只需为您的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

【讨论】:

    【解决方案3】:

    是的。这是 RelativeLayout

    的预期行为

    您正在将ListView Fragment 和TextView 添加到RelativeLayout 中,因此每当子视图尺寸发生变化时,都会影响RelativeLayout 中的另一个子视图。

    所以这里当你添加一个新的 TexView 时,另一个子 Fragment 会受到影响,即使它的高度是 match_parent。

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 2012-09-24
    • 1970-01-01
    相关资源
    最近更新 更多