不滚动的Android ListView?

16

我正在尝试制作一个布局,类似于Android市场的布局... 比如评论部分有一个类似于 ListView 的东西,但它不会滚动(整个页面可以滚动但评论部分不会)。我不确定它是否真的是 ListView,但我想要看起来像列表视图(即具有那些分隔条之类的东西,但不能滚动)。有人建议使用 LinearLayout 而不是 ListView,但我也希望这些项是可点击的并打开一个新的活动。请帮帮我?

我的当前布局树如下所示

<LinearLayout>
  <ScrollView>
     <RelativeLayout>

我想把内容放在RelativeLayout中。


现在的Support Library允许使用<NestedScrollView><RecyclerView>更加容易。NestedScrollView可以包含任何布局,其中包含多个简单或可循环利用的视图。 - Pavel
4个回答

30

正如这个 视频 中的程序员所解释的那样,不要将 ListView 放在 Scroll View 中。如果您的列表不应该滚动,请使用像线性布局这样的 ViewGroup,并在您的代码中使用循环将所有项添加到此 ViewGroup 中。如果您想让整个行可点击,您必须使用另一个 ViewGroup 作为每行的根节点,并将 OnClickListener 添加到此 View。

示例代码:

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

for (int current = 0; current < itemCount; current++) {
   View view = inflater.inflate(R.layout.layout_id, parent, false);

   //initialize the view

   view.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
          Intent intent = new Intent(getApplicationContext(), CLASS_TO_START)
          startActivity(intent);
      }
   });
   viewGroup.addView(view);
   if (current < itemCount - 1) {
      inflater.inflate(R.layout.line, viewGroup);
   }
}

这段代码将为您拥有的每个项目生成一个 View,并将其放入 viewGroup 中。在除最后一项之外的每个项目后,它还将向 viewGroup 添加分隔线。


1
谢谢 =) 在弄清楚LayoutInflater是什么以及如何使用之后,我最终采用了这种方法...现在我只需要在xml中美化一下东西就可以了。 - Kman
4
急问...我如何使视图在点击时高亮显示? - Kman
@Kman,我知道这是一篇老文章,但你知道如何在子视图被点击后将其突出显示吗? - Red M

14

我遇到了同样的问题。我只是通过添加一个setAdapter方法来扩展默认的LinearLayout:

public class LinearListView extends LinearLayout
{
    Adapter adapter;
    Observer observer = new Observer(this);

    public LinearListView(Context context)
    {
        super(context);
    }

    public LinearListView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public LinearListView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    public void setAdapter(Adapter adapter)
    {
        if (this.adapter != null)
            this.adapter.unregisterDataSetObserver(observer);

        this.adapter = adapter;
        adapter.registerDataSetObserver(observer);
        observer.onChanged();
    }

    private class Observer extends DataSetObserver
    {
        LinearListView context;

        public Observer(LinearListView context)
        {
            this.context = context;
        }

        @Override
        public void onChanged()
        {
            List<View> oldViews = new ArrayList<View>(context.getChildCount());

            for (int i = 0; i < context.getChildCount(); i++)
                oldViews.add(context.getChildAt(i));

            Iterator<View> iter = oldViews.iterator();

            context.removeAllViews();

            for (int i = 0; i < context.adapter.getCount(); i++)
            {
                View convertView = iter.hasNext() ? iter.next() : null;
                context.addView(context.adapter.getView(i, convertView, context));
            }
            super.onChanged();
        }

        @Override
        public void onInvalidated()
        {
            context.removeAllViews();
            super.onInvalidated();
        }
    }
}
希望这可以帮助!

1
如果您在“LinearListView”中有很多项,由于行重用,这是一个不好的想法。 - PaNaVTEC
@PaNaVTEC:重复使用行有什么不好的?这也取决于适配器是否正在使用convertView,那又怎样? - Nappy
1
你的LinearListView没有重用行,这就是问题所在。listView只会显示可见的行,并且当你滚动时会重用这些行,因此你在内存中只有可见的行。而使用LinearlistView,你在适配器中填充的所有行都会在内存中。此外,我认为这是一个适用于小行集的不错解决方案。 - PaNaVTEC
2
您的解决方案完美地满足了我的当前需求。但是,当我实施它时,我只得到了适配器中添加的第一项。 - TrtG

3

我没有足够的声望点来发表评论,但对于那些在Nappy的解决方案中只有1个项目出现的人,请确保在您的布局文件中设置以下内容:

    android:orientation="vertical"

否则,看起来好像只添加了一个项目,但实际上它们只是水平地被添加了...希望这能帮助某人。

0
你可以创建一个 ListView 并将所有内容放入其中,这样整个页面就会滚动。你可以自己编写适配器实现,但我建议使用CommonsWare出色的 MergeAdapter。你可以使用 addView() 添加标签或分隔栏,使用 addAdapter() 添加列表。请查看页面以获取更多使用信息和演示项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接