Android - 制作一个包含可滚动ListView的LinearLayout

6
我知道大家都建议我们不要同时使用ListViewScrollView,我完全同意。但是,我目前遇到了一个非常简单的模式,就像8tracks的个人资料页面(如下图所示),包括用户资料区域和他们制作的混音列表。所以基本上,希望用户可以向下滚动该页面,这意味着个人资料部分会出现在屏幕顶部并逐渐消失,与此同时下面的列表也会滚动:

enter image description here

然而,目前我只能在LinearLayout中包含一个ListView,就像我在这里画的那样。

enter image description here

采用这种设计,我只能向下滚动列表,而个人资料区域停留在原地,这很烂。所以我正在寻找任何想法使整个页面可滚动,而不仅仅是列表。请帮帮我,谢谢。

编辑:对于我的误导性问题,我感到抱歉。我的问题更加复杂,因为选项卡的内容不仅仅是ListView - 有些选项卡包含LinearLayoutGridView。再次强调,我想实现的是整个页面可滚动,但是使用ScrollView无法解决问题,因为如果一个选项卡的内容是ListViewGridView,这些视图将被折叠,并且更重要的是 - 这违反了设计规则。

4个回答

1
我知道有点晚了,但我是8tracks的现任开发者。你上面展示的(旧的)2.x应用正在被重写,但我可以向你展示旧开发人员为个人资料页面所做的工作。
在进入之前,我必须说这不是最好的方法,但8tracks应用程序(2.x)已经老旧了。
回到代码本身... ProfileActivity 包含一个 ProfileFragment
你看到的主要布局包括关注按钮(和个人资料图片)如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- Image, name, location -->

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dip" >

        <com.gdub.widget.ImageViewClickable
            android:id="@+id/dj_avatar"
            android:layout_width="110dip"
            android:layout_height="110dip"
            android:layout_marginRight="10dip"
            android:background="@drawable/default_avatar_max200"
            android:scaleType="centerCrop" />

        <com.gdub.widget.CollapsingTextView
            android:id="@+id/dj_location"
            style="@style/mix.counts"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dip"
            android:layout_toRightOf="@id/dj_avatar" />

        <ViewSwitcher
            android:id="@+id/profile_action_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/dj_location"
            android:layout_toRightOf="@id/dj_avatar" >

            <Button
                android:id="@+id/follow_btn"
                style="@style/white_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/follow" />

            <Button
                android:id="@+id/edit_profile_btn"
                style="@style/white_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/edit_profile" />
        </ViewSwitcher>
    </RelativeLayout>

    <TextView
        android:id="@+id/dj_bio"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="-25dip"
        android:gravity="left|center_vertical"
        android:lineSpacingExtra="2dip"
        android:paddingLeft="10dip"
        android:paddingRight="10dip"
        android:textColor="@color/default_text"
        android:textSize="15sp" />

    <include
        android:id="@+id/profile_tabs"
        layout="@layout/profile_tabs" />

</LinearLayout>

并且 profile_tabs...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:visibility="gone"
  android:orientation="horizontal">

    <include
        android:id="@+id/profile_mixes_button"
        layout="@layout/profile_tab" />

    <include
        android:id="@+id/profile_followers_button"
        layout="@layout/profile_tab"  />

    <include
        android:id="@+id/profile_following_button"
        layout="@layout/profile_tab"  /> 

</LinearLayout>

所以你可以看到这是一个常规布局,带有三个“模拟”选项卡按钮。
选项卡的内容也由ViewSwitcher确定:
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/profile_view_switcher"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:inAnimation="@anim/fade_in_300"
              android:outAnimation="@anim/fade_out_300"
              android:background="@color/white">

<include
    android:id="@+id/profile_loading"
    layout="@layout/loading_view_full" />

<ListView
    android:id="@+id/profile_content_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:cacheColorHint="#00000000"
    android:divider="@null"
    android:dividerHeight="0dip"
    android:fadingEdge="none" />

</ViewSwitcher>

这显示一个加载轮并切换到列表视图。没有其他可滚动的ViewGroup。

基本上就是这样。

如果您想让整个屏幕都可以滚动,则需要使用自定义适配器,并将上述布局设置为标题(或者至少在适配器中巧妙地使用getItemType)。这样整个屏幕就成为了列表(具有列表的所有优化)。

我们在正在开发的新版8tracks应用程序中(滥用)它。;)


1
能够得到作者的回答真是太棒了!这太聪明了,我非常感激。虽然我已经完成了我的项目(放弃使用头部),但我相信这对我将来(以及其他人)会很有用!非常感谢。 - huong

0

尝试在您的列表视图上使用以下内容。

listview.addHeaderView(v);

还要记得,在调用listview的setAdapter()方法之前,必须先调用此方法。

将包含用户详细信息和选项卡的LinearLayout添加为列表的标题。


真遗憾我以前没学过这个,所以感谢您启蒙。但可悲的是这也不适合我的需求,因为实际上只有一个选项卡包含一个 ListView,而其他选项卡包含 GridView 和 LinearView,因此我必须将它们每个作为片段添加到选项卡中,而不能将选项卡作为 ListView 的头部添加。 - huong

0
根据UI指南和最佳实践,建议不要在ScrollView中使用可滚动内容,这样做会阻止可滚动内容的滚动。
当您放置两个ScrollView时,Android会混淆哪个ScrollView被触摸。因此,有时它无法传递触摸事件。
但是,如果仍然想要实现滚动功能,可以通过使用特定视图的onTouch事件来管理它。并且您需要相应地设计您的布局。
但是,即使要求您制作这样的布局。试试这个……
假设情况是这样的……
  <ScrollView android:id=”@+id/parent_scroll” 
        android:layout_width=”fill_parent”
        android:layout_height=”wrap_content”
        android:layout_weight=”1″
        android:background=”@drawable/dotted_bg”
        android:focusableInTouchMode=”false”>
                    <LinearLayout   />
                    <LinearLayout   />
                    <LinearLayout  >
                    <ScrollView android:id=”@+id/child_scroll”  
                    android:layout_width=”fill_parent”
                    android:layout_height=”fill_parent”
                    android:background=”@drawable/text_box_bg”>
                <TextView android:id=”@+id/text_description”
                    android:layout_width=”fill_parent”
                    android:layout_height=”fill_parent”
                    android:textColor=”@color/gray”
                    android:textSize=”12dip”
                    android:padding=”5dip”
                    android:scrollbars=”vertical”/>
                <!–ScrollView>
              </LinearLayout>

步骤1:为两个滚动视图提供唯一的ID。

步骤2:在您的活动中获取这两个滚动视图的引用。

  parentScroll=(ScrollView)findViewById(R.id.parent_scroll);
    childScroll=(ScrollView)findViewById(R.id.child_scroll);

步骤三:现在为两者设置触摸监听器。

  parentScroll.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                Log.v(TAG,”PARENT TOUCH”);
  findViewById(R.id.child_scroll).getParent().requestDisallowInterceptTouchEvent(false);
                return false;
            }
        });
        childScroll.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) 
            {
                Log.v(TAG,”CHILD TOUCH”);
                                    // Disallow the touch request for parent scroll on touch of child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });

希望对你有所帮助。


谢谢您提供详细的答案,但我认为您误解了我的问题(也许这是因为标题有些误导)。我想要实现的是能够滚动整个页面,而不仅仅是页面的一部分,因此禁用父级滚动以使子级可滚动就像在LinearLayout中添加ListView一样,这对我来说并不理想。 - huong
你想要实现什么?你想让你的ListView和整个布局都可以滚动吗? - GrIsHu
我刚刚编辑了我的问题和标题,请查看一下。如果您有更好的设计建议,我将非常感激。 - huong

0
你可以尝试将个人资料和选项卡作为列表视图的标题,然后在按下选项卡时更新列表视图的内容。不过我不知道你是否希望在滚动时选项卡消失。

这对我来说有点困惑,因为并不是所有的选项卡都包含一个列表视图。如果第一个选项卡有一个LinearLayout而其他两个选项卡只有ListView,那我该怎么办? - huong

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