ScrollView 不使用包含 Android 中动态内容的 LinearLayout 滚动
Posted
技术标签:
【中文标题】ScrollView 不使用包含 Android 中动态内容的 LinearLayout 滚动【英文标题】:ScrollView not scrolling with LinearLayout that contains dynamic content in Android 【发布时间】:2013-07-15 07:51:42 【问题描述】:我在 ScrollView 中有一个 LinearLayout。我的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical" >
<TextView
android:id="@+id/degree_planner_step2_title"
style="@style/standard_text_view_appearance"
android:layout_
android:layout_ />
<View
android:id="@+id/degree_planner_divider"
android:layout_
android:layout_
android:background="@color/Science" />
<ScrollView
android:id="@+id/sv"
android:layout_
android:layout_
android:background="@color/Commerce"
android:fillViewport="true">
<LinearLayout
android:id="@+id/degreeplanner2_lin_layout"
android:layout_
android:layout_
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
</LinearLayout>
添加我的 ListViews 后,如果 fillViewPort 为 true,它会扩展所有内容,但是最后一个可见的 listview,“第 3 年”在其自身内部是可滚动的,而不是整个线性布局本身。当我检查 DDMS 时,它显示滚动视图不可滚动。如果 fillViewport 为 false,我在 LinearLayout 中的所有列表视图都会缩小并变成一个高且可滚动的项目。我试图让我的列表完全展开,并且在溢出时滚动视图应该滚动线性布局,而不是使列表视图中的单个项目滚动。有人可以帮忙吗?
可以在此处找到图片:http://i.stack.imgur.com/frU0P.png
在上面的屏幕截图中,fillViewPort = false,所有列表视图都缩小到一个项目高并且每个都可以单独滚动,存在 3 个列表视图。
这是我的片段代码,为简单起见,我已经用字母的简单数据加载了我的列表视图,动态添加列表视图的方法是 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();
【问题讨论】:
【参考方案1】:这里的问题是您在 ScrollView 中添加 ListView。这是来自文档的引用
您永远不应该将 ScrollView 与 ListView 一起使用,因为 ListView 负责自己的垂直滚动。最重要的是,这样做会破坏 ListView 中处理大型列表的所有重要优化,因为它有效地强制 ListView 显示其整个项目列表以填充 ScrollView 提供的无限容器。
所以你只需要添加没有 ListView 的项目。
【讨论】:
我想我必须将它添加为按钮,但是如果数据集需要动态更改,那将是非常有问题的。 但在您当前的版本中,您仅将 ListView 添加为包装器。事实上,你也可以尝试只使用带有页脚和页眉的 ListView,然后你会在顶部和底部有一些静态内容,而在列表视图中则是动态的。 谢谢。我决定改用 AmazingListView 来创建多个列表的外观。【参考方案2】:您可以改用RecyclerView
。请注意,如果您确实使用它,则必须对适配器进行更改,因为 RecyclerView
需要 RecyclerView.Adapter
作为适配器。
RecyclerView
它可以滚动,感觉就像 ListView 一样。
编辑:我忘了提到您需要确保在 onBindViewHolder
运行时不要运行 notifyDataSetChanged()
。它一直循环运行。或者您可以使用notifyItemInserted(int position)
和notifyItemRemoved(int position)
通知适配器刷新它。
notifyItemInserted 和 notifyItemRemoved。
【讨论】:
以上是关于ScrollView 不使用包含 Android 中动态内容的 LinearLayout 滚动的主要内容,如果未能解决你的问题,请参考以下文章
Android:ScrollView包含两个嵌套的ConstraintLayout,无法水平填满屏幕
Android学习-滚动视图ScrollView和HorizontalScrollView