我有一个android布局,其中有一个带有许多元素的scrollView。在scrollView的底部,我有一个listView,然后由适配器填充。
我遇到的问题是,android是排除listView从scrollView作为scrollView已经有一个可滚动的功能。我希望listView和内容一样长,并且主滚动视图是可滚动的。
我怎样才能实现这种行为呢?
这是我的主要布局:
<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:fillViewport="true"
android:gravity="top" >
<LinearLayout
android:id="@+id/foodItemActvity_linearLayout_fragments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
然后,我以编程方式将我的组件添加到linearlayour的id: foodItemActvity_linearLayout_fragments。下面是加载到线性布局中的一个视图。就是这个给我的卷轴带来了麻烦。
<?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:orientation="vertical" >
<TextView
android:id="@+id/fragment_dds_review_textView_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reviews:"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ListView
android:id="@+id/fragment_dds_review_listView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
我的适配器然后填充这个列表视图。
当我点击主scrollView时,这是一个来自android层级查看器的图像:
如您所见,它排除了评论列表视图。
我应该能够向下滚动页面,看到8个评论,但它只显示了这3个,我可以滚动评论所在的一小部分。我想要一个全局页面滚动
如果出于某种原因你不想使用addHeaderView和addFooterView,例如当你有几个列表时,一个好主意是重用ListAdapter来填充一个简单的线性布局,这样就没有滚动功能了。
如果你已经从ListFragment中获得了一个完整的片段,并且想用简单的线性布局将其转换为一个类似的片段,而不需要滚动(例如,将它放在ScrollView中),你可以像这样实现一个适配器片段:
// converts listFragment to linearLayout (no scrolling)
// please call init() after fragment is inflated to set listFragment to convert
public class ListAsArrayFragment extends Fragment {
public ListAsArrayFragment() {}
private ListFragment mListFragment;
private LinearLayout mRootView;
// please call me!
public void init(Activity activity, ListFragment listFragment){
mListFragment = listFragment;
mListFragment.onAttach(activity);
mListFragment.getListAdapter().registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
refreshView();
}
});
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// create an empty vertical LinearLayout as the root view of this fragment
mRootView = new LinearLayout(getActivity());
mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mRootView.setOrientation(LinearLayout.VERTICAL);
return mRootView;
}
// reusing views for performance
// todo: support for more than one view type
ArrayList<View> mViewsToReuse = new ArrayList<>();
ArrayList<View> mCurrentViews = new ArrayList<>();
// re-add views to linearLayout
void refreshView(){
// remove old views from linearLayout and move them to mViewsToReuse
mRootView.removeAllViews();
mViewsToReuse.addAll(mCurrentViews);
mCurrentViews.clear();
// create new views
for(int i=0; i<mListFragment.getListAdapter().getCount(); ++i){
View viewToReuse = null;
if(!mViewsToReuse.isEmpty()){
viewToReuse = mViewsToReuse.get(mViewsToReuse.size()-1);
mViewsToReuse.remove(mViewsToReuse.size()-1);
}
final View view = mListFragment.getListAdapter().getView(i, viewToReuse, mRootView);
ViewGroup.LayoutParams oldParams = view.getLayoutParams();
view.setLayoutParams(new LinearLayout.LayoutParams(oldParams.width, oldParams.height));
final int finalI = i;
// pass click events to listFragment
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListFragment.onListItemClick(null, view, finalI, finalI);
}
});
mRootView.addView(view);
mCurrentViews.add(view);
}
}
你也可以根据你的需要转发onCreate, onPause, onResume等到原始片段或尝试继承而不是组合(但覆盖某些方法,因此原始片段实际上没有附加到布局层次结构);但是我想尽可能地分离原始片段,因为我们只需要提取它的ListAdapter。如果你在onAttach中调用原始片段的setListAdapter,这可能就足够了。
下面是如何使用ListAsArrayFragment包含OriginalListFragment而不滚动。在父活动的onCreate中:
ListAsArrayFragment fragment = (ListAsArrayFragment) getFragmentManager().findFragmentById(R.id.someFragmentId);
OriginalListFragment originalFragment = new OriginalListFragment();
fragment.init(this, originalFragment);
// now access originalFragment.getListAdapter() to modify list entries
// and remember to call notifyDatasetChanged()
在xml:
<com.example.util.NestedListView
android:layout_marginTop="10dp"
android:id="@+id/listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="@null"
android:layout_below="@+id/rl_delivery_type" >
</com.example.util.NestedListView>
在Java中:
public class NestedListView extends ListView implements View.OnTouchListener, AbsListView.OnScrollListener {
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
setOnTouchListener(this);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null, this);
//now it will not throw a NPE if listItem is a ViewGroup instance
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, 1);
}
}
return false;
}
}