user1950087
user1950087

Reputation: 11

ScrollView not scrolling with LinearLayout that contains dynamic content in Android

I have a LinearLayout inside a ScrollView. My layout is as follows:

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

    <TextView
        android:id="@+id/degree_planner_step2_title"
        style="@style/standard_text_view_appearance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <View
        android:id="@+id/degree_planner_divider"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/Science" />

    <ScrollView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/Commerce"
        android:fillViewport="true">

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

Upon adding my ListViews, if fillViewPort is true it expands everything, however the last listview visible, 'year 3' is scrollable within itself and not the whole linear layout itself. When I check the DDMS it displays that the scrollview is not scrollable. If fillViewport is false all my listviews within the LinearLayout shrink and become one item tall and scrollable. I'm trying to have my lists fully expand and upon overflow the scrollview should scroll the linearlayout and not make the individual items in the list view scroll. does anyone able to help?

an image can be found here: https://i.sstatic.net/frU0P.png

In the above screenshot fillViewPort = false, all listviews shrink to one item tall and each individually scrollable, there are 3 listviews present.

here is my fragment code, for simplicity i have loaded my listview with simple data of the alphabet letters, the method where the listViews are added dynamically is notifyCourseDataSetChange():

import java.io.IOException;
import java.util.ArrayList;

import org.holoeverywhere.widget.Toast;

import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import com.actionbarsherlock.app.SherlockFragment;
import com.example.u2.R;
import com.example.u2.constantsandprocesses.Course;
import com.example.u2.constantsandprocesses.DatabaseHelper;
import com.example.u2.constantsandprocesses.DegreeYear;
import com.example.u2.constantsandprocesses.ScienceDegreePlan;
import com.example.u2.constantsandprocesses.UCT_Constants;
import com.example.u2.constantsandprocesses.DegreePlan;

public class DegreePlannerStep2Fragment extends SherlockFragment {
    private LinearLayout baseLayout;
    private DatabaseHelper DBHelper;
    private String faculty;
    private String degree;
    private String degreeAbbrev;
    private String major1;
    private String major2;
    private DegreePlan plan;
    private TextView title;
    private View divider;
    private int facultyColour;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedPreferences sp = getActivity().getSharedPreferences(UCT_Constants.PREFS_DEGREE, 0);
        faculty = sp.getString("faculty", null);
        degree = sp.getString("degree", null);
        degreeAbbrev = sp.getString("degreeAbbrev", null);
        major1 = sp.getString("major1", null);
        major2 = sp.getString("major2", null);
        setRetainInstance(true);
        if (savedInstanceState == null){
            DBHelper = new DatabaseHelper(getActivity());
            try {
                Log.d("DPS2", "connecting to db");
                DBHelper.connectDataBase();
            } catch (IOException e) {
                e.printStackTrace();
            }
            new GetAllCourses().execute(new String [] {major1, major2, faculty});
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.degree_planner_step_2, container, false);
        if (faculty!=null){
            facultyColour = selectColour(faculty);
            baseLayout = (LinearLayout) view.findViewById(R.id.degreeplanner2_lin_layout);
            title = (TextView) view.findViewById(R.id.degree_planner_step2_title);
            title.setText(degree);
            divider = view.findViewById(R.id.degree_planner_divider);
            divider.setBackgroundResource(facultyColour);
        }
        return view;
    }

    @Override
    public void onPause() {
        super.onPause();
        DBHelper.close();
    }

    @Override
    public void onResume() {
        super.onResume();
        //open database connection
        try {
            Log.d("DPS2", "opening db");
            DBHelper.connectDataBase();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * returns the id (int) of the colour variable for the faculty
     */
    private int selectColour(String facultyName) {
        String [] faculties = getActivity().getResources().getStringArray(R.array.faculties);
        if (facultyName.equals(faculties[0])){
            return R.color.Commerce;
        }else if(facultyName.equals(faculties[1])){
            return R.color.EBE;
        }else if(facultyName.equals(faculties[2])){
            return R.color.Health_Sciences;
        }else if(facultyName.equals(faculties[3])){
            return R.color.Humanities;
        }else if (facultyName.equals(faculties[4])){
            return R.color.Law;
        }else{
            return R.color.Science;
        }
    }

    public void notifyCourseDataSetChange(){
        for (DegreeYear dy : plan.getDegreeYears()){
            if (dy.isActive()){
                LayoutInflater inflater = getActivity().getLayoutInflater();
                View sectionHeader = inflater.inflate(R.layout.listview_section_header, null);
                ((TextView)sectionHeader.findViewById(R.id.section_header_title)).setText("Year "+dy.getYear());        //section header title
                sectionHeader.findViewById(R.id.section_header_divider).setBackgroundResource(facultyColour);   //section header divider
                ListView lv = new ListView(getActivity());
                lv.setHeaderDividersEnabled(false);
                lv.addHeaderView(sectionHeader);
                lv.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.drawer_list_item,new String [] {"a","b","c","d"}));
                baseLayout.addView(lv);
            }
        }
    }

    private class GetAllCourses extends AsyncTask<String, Void, ArrayList<Course>>{
        String facultyName = "";

        @Override
        protected ArrayList<Course> doInBackground(String... params) {
            facultyName = params[2];
            return DBHelper.getCoursesForMajor(params[0], params[1]);
        }

        @Override
        protected void onPostExecute(ArrayList<Course> result) {
            super.onPostExecute(result);
            String [] faculties = getActivity().getResources().getStringArray(R.array.faculties);
            if (facultyName.equals(faculties[0])){          //COM
                //TODO create corresponding degree
            }else if(facultyName.equals(faculties[1])){     //EBE
                //TODO create corresponding degree
            }else if(facultyName.equals(faculties[2])){     //Health
                //TODO create corresponding degree
            }else if(facultyName.equals(faculties[3])){     //HUM
                //TODO create corresponding degree
            }else if (facultyName.equals(faculties[4])){    //LAW
                //TODO create corresponding degree
            }else{                                          //SCI
                plan = new ScienceDegreePlan(result);
            }
            notifyCourseDataSetChange();
        }

    }
}

Upvotes: 1

Views: 1570

Answers (2)

Rithik Kumar
Rithik Kumar

Reputation: 49

You can use RecyclerView instead. Note that if you do use it, you must make changes to your adapter as RecyclerView requires RecyclerView.Adapter as the adapter.

RecyclerView

It scrolls and feels just like a ListView would, too.

EDIT: I forgot to mention that you need to make sure that you DO NOT run notifyDataSetChanged() while onBindViewHolder is running. It keeps running in a loop. OR you can use notifyItemInserted(int position) and notifyItemRemoved(int position) to notify the Adapter to refresh it. notifyItemInserted and notifyItemRemoved.

Upvotes: 0

Desert
Desert

Reputation: 2303

The problem here is that you are adding ListView inside a ScrollView. Here is a quote from documentation

You should never use a ScrollView with a ListView, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.

So you need to add only your items without ListView.

Upvotes: 1

Related Questions