滚动视图中的ListView我的滚动视图移动到列表视图的顶部。我该如何防止这种情况?

时间:2012-02-21 22:58:21

标签: java android android-layout

我的滚动视图中有一个listview,在此之前几乎有一页滚动,但是一旦我的listview被填充,滚动视图就会移动到列表视图的顶部。我该如何解决这个问题?防止这种情况发生?

滚动浏览XML:

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include 
            layout="@layout/a" />

        <include 
            layout="@layout/b" />

        <include 
            layout="@layout/c" />

        <include 
            layout="@layout/d" />


<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

我试过了           sv.fullScroll(ScrollView.FOCUS_UP); 以及所有那些东西到我的滚动视图但它不起作用

13 个答案:

答案 0 :(得分:9)

我们绝不应将ListView放在ScrollView内。

解决方法:当ScrollView由于列表视图notifyDataSetChanged()而向上/向下移动时, 然后试试,

scrollview.setEnabled(false);
listview.setFocusable(false);
adapter.notifyDataSetChanged();
scrollview.setEnabled(true);

答案 1 :(得分:8)

首先,您可能已经听说过,但以防万一:您永远不应将ListView放在ScrollView 中,因为ListView本身已经有一个ScrollView,这个设计违背了整个ListView的想法。如果你确信你必须使用它,可能有一个更好的使用方法,你可能需要以某种方式简化你的代码。

现在,即使您仍想使用类似的东西,也可以使用以下内容:

package your.package.name;

import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;

public class ScrollingListView {
  public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter(); 
    if (listAdapter == null)
      return;

    int totalHeight = 0;
    for (int i = 0; i < listAdapter.getCount(); i++) {
      View listItem = listAdapter.getView(i, null, listView);
      listItem.measure(0, 0);
      totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
  }
}

您只需通过.setAdapter()设置适配器,然后致电ScrollingListView.setListViewHeightBasedOnChildren(your_listview)。这应该相应地将窗口重新设置为ListView高度。

----编辑----

这可能是最丑陋的解决方法,但请尝试执行以下操作:

ScrollView sv = (ScrollView) findViewById(R.id.your_scrollview);
sv.setEnabled(false);
// Populate your ListView
sv.setEnabled(true);

答案 2 :(得分:3)

  

在列表中添加项目之前只做一件事

listview.setFocusable(false);
  

之后你可以再次那样做

listview.setFocusable(true);
  

如果需要,它肯定会起作用

答案 3 :(得分:2)

将所有内容添加到header作为列表视图。

现在我看到了代码..你只能在scrollview中有一个ViewGroup。所以你会把两个布局变成另一个布局,但是ListView会自动在其中有一个滚动视图,这样就不会真正起作用了。

所以你需要做的是使用ListActivity(片段)中的addHeader视图,并从另一个xml文件中激活活动中的LinearLayout1。

答案 4 :(得分:2)

添加:

android:transcriptMode="disabled"
列表中的

您不想滚动

From Android Docs

答案 5 :(得分:2)

无法在可滚动视图中创建可滚动视图。但是作为解决此问题的方法,并且只有在所有视图都被加载时此列表视图不会占用太多内存的情况下。你可以用这个

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class NonScrollableListView extends ListView {
    public NonScrollableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Do not use the highest two bits of Integer.MAX_VALUE because they are
        // reserved for the MeasureSpec mode
        int heightSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightSpec);
        getLayoutParams().height = getMeasuredHeight();
    }

}

再次,使用此解决方法

并不好

答案 6 :(得分:1)

我会将列表和其他布局包装在RelativeLayout而不是LinearLayout

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <include 
                layout="@layout/a" />

            <include 
                layout="@layout/b" />

            <include 
                layout="@layout/c" />

            <include 
                layout="@layout/d" />

        </LinearLayout>

        <ListView
            android:id="@+id/listview"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/container" />

    </RelativeLayout>
</ScrollView>

这样,ListView的顶部边框位于LinearLayout的底部边框,并始终位于其他所有位置。

您无法将包含直接放在RelativeLayout中!有关详细信息,请参阅here

答案 7 :(得分:1)

我在xml文件中进行了2或3次更改

