简体   繁体   中英

Android - Make a LinearLayout which contains a ListView scrollable

I know that everyone's recommended that we should never use ListView and ScrollView together, and I totally agree. However, I'm currently stuck with a very simple pattern like 8tracks' profile page (as shown in the image below), which include an area for the user profile and a list of mixes they made. So basically, it's desirable that users can just scroll down that page, which means the profile part will get on top of the screen and gradually out of view, and at the same time the below list is scrolled too:

在此输入图像描述

However, at the moment, all I can do is to include a ListView within a LinearLayout , just like my sketch here.

在此输入图像描述

With this design, I can only scroll the list down, while the profile area stays at the same place, which sucks. So I'm looking for any idea to make the whole page scrollable, not just the list. Please help and thanks.

EDITED : I'm sorry for the misleading question. My problem is even more complicated because the content of the tabs are not just ListView - some tab contains LinearLayout or GridView instead. Again, what I want to achieve is to make the whole page scrollable, but ScrollView can't help because if the content of a tab is a ListView or GridView , these views will be collapsed and more importantly - this goes against the design rule.

I know this is late, but I'm the current developer for 8tracks. The (old) 2.x app you have shown above is being rewritten, but I can show you what the old dev did for the profile page.

Before going into that I must say that this is not the best way to do this, but the 8tracks app (2.x) is old.

So back to the code… The ProfileActivity contains a ProfileFragment .

The main layout you see with the Follow button (and the profile image) is this:

<?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>

And 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>

So as you can see it's a regular layout with three buttons "simulating" tabs.

The contents of the tabs is also dictated by a 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>

That shows a loading wheel and then switches to the listview. There is no other scrollable ViewGroup.

And that's basically it.

Now if you wanted to make the WHOLE thing scroll, then you need to use a custom adapter and set the above layout as the Header (or at least use getItemType in the adapter in a clever way). That way the whole screen is a List (with all the optimizations a list has).

We (ab)use this in the new 8tracks App under dev. ;)

Try to use the following on your listview.

listview.addHeaderView(v);

Also rememeber, you must call this method before calling setAdapter() on your listview.

include your linearlayout where you have the user details and the tabs and add it as a header to the list.

You can try to make the profile and the tabs the header of the listview, then updating the contents of the listview when the tabs are pressed. I don't know if you want the tabs to disappear from view as you scroll, though.

According to the UI guide lines and best practices, it is advisable not to use Scrollable content inside Scrollview and doing that prevents the scrolling of the Scrollable content.

When you put two scrollview android just get confused which scroll view is touched. So sometimes it gets unable to deliver touch event.

But if still you want to achieve the scrolling functionality you can manage it by using the onTouch event of the particular view. And you need to design your layout accordingly.

But even if the requirement forces you to make such layouts. Try this…

Say case is somewhat like this….

  <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>

Step 1 : Provide unique id to both the scrollview.

Step 2 : get reference of that two scrollview in your activity.

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

Step 3: Now set touch listeners for both.

  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; } }); 

I hope it will help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM