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

Android 添加视图会使片段中的ListView刷新,android,android-layout,listview,android-fragments,android-listview,Android,Android Layout,Listview,Android Fragments,Android Listview,这可能有点难以解释,所以我能想到的最好的办法是给你提供一个视频来展示这个问题 在视频中,我展示了我自己滚动listview,5秒钟后,一个视图被创建并添加到底部的支架中。此时,listview被刷新 问题如下: 我有一个活动,其布局包括: 片段(位于RelativeLayout上方)、匹配父级、匹配父级 RelativeLayout,作为包装内容 该片段显示一个列表视图,其中包含每行的动画 如果我在“RelativeLayout”上添加一个视图,它会使片段重新调整到新的大小,因为它设置在这个R

这可能有点难以解释,所以我能想到的最好的办法是给你提供一个视频来展示这个问题

在视频中,我展示了我自己滚动listview,5秒钟后,一个视图被创建并添加到底部的支架中。此时,listview被刷新

问题如下:

我有一个活动,其布局包括:

  • 片段(位于RelativeLayout上方)、匹配父级、匹配父级
  • RelativeLayout,作为包装内容
  • 该片段显示一个列表视图,其中包含每行的动画

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

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

    编辑:源代码:
    是的。这是RelativeLayout的预期行为

    您正在将列表视图片段和文本视图添加到RelativeLayout中,因此每当子视图维度发生更改时,都会影响RelativeLayout中的另一个子视图

    因此,在这里,当您添加一个新的TexView时,另一个子片段会受到影响,即使它的高度是match_parent


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

    是的,我可以想出一种可能的方法来解决此问题

    你的问题是:

  • 您已将
    支架的布局参数设置为包装内容。默认情况下,当它没有内容时,它在底部的某个地方是“零大小”的,对你来说是不可见的(但对于Android来说不是不可见的,sic!)
  • 当您将视图添加到此
    holder
    时,框架会理解,
    holder
    容器的大小现在不同了。但是这个容器是另一个容器的子容器,即您的
    相对名
    ,它又包含另一个子容器,即您的
  • 因此,框架决定,根容器及其子容器应该重新布局。这就是为什么您的列表会失效并重新绘制
  • 要解决列表失效和重新绘制的问题,只需为
    持有者指定一些固定的布局参数即可。例如:

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

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

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

    将此方法添加到活动中:

    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;
    }
    
    当然,整个活动片段通信可以得到很大的改进,但该示例为您提供了解决问题的总体思路

    虽然它会阻止动画启动,但不会阻止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的页脚,看看会发生什么。可能它不会刷新listview。视图是由活动生成的,片段不应该关心它。这就是为什么它没有添加为listview中的一行。另外,我想在底部添加它,不管用户是否滚动。我想你应该读一点关于页脚的内容。如果您在运行时添加了任何内容,则始终会进行重新调整。请查看链接。这是一个显示页脚的图片链接(ok按钮)。你提供的链接实际上做了一些我已经在做的事情。包含微调器-列表视图-按钮的容器。我的问题发生的原因是:Fragment(ListView-Inside)-view我已经附加了源代码,您可以自己编译和检查它。明天早上我会尝试一下=)刚刚尝试过,同样的问题也发生了,这是目前的布局:我想知道你的方法是否能阻止ListView在OPIf设置的条件下失效和重新绘制如果你读过我的答案,你会知道它没有,但我猜你的问题只是一个修辞问题。。。我认为问题不在于重新绘制ListView,而在于用户可以看到的工件(动画)。没有这些,用户不会注意到任何东西。但是让OP来决定哪种解决方案更好,在屏幕上放置一个固定大小的视图(从实际的列表视图中去掉空间)还是我的解决方案,而不是修辞性的解决方案。我很好奇,如果你的解决方案真的给用户带来了一个透明的过程-除了OP.为我的解决方案提供的动画之外,我不认为这是一个很好的UI,我只是努力描述问题的根源,并展示了处理这些问题的一种可能的方法。快速和肮脏:)我实际上在考虑一种方法来防止重画发生(使用一个自定义的ListView,它忽略某些“事件”,比如调用invalidate()或requestLayout(),但是1)这不起作用,2)抑制布局过程可能不是一个好主意,因为它在向布局添加新视图时运行是有原因的,抑制它可能会产生不希望的副作用。请检查我的新“ddd”方法。看起来很干净,很有效。
    @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);
        }