<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" 
        android:padding="10dp">  // This will let you see the scroll bar of list view
                                    when you scroll your list view.

        <include 
            layout="@layout/a" />
        <include 
            layout="@layout/b" />
        <include 
            layout="@layout/c" />
        <include 
            layout="@layout/d" />


    <ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="300dp" />// Instead of wraping up your list, if you wish
                                       you can give certain height to your list view.

    </LinearLayout>
</ScrollView>

您需要的另一件事是在java文件中编写给定的代码。

   onCreate()
  {
   ....
   ScrollView sView=(ScrollView)findViewById(R.id.tvscrollview);

   yourListView.setOnTouchListener(new OnTouchListener()
    {
        public boolean onTouch(View arg0, MotionEvent arg1) 
        {
            if(arg1.getAction() == MotionEvent.ACTION_DOWN ||   arg1.getAction() == MotionEvent.ACTION_MOVE)
            {
                sView.requestDisallowInterceptTouchEvent(true);
            }
            return false;
        }
    });

我希望这会对你有所帮助。

答案 8 :(得分:1)

您可能希望通过以下方式实现此目的:

 <LinearLayout 
......>
<ScrollView
    android:id="@+id/tvscrollview"
    android:layout_marginTop="8.0dip" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <include 
            layout="@layout/a" />

        <include 
            layout="@layout/b" />

        <include 
            layout="@layout/c" />

        <include 
            layout="@layout/d" />

    </LinearLayout>
</ScrollView>
<ListView
    android:id="@+id/listview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
 </LinearLayout>

将listview包装在scrollview之外,而不是在scrollview中,因为你不应该使用带有ListView的ScrollView,因为ListView负责自己的垂直滚动。最重要的是,这样做会使ListView中的所有重要优化都无法处理大型列表,因为它有效地强制ListView显示其整个项目列表以填充ScrollView提供的无限容器。

Source Android Docs

答案 9 :(得分:0)

唯一对我有用的解决方案是添加 EditText 作为布局的第一个子项。我知道,丑陋。

var match = reg.exec(text);
// ["ARCHIVE: KxhASjx0000-4", "KxhASjx0000-4"]

答案 10 :(得分:0)

我遇到了同样的问题,我在设置适配器后,通过更改XML中列表视图的可见性找到了解决方案,我将可见性更改为可见

var numbers = [2,4,34,6,33,1,67,20]


var numbersSorted = numbers.sort( { (first, second ) -> Bool in

    return first < second
})

答案 11 :(得分:0)

虽然这是对这个问题的一个非常晚的答案,而且这个答案已经得到了一个公认的答案,但我认为我在这里解决问题的方法可能会帮助其他人在单个SO线程中找到与此问题相关的所有内容。

所以我的情况就是这样:我在布局结束时有一个ScrollViewListView。我知道这是一个非常糟糕的做法。通过将标题附加到ListView,我可以实现我想要的相同行为。但无论如何,我的ListView在填充数据时得到了焦点,页面自动滚动到ListView开始的底部。

我在这里尝试了接受的答案,但它对我没有用。我尝试在布局顶部使用虚拟EditText,以便它可以自动请求焦点,但它也没有工作。因为ListView在从REST Api调用加载数据后获得了焦点。

然后我找到了this answer,这确实有帮助。所以我想把它放在这里,以便其他人可以从像我这样有同样问题的单个线程中获得帮助。

mainScrollView.fullScroll(ScrollView.FOCUS_UP);对我来说不起作用,因为在填充其他视图后填充了列表。因此,在填充ScrollView后,我必须将ListView滚动到顶部。所以我在这里解决了我的问题。

mScrollView.setEnabled(false);
mIntroducerListView.setFocusable(false);
mListAdapter.notifyDataSetChanged();

// Force scroll to the top of the scroll view.
// Because, when the list view gets loaded it focuses the list view
// automatically at the bottom of this page.
mScrollView.smoothScrollTo(0, 0);

答案 12 :(得分:0)

我尝试了上述答案,但都没有奏效。以下是我的最终解决方案。 只需覆盖 onFinishInflate 方法,然后发一个帖子到scrollTo(0,0)。

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
        this.post(new Runnable() {
            @Override
            public void run() {
                scrollTo(0, 0);
            }
        });
}