Horizo​​ntalScrollView中的ListView - 在setSelection()之后调用了太多次getView()

时间:2014-03-05 14:36:04

标签: android android-listview horizontalscrollview

大家好,谢谢你的时间。我希望,有人能够帮助解决我的问题。我被困了。

目标: 我试图用两个ListViews进行布局,它们一起滚动(下面的代码) - 如果用户首先滚动ListView,第二个也滚动,如果用户滚动第二个ListView,首先也是滚动。与他们同步是没有问题的。这是我使用的syncer代码。

class ListScrollSyncer implements OnScrollListener, OnTouchListener {

    private Set<ListView> listSet = new HashSet<ListView>();
    private ListView currentTouchSource;

    private int currentOffset = 0;
    private int currentPosition = 0;

    public void addList(ListView list) {
        listSet.add(list);
        list.setOnTouchListener(this);
        list.setSelectionFromTop(currentPosition, currentOffset);
    }

    public void removeList(ListView list) {
        listSet.remove(list);
    }

    public boolean onTouch(View view, MotionEvent event) {
        ListView list = (ListView) view;

        if (currentTouchSource != null) {
            currentTouchSource.setOnScrollListener(null);
        }
        currentTouchSource = list;
        currentTouchSource.setOnScrollListener(this);


        return false;
    }

    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        scrollToPosition();
    }

    private void scrollToPosition() {
        if (currentTouchSource.getChildCount() > 0) {
            currentPosition = currentTouchSource.getFirstVisiblePosition();
            currentOffset   = currentTouchSource.getChildAt(0).getTop();
        }
        Iterator<ListView> it = listSet.iterator();
        while (it.hasNext()) {
            ListView list = it.next();
            if (list == currentTouchSource) {
                continue;
            }
            list.setSelectionFromTop(currentPosition, currentOffset);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE && currentTouchSource != null) {
            scrollToPosition();
            currentTouchSource.setOnScrollListener(null);
            currentTouchSource = null;
        }
    }   
}

问题: ListView之一位于Horizo​​ntalScrollView中。两个方向都可以正常工作,但是当我为此ListView调用方法setSelection()或setSelectionFromTop()时,在每个setSelection *()方法之后调用位置为0的getView(),这会导致实际的性能问题。

问题:在调用setSelection *()之后,如何避免在Horizo​​ntalScrollView中重复测量ListView?

我发现了什么

  • 如果将ListView放在FrameLayout中,一切正常。问题仅在于它在Horizo​​ntalScrollView中。我想,reuqestLayout()可能有问题,所以我使用了Horizo​​ntalScrollView并使用了父亲的requestLayout() - Horizo​​ntalScrollView的父亲是FrameLayout,但这也没有用,我没有更多的想法,可能在哪里问题

  • 我知道,或者至少我认为,在requestLayout之后从Horizo​​ntalScrollView请求ListView的大小存在问题,但我不知道。

  • 为layout_width和layout_height设置的wrap_content / match_parent / fixed_size_in_dp无效。

感谢您的时间和帮助。

更新1 添加了布局

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
>

    <!-- First cell -->
    <FrameLayout 
        android:id="@+id/first_cell"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    />

    <View
        android:id="@+id/first_col_divider"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_toRightOf="@id/first_cell"
    />

    <View
        android:id="@+id/header_divider"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_below="@id/first_cell"
    />


    <!-- Header -->
    <com.peterbucko.android.example.fixedheaderstable.SyncedHorizontalScrollView
        android:id="@+id/header_scroll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/first_col_divider"
    >

        <LinearLayout
            android:id="@+id/header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
        />

    </com.peterbucko.android.example.fixedheaderstable.SyncedHorizontalScrollView>

    <ListView 
        android:id="@+id/first_col"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/header_divider"
        android:layout_alignRight="@id/first_cell"
    />


    <com.peterbucko.android.example.fixedheaderstable.SyncedHorizontalScrollView 
        android:id="@+id/content_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/header_divider"
        android:layout_toRightOf="@id/first_col_divider"
        android:fillViewport="true"
    >

        <ListView
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" 
       />


    </com.peterbucko.android.example.fixedheaderstable.SyncedHorizontalScrollView>



</RelativeLayout>

注意:SyncedHorizo​​ntalScrollView是Horizo​​ntalScrollView,带有用于滚动的侦听器,因此我可以同步两个Horizo​​ntalScrollView的水平滚动。

更新2 我尝试使用此布局创建简约项目

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
>

    <ListView
        android:id="@+id/list1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"    
    />

    <ListView
        android:id="@+id/list2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#FF00ff00"    
    />    

</LinearLayout>

使用此布局时,两个ListView都存在问题 - 两者都在setSelection *()之后重新测量。但是布局

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
>

    <ListView
        android:id="@+id/list1"
        android:layout_width="100dp"
        android:layout_height="match_parent"
    />

    <ListView
        android:id="@+id/list2"
        android:layout_width="110dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="100dp"
        android:background="#FF00ff00"    
    />    

</FrameLayout>

没有问题,并且在需要时调用getView - 应该显示新项目。

我可以想象,有一些机制可以为每个布局视图重新测量整个布局。所以这是一个问题。布局应该如何以及哪些视图应该用于我需要的结果?可能我可以创建一个自定义的FrameLayout,它的行为类似于Horizo​​ntalScrollView,但Horizo​​ntalScrollView已经是FrameLayout的后代。

0 个答案:

没有答案